Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Parse/ParsePragma.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file implements the language specific #pragma handlers.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/AST/ASTContext.h"
14
#include "clang/Basic/PragmaKinds.h"
15
#include "clang/Basic/TargetInfo.h"
16
#include "clang/Lex/Preprocessor.h"
17
#include "clang/Lex/Token.h"
18
#include "clang/Parse/LoopHint.h"
19
#include "clang/Parse/ParseDiagnostic.h"
20
#include "clang/Parse/Parser.h"
21
#include "clang/Parse/RAIIObjectsForParser.h"
22
#include "clang/Sema/Scope.h"
23
#include "llvm/ADT/ArrayRef.h"
24
#include "llvm/ADT/StringSwitch.h"
25
using namespace clang;
26
27
namespace {
28
29
struct PragmaAlignHandler : public PragmaHandler {
30
88.1k
  explicit PragmaAlignHandler() : PragmaHandler("align") {}
31
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
32
                    Token &FirstToken) override;
33
};
34
35
struct PragmaGCCVisibilityHandler : public PragmaHandler {
36
88.1k
  explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
37
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
38
                    Token &FirstToken) override;
39
};
40
41
struct PragmaOptionsHandler : public PragmaHandler {
42
88.1k
  explicit PragmaOptionsHandler() : PragmaHandler("options") {}
43
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
44
                    Token &FirstToken) override;
45
};
46
47
struct PragmaPackHandler : public PragmaHandler {
48
88.1k
  explicit PragmaPackHandler() : PragmaHandler("pack") {}
49
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
50
                    Token &FirstToken) override;
51
};
52
53
struct PragmaClangSectionHandler : public PragmaHandler {
54
  explicit PragmaClangSectionHandler(Sema &S)
55
88.1k
             : PragmaHandler("section"), Actions(S) {}
56
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
57
                    Token &FirstToken) override;
58
59
private:
60
  Sema &Actions;
61
};
62
63
struct PragmaMSStructHandler : public PragmaHandler {
64
88.1k
  explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
65
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
66
                    Token &FirstToken) override;
67
};
68
69
struct PragmaUnusedHandler : public PragmaHandler {
70
88.1k
  PragmaUnusedHandler() : PragmaHandler("unused") {}
71
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
72
                    Token &FirstToken) override;
73
};
74
75
struct PragmaWeakHandler : public PragmaHandler {
76
88.1k
  explicit PragmaWeakHandler() : PragmaHandler("weak") {}
77
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
78
                    Token &FirstToken) override;
79
};
80
81
struct PragmaRedefineExtnameHandler : public PragmaHandler {
82
88.1k
  explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
83
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
84
                    Token &FirstToken) override;
85
};
86
87
struct PragmaOpenCLExtensionHandler : public PragmaHandler {
88
793
  PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
89
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
90
                    Token &FirstToken) override;
91
};
92
93
94
struct PragmaFPContractHandler : public PragmaHandler {
95
88.1k
  PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
96
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
97
                    Token &FirstToken) override;
98
};
99
100
// Pragma STDC implementations.
101
102
/// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
103
struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
104
88.1k
  PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
105
106
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
107
79
                    Token &Tok) override {
108
79
    Token PragmaName = Tok;
109
79
    if (!PP.getTargetInfo().hasStrictFP() && 
!PP.getLangOpts().ExpStrictFP3
) {
110
3
      PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
111
3
          << PragmaName.getIdentifierInfo()->getName();
112
3
      return;
113
3
    }
114
76
    tok::OnOffSwitch OOS;
115
76
    if (PP.LexOnOffSwitch(OOS))
116
3
     return;
117
118
73
    MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
119
73
                                1);
120
73
    Toks[0].startToken();
121
73
    Toks[0].setKind(tok::annot_pragma_fenv_access);
122
73
    Toks[0].setLocation(Tok.getLocation());
123
73
    Toks[0].setAnnotationEndLoc(Tok.getLocation());
124
73
    Toks[0].setAnnotationValue(reinterpret_cast<void*>(
125
73
                               static_cast<uintptr_t>(OOS)));
126
73
    PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
127
73
                        /*IsReinject=*/false);
128
73
  }
129
};
130
131
/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
132
struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
133
88.1k
  PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
134
135
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
136
9
                    Token &Tok) override {
137
9
    tok::OnOffSwitch OOS;
138
9
    PP.LexOnOffSwitch(OOS);
139
9
  }
140
};
141
142
/// Handler for "\#pragma STDC FENV_ROUND ...".
143
struct PragmaSTDC_FENV_ROUNDHandler : public PragmaHandler {
144
88.1k
  PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {}
145
146
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
147
                    Token &Tok) override;
148
};
149
150
/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
151
struct PragmaSTDC_UnknownHandler : public PragmaHandler {
152
88.1k
  PragmaSTDC_UnknownHandler() = default;
153
154
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
155
2
                    Token &UnknownTok) override {
156
    // C99 6.10.6p2, unknown forms are not allowed.
157
2
    PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
158
2
  }
159
};
160
161
struct PragmaFPHandler : public PragmaHandler {
162
88.1k
  PragmaFPHandler() : PragmaHandler("fp") {}
163
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
164
                    Token &FirstToken) override;
165
};
166
167
struct PragmaNoOpenMPHandler : public PragmaHandler {
168
75.8k
  PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
169
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
170
                    Token &FirstToken) override;
171
};
172
173
struct PragmaOpenMPHandler : public PragmaHandler {
174
12.3k
  PragmaOpenMPHandler() : PragmaHandler("omp") { }
175
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
176
                    Token &FirstToken) override;
177
};
178
179
/// PragmaCommentHandler - "\#pragma comment ...".
180
struct PragmaCommentHandler : public PragmaHandler {
181
  PragmaCommentHandler(Sema &Actions)
182
37.8k
    : PragmaHandler("comment"), Actions(Actions) {}
183
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
184
                    Token &FirstToken) override;
185
186
private:
187
  Sema &Actions;
188
};
189
190
struct PragmaDetectMismatchHandler : public PragmaHandler {
191
  PragmaDetectMismatchHandler(Sema &Actions)
192
11.1k
    : PragmaHandler("detect_mismatch"), Actions(Actions) {}
193
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
194
                    Token &FirstToken) override;
195
196
private:
197
  Sema &Actions;
198
};
199
200
struct PragmaFloatControlHandler : public PragmaHandler {
201
  PragmaFloatControlHandler(Sema &Actions)
202
88.1k
      : PragmaHandler("float_control") {}
203
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
204
                    Token &FirstToken) override;
205
};
206
207
struct PragmaMSPointersToMembers : public PragmaHandler {
208
11.1k
  explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
209
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
210
                    Token &FirstToken) override;
211
};
212
213
struct PragmaMSVtorDisp : public PragmaHandler {
214
11.1k
  explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
215
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
216
                    Token &FirstToken) override;
217
};
218
219
struct PragmaMSPragma : public PragmaHandler {
220
100k
  explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
221
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
222
                    Token &FirstToken) override;
223
};
224
225
/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
226
struct PragmaOptimizeHandler : public PragmaHandler {
227
  PragmaOptimizeHandler(Sema &S)
228
88.1k
    : PragmaHandler("optimize"), Actions(S) {}
229
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
230
                    Token &FirstToken) override;
231
232
private:
233
  Sema &Actions;
234
};
235
236
struct PragmaLoopHintHandler : public PragmaHandler {
237
88.1k
  PragmaLoopHintHandler() : PragmaHandler("loop") {}
238
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
239
                    Token &FirstToken) override;
240
};
241
242
struct PragmaUnrollHintHandler : public PragmaHandler {
243
352k
  PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
244
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
245
                    Token &FirstToken) override;
246
};
247
248
struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
249
11.1k
  PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
250
};
251
252
struct PragmaMSIntrinsicHandler : public PragmaHandler {
253
11.1k
  PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
254
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
255
                    Token &FirstToken) override;
256
};
257
258
// "\#pragma fenv_access (on)".
259
struct PragmaMSFenvAccessHandler : public PragmaHandler {
260
11.1k
  PragmaMSFenvAccessHandler() : PragmaHandler("fenv_access") {}
261
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
262
11
                    Token &FirstToken) override {
263
11
    StringRef PragmaName = FirstToken.getIdentifierInfo()->getName();
264
11
    if (!PP.getTargetInfo().hasStrictFP() && 
!PP.getLangOpts().ExpStrictFP0
) {
265
0
      PP.Diag(FirstToken.getLocation(), diag::warn_pragma_fp_ignored)
266
0
          << PragmaName;
267
0
      return;
268
0
    }
269
270
11
    Token Tok;
271
11
    PP.Lex(Tok);
272
11
    if (Tok.isNot(tok::l_paren)) {
273
3
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
274
3
          << PragmaName;
275
3
      return;
276
3
    }
277
8
    PP.Lex(Tok); // Consume the l_paren.
278
8
    if (Tok.isNot(tok::identifier)) {
279
1
      PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
280
1
      return;
281
1
    }
282
7
    const IdentifierInfo *II = Tok.getIdentifierInfo();
283
7
    tok::OnOffSwitch OOS;
284
7
    if (II->isStr("on")) {
285
5
      OOS = tok::OOS_ON;
286
5
      PP.Lex(Tok);
287
5
    } else 
if (2
II->isStr("off")2
) {
288
2
      OOS = tok::OOS_OFF;
289
2
      PP.Lex(Tok);
290
2
    } else {
291
0
      PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
292
0
      return;
293
0
    }
294
7
    if (Tok.isNot(tok::r_paren)) {
295
1
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
296
1
          << PragmaName;
297
1
      return;
298
1
    }
299
6
    PP.Lex(Tok); // Consume the r_paren.
300
301
6
    if (Tok.isNot(tok::eod)) {
302
1
      PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
303
1
          << PragmaName;
304
1
      return;
305
1
    }
306
307
5
    MutableArrayRef<Token> Toks(
308
5
        PP.getPreprocessorAllocator().Allocate<Token>(1), 1);
309
5
    Toks[0].startToken();
310
5
    Toks[0].setKind(tok::annot_pragma_fenv_access_ms);
311
5
    Toks[0].setLocation(FirstToken.getLocation());
312
5
    Toks[0].setAnnotationEndLoc(Tok.getLocation());
313
5
    Toks[0].setAnnotationValue(
314
5
        reinterpret_cast<void*>(static_cast<uintptr_t>(OOS)));
315
5
    PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
316
5
                        /*IsReinject=*/false);
317
5
  }
318
};
319
320
struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
321
  PragmaForceCUDAHostDeviceHandler(Sema &Actions)
322
373
      : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
323
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
324
                    Token &FirstToken) override;
325
326
private:
327
  Sema &Actions;
328
};
329
330
/// PragmaAttributeHandler - "\#pragma clang attribute ...".
331
struct PragmaAttributeHandler : public PragmaHandler {
332
  PragmaAttributeHandler(AttributeFactory &AttrFactory)
333
88.1k
      : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
334
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
335
                    Token &FirstToken) override;
336
337
  /// A pool of attributes that were parsed in \#pragma clang attribute.
338
  ParsedAttributes AttributesForPragmaAttribute;
339
};
340
341
struct PragmaMaxTokensHereHandler : public PragmaHandler {
342
88.1k
  PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
343
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
344
                    Token &FirstToken) override;
345
};
346
347
struct PragmaMaxTokensTotalHandler : public PragmaHandler {
348
88.1k
  PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
349
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
350
                    Token &FirstToken) override;
351
};
352
353
1.74k
void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) {
354
1.74k
  for (auto &T : Toks)
355
43.3k
    T.setFlag(clang::Token::IsReinjected);
356
1.74k
}
357
}  // end namespace
358
359
88.1k
void Parser::initializePragmaHandlers() {
360
88.1k
  AlignHandler = std::make_unique<PragmaAlignHandler>();
361
88.1k
  PP.AddPragmaHandler(AlignHandler.get());
362
363
88.1k
  GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
364
88.1k
  PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
365
366
88.1k
  OptionsHandler = std::make_unique<PragmaOptionsHandler>();
367
88.1k
  PP.AddPragmaHandler(OptionsHandler.get());
368
369
88.1k
  PackHandler = std::make_unique<PragmaPackHandler>();
370
88.1k
  PP.AddPragmaHandler(PackHandler.get());
371
372
88.1k
  MSStructHandler = std::make_unique<PragmaMSStructHandler>();
373
88.1k
  PP.AddPragmaHandler(MSStructHandler.get());
374
375
88.1k
  UnusedHandler = std::make_unique<PragmaUnusedHandler>();
376
88.1k
  PP.AddPragmaHandler(UnusedHandler.get());
377
378
88.1k
  WeakHandler = std::make_unique<PragmaWeakHandler>();
379
88.1k
  PP.AddPragmaHandler(WeakHandler.get());
380
381
88.1k
  RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
382
88.1k
  PP.AddPragmaHandler(RedefineExtnameHandler.get());
383
384
88.1k
  FPContractHandler = std::make_unique<PragmaFPContractHandler>();
385
88.1k
  PP.AddPragmaHandler("STDC", FPContractHandler.get());
386
387
88.1k
  STDCFenvAccessHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
388
88.1k
  PP.AddPragmaHandler("STDC", STDCFenvAccessHandler.get());
389
390
88.1k
  STDCFenvRoundHandler = std::make_unique<PragmaSTDC_FENV_ROUNDHandler>();
391
88.1k
  PP.AddPragmaHandler("STDC", STDCFenvRoundHandler.get());
392
393
88.1k
  STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
394
88.1k
  PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
395
396
88.1k
  STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
397
88.1k
  PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
398
399
88.1k
  PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
400
88.1k
  PP.AddPragmaHandler("clang", PCSectionHandler.get());
401
402
88.1k
  if (getLangOpts().OpenCL) {
403
793
    OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
404
793
    PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
405
406
793
    PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
407
793
  }
408
88.1k
  if (getLangOpts().OpenMP)
409
12.3k
    OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
410
75.8k
  else
411
75.8k
    OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
412
88.1k
  PP.AddPragmaHandler(OpenMPHandler.get());
413
414
88.1k
  if (getLangOpts().MicrosoftExt ||
415
88.1k
      
getTargetInfo().getTriple().isOSBinFormatELF()76.9k
) {
416
37.8k
    MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
417
37.8k
    PP.AddPragmaHandler(MSCommentHandler.get());
418
37.8k
  }
419
420
88.1k
  FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);
421
88.1k
  PP.AddPragmaHandler(FloatControlHandler.get());
422
88.1k
  if (getLangOpts().MicrosoftExt) {
423
11.1k
    MSDetectMismatchHandler =
424
11.1k
        std::make_unique<PragmaDetectMismatchHandler>(Actions);
425
11.1k
    PP.AddPragmaHandler(MSDetectMismatchHandler.get());
426
11.1k
    MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
427
11.1k
    PP.AddPragmaHandler(MSPointersToMembers.get());
428
11.1k
    MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
429
11.1k
    PP.AddPragmaHandler(MSVtorDisp.get());
430
11.1k
    MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
431
11.1k
    PP.AddPragmaHandler(MSInitSeg.get());
432
11.1k
    MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
433
11.1k
    PP.AddPragmaHandler(MSDataSeg.get());
434
11.1k
    MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
435
11.1k
    PP.AddPragmaHandler(MSBSSSeg.get());
436
11.1k
    MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
437
11.1k
    PP.AddPragmaHandler(MSConstSeg.get());
438
11.1k
    MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
439
11.1k
    PP.AddPragmaHandler(MSCodeSeg.get());
440
11.1k
    MSSection = std::make_unique<PragmaMSPragma>("section");
441
11.1k
    PP.AddPragmaHandler(MSSection.get());
442
11.1k
    MSFunction = std::make_unique<PragmaMSPragma>("function");
443
11.1k
    PP.AddPragmaHandler(MSFunction.get());
444
11.1k
    MSAllocText = std::make_unique<PragmaMSPragma>("alloc_text");
445
11.1k
    PP.AddPragmaHandler(MSAllocText.get());
446
11.1k
    MSOptimize = std::make_unique<PragmaMSPragma>("optimize");
447
11.1k
    PP.AddPragmaHandler(MSOptimize.get());
448
11.1k
    MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
449
11.1k
    PP.AddPragmaHandler(MSRuntimeChecks.get());
450
11.1k
    MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
451
11.1k
    PP.AddPragmaHandler(MSIntrinsic.get());
452
11.1k
    MSFenvAccess = std::make_unique<PragmaMSFenvAccessHandler>();
453
11.1k
    PP.AddPragmaHandler(MSFenvAccess.get());
454
11.1k
  }
455
456
88.1k
  if (getLangOpts().CUDA) {
457
373
    CUDAForceHostDeviceHandler =
458
373
        std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
459
373
    PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
460
373
  }
461
462
88.1k
  OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
463
88.1k
  PP.AddPragmaHandler("clang", OptimizeHandler.get());
464
465
88.1k
  LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
466
88.1k
  PP.AddPragmaHandler("clang", LoopHintHandler.get());
467
468
88.1k
  UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
469
88.1k
  PP.AddPragmaHandler(UnrollHintHandler.get());
470
88.1k
  PP.AddPragmaHandler("GCC", UnrollHintHandler.get());
471
472
88.1k
  NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
473
88.1k
  PP.AddPragmaHandler(NoUnrollHintHandler.get());
474
88.1k
  PP.AddPragmaHandler("GCC", NoUnrollHintHandler.get());
475
476
88.1k
  UnrollAndJamHintHandler =
477
88.1k
      std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
478
88.1k
  PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
479
480
88.1k
  NoUnrollAndJamHintHandler =
481
88.1k
      std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
482
88.1k
  PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
483
484
88.1k
  FPHandler = std::make_unique<PragmaFPHandler>();
485
88.1k
  PP.AddPragmaHandler("clang", FPHandler.get());
486
487
88.1k
  AttributePragmaHandler =
488
88.1k
      std::make_unique<PragmaAttributeHandler>(AttrFactory);
489
88.1k
  PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
490
491
88.1k
  MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();
492
88.1k
  PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());
493
494
88.1k
  MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
495
88.1k
  PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
496
88.1k
}
497
498
88.0k
void Parser::resetPragmaHandlers() {
499
  // Remove the pragma handlers we installed.
500
88.0k
  PP.RemovePragmaHandler(AlignHandler.get());
501
88.0k
  AlignHandler.reset();
502
88.0k
  PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
503
88.0k
  GCCVisibilityHandler.reset();
504
88.0k
  PP.RemovePragmaHandler(OptionsHandler.get());
505
88.0k
  OptionsHandler.reset();
506
88.0k
  PP.RemovePragmaHandler(PackHandler.get());
507
88.0k
  PackHandler.reset();
508
88.0k
  PP.RemovePragmaHandler(MSStructHandler.get());
509
88.0k
  MSStructHandler.reset();
510
88.0k
  PP.RemovePragmaHandler(UnusedHandler.get());
511
88.0k
  UnusedHandler.reset();
512
88.0k
  PP.RemovePragmaHandler(WeakHandler.get());
513
88.0k
  WeakHandler.reset();
514
88.0k
  PP.RemovePragmaHandler(RedefineExtnameHandler.get());
515
88.0k
  RedefineExtnameHandler.reset();
516
517
88.0k
  if (getLangOpts().OpenCL) {
518
793
    PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
519
793
    OpenCLExtensionHandler.reset();
520
793
    PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
521
793
  }
522
88.0k
  PP.RemovePragmaHandler(OpenMPHandler.get());
523
88.0k
  OpenMPHandler.reset();
524
525
88.0k
  if (getLangOpts().MicrosoftExt ||
526
88.0k
      
getTargetInfo().getTriple().isOSBinFormatELF()76.9k
) {
527
37.8k
    PP.RemovePragmaHandler(MSCommentHandler.get());
528
37.8k
    MSCommentHandler.reset();
529
37.8k
  }
530
531
88.0k
  PP.RemovePragmaHandler("clang", PCSectionHandler.get());
532
88.0k
  PCSectionHandler.reset();
533
534
88.0k
  PP.RemovePragmaHandler(FloatControlHandler.get());
535
88.0k
  FloatControlHandler.reset();
536
88.0k
  if (getLangOpts().MicrosoftExt) {
537
11.1k
    PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
538
11.1k
    MSDetectMismatchHandler.reset();
539
11.1k
    PP.RemovePragmaHandler(MSPointersToMembers.get());
540
11.1k
    MSPointersToMembers.reset();
541
11.1k
    PP.RemovePragmaHandler(MSVtorDisp.get());
542
11.1k
    MSVtorDisp.reset();
543
11.1k
    PP.RemovePragmaHandler(MSInitSeg.get());
544
11.1k
    MSInitSeg.reset();
545
11.1k
    PP.RemovePragmaHandler(MSDataSeg.get());
546
11.1k
    MSDataSeg.reset();
547
11.1k
    PP.RemovePragmaHandler(MSBSSSeg.get());
548
11.1k
    MSBSSSeg.reset();
549
11.1k
    PP.RemovePragmaHandler(MSConstSeg.get());
550
11.1k
    MSConstSeg.reset();
551
11.1k
    PP.RemovePragmaHandler(MSCodeSeg.get());
552
11.1k
    MSCodeSeg.reset();
553
11.1k
    PP.RemovePragmaHandler(MSSection.get());
554
11.1k
    MSSection.reset();
555
11.1k
    PP.RemovePragmaHandler(MSFunction.get());
556
11.1k
    MSFunction.reset();
557
11.1k
    PP.RemovePragmaHandler(MSAllocText.get());
558
11.1k
    MSAllocText.reset();
559
11.1k
    PP.RemovePragmaHandler(MSRuntimeChecks.get());
560
11.1k
    MSRuntimeChecks.reset();
561
11.1k
    PP.RemovePragmaHandler(MSIntrinsic.get());
562
11.1k
    MSIntrinsic.reset();
563
11.1k
    PP.RemovePragmaHandler(MSOptimize.get());
564
11.1k
    MSOptimize.reset();
565
11.1k
    PP.RemovePragmaHandler(MSFenvAccess.get());
566
11.1k
    MSFenvAccess.reset();
567
11.1k
  }
568
569
88.0k
  if (getLangOpts().CUDA) {
570
373
    PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
571
373
    CUDAForceHostDeviceHandler.reset();
572
373
  }
573
574
88.0k
  PP.RemovePragmaHandler("STDC", FPContractHandler.get());
575
88.0k
  FPContractHandler.reset();
576
577
88.0k
  PP.RemovePragmaHandler("STDC", STDCFenvAccessHandler.get());
578
88.0k
  STDCFenvAccessHandler.reset();
579
580
88.0k
  PP.RemovePragmaHandler("STDC", STDCFenvRoundHandler.get());
581
88.0k
  STDCFenvRoundHandler.reset();
582
583
88.0k
  PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
584
88.0k
  STDCCXLIMITHandler.reset();
585
586
88.0k
  PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
587
88.0k
  STDCUnknownHandler.reset();
588
589
88.0k
  PP.RemovePragmaHandler("clang", OptimizeHandler.get());
590
88.0k
  OptimizeHandler.reset();
591
592
88.0k
  PP.RemovePragmaHandler("clang", LoopHintHandler.get());
593
88.0k
  LoopHintHandler.reset();
594
595
88.0k
  PP.RemovePragmaHandler(UnrollHintHandler.get());
596
88.0k
  PP.RemovePragmaHandler("GCC", UnrollHintHandler.get());
597
88.0k
  UnrollHintHandler.reset();
598
599
88.0k
  PP.RemovePragmaHandler(NoUnrollHintHandler.get());
600
88.0k
  PP.RemovePragmaHandler("GCC", NoUnrollHintHandler.get());
601
88.0k
  NoUnrollHintHandler.reset();
602
603
88.0k
  PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
604
88.0k
  UnrollAndJamHintHandler.reset();
605
606
88.0k
  PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
607
88.0k
  NoUnrollAndJamHintHandler.reset();
608
609
88.0k
  PP.RemovePragmaHandler("clang", FPHandler.get());
610
88.0k
  FPHandler.reset();
611
612
88.0k
  PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
613
88.0k
  AttributePragmaHandler.reset();
614
615
88.0k
  PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());
616
88.0k
  MaxTokensHerePragmaHandler.reset();
617
618
88.0k
  PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
619
88.0k
  MaxTokensTotalPragmaHandler.reset();
620
88.0k
}
621
622
/// Handle the annotation token produced for #pragma unused(...)
623
///
624
/// Each annot_pragma_unused is followed by the argument token so e.g.
625
/// "#pragma unused(x,y)" becomes:
626
/// annot_pragma_unused 'x' annot_pragma_unused 'y'
627
25
void Parser::HandlePragmaUnused() {
628
25
  assert(Tok.is(tok::annot_pragma_unused));
629
0
  SourceLocation UnusedLoc = ConsumeAnnotationToken();
630
25
  Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
631
25
  ConsumeToken(); // The argument token.
632
25
}
633
634
125
void Parser::HandlePragmaVisibility() {
635
125
  assert(Tok.is(tok::annot_pragma_vis));
636
0
  const IdentifierInfo *VisType =
637
125
    static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
638
125
  SourceLocation VisLoc = ConsumeAnnotationToken();
639
125
  Actions.ActOnPragmaVisibility(VisType, VisLoc);
640
125
}
641
642
namespace {
643
struct PragmaPackInfo {
644
  Sema::PragmaMsStackAction Action;
645
  StringRef SlotLabel;
646
  Token Alignment;
647
};
648
} // end anonymous namespace
649
650
259k
void Parser::HandlePragmaPack() {
651
259k
  assert(Tok.is(tok::annot_pragma_pack));
652
0
  PragmaPackInfo *Info =
653
259k
    static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
654
259k
  SourceLocation PragmaLoc = Tok.getLocation();
655
259k
  ExprResult Alignment;
656
259k
  if (Info->Alignment.is(tok::numeric_constant)) {
657
129k
    Alignment = Actions.ActOnNumericConstant(Info->Alignment);
658
129k
    if (Alignment.isInvalid()) {
659
0
      ConsumeAnnotationToken();
660
0
      return;
661
0
    }
662
129k
  }
663
259k
  Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
664
259k
                          Alignment.get());
665
  // Consume the token after processing the pragma to enable pragma-specific
666
  // #include warnings.
667
259k
  ConsumeAnnotationToken();
668
259k
}
669
670
14
void Parser::HandlePragmaMSStruct() {
671
14
  assert(Tok.is(tok::annot_pragma_msstruct));
672
0
  PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
673
14
      reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
674
14
  Actions.ActOnPragmaMSStruct(Kind);
675
14
  ConsumeAnnotationToken();
676
14
}
677
678
2.81k
void Parser::HandlePragmaAlign() {
679
2.81k
  assert(Tok.is(tok::annot_pragma_align));
680
0
  Sema::PragmaOptionsAlignKind Kind =
681
2.81k
    static_cast<Sema::PragmaOptionsAlignKind>(
682
2.81k
    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
683
2.81k
  Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
684
  // Consume the token after processing the pragma to enable pragma-specific
685
  // #include warnings.
686
2.81k
  ConsumeAnnotationToken();
687
2.81k
}
688
689
20
void Parser::HandlePragmaDump() {
690
20
  assert(Tok.is(tok::annot_pragma_dump));
691
0
  IdentifierInfo *II =
692
20
      reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
693
20
  Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
694
20
  ConsumeAnnotationToken();
695
20
}
696
697
91
void Parser::HandlePragmaWeak() {
698
91
  assert(Tok.is(tok::annot_pragma_weak));
699
0
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
700
91
  Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
701
91
                            Tok.getLocation());
702
91
  ConsumeToken(); // The weak name.
703
91
}
704
705
35
void Parser::HandlePragmaWeakAlias() {
706
35
  assert(Tok.is(tok::annot_pragma_weakalias));
707
0
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
708
35
  IdentifierInfo *WeakName = Tok.getIdentifierInfo();
709
35
  SourceLocation WeakNameLoc = Tok.getLocation();
710
35
  ConsumeToken();
711
35
  IdentifierInfo *AliasName = Tok.getIdentifierInfo();
712
35
  SourceLocation AliasNameLoc = Tok.getLocation();
713
35
  ConsumeToken();
714
35
  Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
715
35
                               WeakNameLoc, AliasNameLoc);
716
717
35
}
718
719
11
void Parser::HandlePragmaRedefineExtname() {
720
11
  assert(Tok.is(tok::annot_pragma_redefine_extname));
721
0
  SourceLocation RedefLoc = ConsumeAnnotationToken();
722
11
  IdentifierInfo *RedefName = Tok.getIdentifierInfo();
723
11
  SourceLocation RedefNameLoc = Tok.getLocation();
724
11
  ConsumeToken();
725
11
  IdentifierInfo *AliasName = Tok.getIdentifierInfo();
726
11
  SourceLocation AliasNameLoc = Tok.getLocation();
727
11
  ConsumeToken();
728
11
  Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
729
11
                                     RedefNameLoc, AliasNameLoc);
730
11
}
731
732
33
void Parser::HandlePragmaFPContract() {
733
33
  assert(Tok.is(tok::annot_pragma_fp_contract));
734
0
  tok::OnOffSwitch OOS =
735
33
    static_cast<tok::OnOffSwitch>(
736
33
    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
737
738
33
  LangOptions::FPModeKind FPC;
739
33
  switch (OOS) {
740
24
  case tok::OOS_ON:
741
24
    FPC = LangOptions::FPM_On;
742
24
    break;
743
7
  case tok::OOS_OFF:
744
7
    FPC = LangOptions::FPM_Off;
745
7
    break;
746
2
  case tok::OOS_DEFAULT:
747
2
    FPC = getLangOpts().getDefaultFPContractMode();
748
2
    break;
749
33
  }
750
751
33
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
752
33
  Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
753
33
}
754
755
476
void Parser::HandlePragmaFloatControl() {
756
476
  assert(Tok.is(tok::annot_pragma_float_control));
757
758
  // The value that is held on the PragmaFloatControlStack encodes
759
  // the PragmaFloatControl kind and the MSStackAction kind
760
  // into a single 32-bit word. The MsStackAction is the high 16 bits
761
  // and the FloatControl is the lower 16 bits. Use shift and bit-and
762
  // to decode the parts.
763
0
  uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
764
476
  Sema::PragmaMsStackAction Action =
765
476
      static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
766
476
  PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF);
767
476
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
768
476
  Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);
769
476
}
770
771
74
void Parser::HandlePragmaFEnvAccess() {
772
74
  assert(Tok.is(tok::annot_pragma_fenv_access) ||
773
74
         Tok.is(tok::annot_pragma_fenv_access_ms));
774
0
  tok::OnOffSwitch OOS =
775
74
    static_cast<tok::OnOffSwitch>(
776
74
    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
777
778
74
  bool IsEnabled;
779
74
  switch (OOS) {
780
50
  case tok::OOS_ON:
781
50
    IsEnabled = true;
782
50
    break;
783
24
  case tok::OOS_OFF:
784
24
    IsEnabled = false;
785
24
    break;
786
0
  case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
787
0
    IsEnabled = false;
788
0
    break;
789
74
  }
790
791
74
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
792
74
  Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);
793
74
}
794
795
76
void Parser::HandlePragmaFEnvRound() {
796
76
  assert(Tok.is(tok::annot_pragma_fenv_round));
797
0
  auto RM = static_cast<llvm::RoundingMode>(
798
76
      reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
799
800
76
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
801
76
  Actions.ActOnPragmaFEnvRound(PragmaLoc, RM);
802
76
}
803
804
StmtResult Parser::HandlePragmaCaptured()
805
57
{
806
57
  assert(Tok.is(tok::annot_pragma_captured));
807
0
  ConsumeAnnotationToken();
808
809
57
  if (Tok.isNot(tok::l_brace)) {
810
1
    PP.Diag(Tok, diag::err_expected) << tok::l_brace;
811
1
    return StmtError();
812
1
  }
813
814
56
  SourceLocation Loc = Tok.getLocation();
815
816
56
  ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
817
56
                                           Scope::CompoundStmtScope);
818
56
  Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
819
56
                                   /*NumParams=*/1);
820
821
56
  StmtResult R = ParseCompoundStatement();
822
56
  CapturedRegionScope.Exit();
823
824
56
  if (R.isInvalid()) {
825
0
    Actions.ActOnCapturedRegionError();
826
0
    return StmtError();
827
0
  }
828
829
56
  return Actions.ActOnCapturedRegionEnd(R.get());
830
56
}
831
832
namespace {
833
  enum OpenCLExtState : char {
834
    Disable, Enable, Begin, End
835
  };
836
  typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
837
}
838
839
1.81k
void Parser::HandlePragmaOpenCLExtension() {
840
1.81k
  assert(Tok.is(tok::annot_pragma_opencl_extension));
841
0
  OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
842
1.81k
  auto State = Data->second;
843
1.81k
  auto Ident = Data->first;
844
1.81k
  SourceLocation NameLoc = Tok.getLocation();
845
1.81k
  ConsumeAnnotationToken();
846
847
1.81k
  auto &Opt = Actions.getOpenCLOptions();
848
1.81k
  auto Name = Ident->getName();
849
  // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
850
  // overriding all previously issued extension directives, but only if the
851
  // behavior is set to disable."
852
1.81k
  if (Name == "all") {
853
93
    if (State == Disable)
854
84
      Opt.disableAll();
855
9
    else
856
9
      PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
857
1.72k
  } else if (State == Begin) {
858
28
    if (!Opt.isKnown(Name) || 
!Opt.isSupported(Name, getLangOpts())12
) {
859
16
      Opt.support(Name);
860
      // FIXME: Default behavior of the extension pragma is not defined.
861
      // Therefore, it should never be added by default.
862
16
      Opt.acceptsPragma(Name);
863
16
    }
864
1.69k
  } else if (State == End) {
865
    // There is no behavior for this directive. We only accept this for
866
    // backward compatibility.
867
1.66k
  } else if (!Opt.isKnown(Name) || 
!Opt.isWithPragma(Name)1.62k
)
868
298
    PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
869
1.36k
  else if (Opt.isSupportedExtension(Name, getLangOpts()))
870
852
    Opt.enable(Name, State == Enable);
871
512
  else if (Opt.isSupportedCoreOrOptionalCore(Name, getLangOpts()))
872
261
    PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
873
251
  else
874
251
    PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
875
1.81k
}
876
877
25
void Parser::HandlePragmaMSPointersToMembers() {
878
25
  assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
879
0
  LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
880
25
      static_cast<LangOptions::PragmaMSPointersToMembersKind>(
881
25
          reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
882
25
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
883
25
  Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
884
25
}
885
886
45
void Parser::HandlePragmaMSVtorDisp() {
887
45
  assert(Tok.is(tok::annot_pragma_ms_vtordisp));
888
0
  uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
889
45
  Sema::PragmaMsStackAction Action =
890
45
      static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
891
45
  MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);
892
45
  SourceLocation PragmaLoc = ConsumeAnnotationToken();
893
45
  Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
894
45
}
895
896
197
void Parser::HandlePragmaMSPragma() {
897
197
  assert(Tok.is(tok::annot_pragma_ms_pragma));
898
  // Grab the tokens out of the annotation and enter them into the stream.
899
0
  auto TheTokens =
900
197
      (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
901
197
  PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
902
197
                      /*IsReinject=*/true);
903
197
  SourceLocation PragmaLocation = ConsumeAnnotationToken();
904
197
  assert(Tok.isAnyIdentifier());
905
0
  StringRef PragmaName = Tok.getIdentifierInfo()->getName();
906
197
  PP.Lex(Tok); // pragma kind
907
908
  // Figure out which #pragma we're dealing with.  The switch has no default
909
  // because lex shouldn't emit the annotation token for unrecognized pragmas.
910
197
  typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
911
197
  PragmaHandler Handler =
912
197
      llvm::StringSwitch<PragmaHandler>(PragmaName)
913
197
          .Case("data_seg", &Parser::HandlePragmaMSSegment)
914
197
          .Case("bss_seg", &Parser::HandlePragmaMSSegment)
915
197
          .Case("const_seg", &Parser::HandlePragmaMSSegment)
916
197
          .Case("code_seg", &Parser::HandlePragmaMSSegment)
917
197
          .Case("section", &Parser::HandlePragmaMSSection)
918
197
          .Case("init_seg", &Parser::HandlePragmaMSInitSeg)
919
197
          .Case("function", &Parser::HandlePragmaMSFunction)
920
197
          .Case("alloc_text", &Parser::HandlePragmaMSAllocText)
921
197
          .Case("optimize", &Parser::HandlePragmaMSOptimize);
922
923
197
  if (!(this->*Handler)(PragmaName, PragmaLocation)) {
924
    // Pragma handling failed, and has been diagnosed.  Slurp up the tokens
925
    // until eof (really end of line) to prevent follow-on errors.
926
131
    while (Tok.isNot(tok::eof))
927
71
      PP.Lex(Tok);
928
60
    PP.Lex(Tok);
929
60
  }
930
197
}
931
932
bool Parser::HandlePragmaMSSection(StringRef PragmaName,
933
31
                                   SourceLocation PragmaLocation) {
934
31
  if (Tok.isNot(tok::l_paren)) {
935
1
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
936
1
    return false;
937
1
  }
938
30
  PP.Lex(Tok); // (
939
  // Parsing code for pragma section
940
30
  if (Tok.isNot(tok::string_literal)) {
941
2
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
942
2
        << PragmaName;
943
2
    return false;
944
2
  }
945
28
  ExprResult StringResult = ParseStringLiteralExpression();
946
28
  if (StringResult.isInvalid())
947
0
    return false; // Already diagnosed.
948
28
  StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
949
28
  if (SegmentName->getCharByteWidth() != 1) {
950
0
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
951
0
        << PragmaName;
952
0
    return false;
953
0
  }
954
28
  int SectionFlags = ASTContext::PSF_Read;
955
28
  bool SectionFlagsAreDefault = true;
956
82
  while (Tok.is(tok::comma)) {
957
58
    PP.Lex(Tok); // ,
958
    // Ignore "long" and "short".
959
    // They are undocumented, but widely used, section attributes which appear
960
    // to do nothing.
961
58
    if (Tok.is(tok::kw_long) || 
Tok.is(tok::kw_short)42
) {
962
17
      PP.Lex(Tok); // long/short
963
17
      continue;
964
17
    }
965
966
41
    if (!Tok.isAnyIdentifier()) {
967
2
      PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
968
2
          << PragmaName;
969
2
      return false;
970
2
    }
971
39
    ASTContext::PragmaSectionFlag Flag =
972
39
      llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
973
39
      Tok.getIdentifierInfo()->getName())
974
39
      .Case("read", ASTContext::PSF_Read)
975
39
      .Case("write", ASTContext::PSF_Write)
976
39
      .Case("execute", ASTContext::PSF_Execute)
977
39
      .Case("shared", ASTContext::PSF_Invalid)
978
39
      .Case("nopage", ASTContext::PSF_Invalid)
979
39
      .Case("nocache", ASTContext::PSF_Invalid)
980
39
      .Case("discard", ASTContext::PSF_Invalid)
981
39
      .Case("remove", ASTContext::PSF_Invalid)
982
39
      .Default(ASTContext::PSF_None);
983
39
    if (Flag == ASTContext::PSF_None || 
Flag == ASTContext::PSF_Invalid38
) {
984
2
      PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
985
2
                                  ? 
diag::warn_pragma_invalid_specific_action1
986
2
                                  : 
diag::warn_pragma_unsupported_action1
)
987
2
          << PragmaName << Tok.getIdentifierInfo()->getName();
988
2
      return false;
989
2
    }
990
37
    SectionFlags |= Flag;
991
37
    SectionFlagsAreDefault = false;
992
37
    PP.Lex(Tok); // Identifier
993
37
  }
994
  // If no section attributes are specified, the section will be marked as
995
  // read/write.
996
24
  if (SectionFlagsAreDefault)
997
5
    SectionFlags |= ASTContext::PSF_Write;
998
24
  if (Tok.isNot(tok::r_paren)) {
999
2
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
1000
2
    return false;
1001
2
  }
1002
22
  PP.Lex(Tok); // )
1003
22
  if (Tok.isNot(tok::eof)) {
1004
0
    PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
1005
0
        << PragmaName;
1006
0
    return false;
1007
0
  }
1008
22
  PP.Lex(Tok); // eof
1009
22
  Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
1010
22
  return true;
1011
22
}
1012
1013
bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
1014
67
                                   SourceLocation PragmaLocation) {
1015
67
  if (Tok.isNot(tok::l_paren)) {
1016
2
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
1017
2
    return false;
1018
2
  }
1019
65
  PP.Lex(Tok); // (
1020
65
  Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1021
65
  StringRef SlotLabel;
1022
65
  if (Tok.isAnyIdentifier()) {
1023
27
    StringRef PushPop = Tok.getIdentifierInfo()->getName();
1024
27
    if (PushPop == "push")
1025
20
      Action = Sema::PSK_Push;
1026
7
    else if (PushPop == "pop")
1027
7
      Action = Sema::PSK_Pop;
1028
0
    else {
1029
0
      PP.Diag(PragmaLocation,
1030
0
              diag::warn_pragma_expected_section_push_pop_or_name)
1031
0
          << PragmaName;
1032
0
      return false;
1033
0
    }
1034
27
    if (Action != Sema::PSK_Reset) {
1035
27
      PP.Lex(Tok); // push | pop
1036
27
      if (Tok.is(tok::comma)) {
1037
20
        PP.Lex(Tok); // ,
1038
        // If we've got a comma, we either need a label or a string.
1039
20
        if (Tok.isAnyIdentifier()) {
1040
4
          SlotLabel = Tok.getIdentifierInfo()->getName();
1041
4
          PP.Lex(Tok); // identifier
1042
4
          if (Tok.is(tok::comma))
1043
3
            PP.Lex(Tok);
1044
1
          else if (Tok.isNot(tok::r_paren)) {
1045
0
            PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
1046
0
                << PragmaName;
1047
0
            return false;
1048
0
          }
1049
4
        }
1050
20
      } else 
if (7
Tok.isNot(tok::r_paren)7
) {
1051
0
        PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
1052
0
        return false;
1053
0
      }
1054
27
    }
1055
27
  }
1056
  // Grab the string literal for our section name.
1057
65
  StringLiteral *SegmentName = nullptr;
1058
65
  if (Tok.isNot(tok::r_paren)) {
1059
53
    if (Tok.isNot(tok::string_literal)) {
1060
4
      unsigned DiagID = Action != Sema::PSK_Reset ? 
!SlotLabel.empty()2
?
1061
1
          diag::warn_pragma_expected_section_name :
1062
2
          
diag::warn_pragma_expected_section_label_or_name1
:
1063
4
          
diag::warn_pragma_expected_section_push_pop_or_name2
;
1064
4
      PP.Diag(PragmaLocation, DiagID) << PragmaName;
1065
4
      return false;
1066
4
    }
1067
49
    ExprResult StringResult = ParseStringLiteralExpression();
1068
49
    if (StringResult.isInvalid())
1069
1
      return false; // Already diagnosed.
1070
48
    SegmentName = cast<StringLiteral>(StringResult.get());
1071
48
    if (SegmentName->getCharByteWidth() != 1) {
1072
1
      PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1073
1
          << PragmaName;
1074
1
      return false;
1075
1
    }
1076
    // Setting section "" has no effect
1077
47
    if (SegmentName->getLength())
1078
47
      Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
1079
47
  }
1080
59
  if (Tok.isNot(tok::r_paren)) {
1081
2
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
1082
2
    return false;
1083
2
  }
1084
57
  PP.Lex(Tok); // )
1085
57
  if (Tok.isNot(tok::eof)) {
1086
0
    PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
1087
0
        << PragmaName;
1088
0
    return false;
1089
0
  }
1090
57
  PP.Lex(Tok); // eof
1091
57
  Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
1092
57
                           SegmentName, PragmaName);
1093
57
  return true;
1094
57
}
1095
1096
// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
1097
bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
1098
48
                                   SourceLocation PragmaLocation) {
1099
48
  if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
1100
3
    PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
1101
3
    return false;
1102
3
  }
1103
1104
45
  if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1105
45
                       PragmaName))
1106
6
    return false;
1107
1108
  // Parse either the known section names or the string section name.
1109
39
  StringLiteral *SegmentName = nullptr;
1110
39
  if (Tok.isAnyIdentifier()) {
1111
17
    auto *II = Tok.getIdentifierInfo();
1112
17
    StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
1113
17
                            .Case("compiler", "\".CRT$XCC\"")
1114
17
                            .Case("lib", "\".CRT$XCL\"")
1115
17
                            .Case("user", "\".CRT$XCU\"")
1116
17
                            .Default("");
1117
1118
17
    if (!Section.empty()) {
1119
      // Pretend the user wrote the appropriate string literal here.
1120
17
      Token Toks[1];
1121
17
      Toks[0].startToken();
1122
17
      Toks[0].setKind(tok::string_literal);
1123
17
      Toks[0].setLocation(Tok.getLocation());
1124
17
      Toks[0].setLiteralData(Section.data());
1125
17
      Toks[0].setLength(Section.size());
1126
17
      SegmentName =
1127
17
          cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
1128
17
      PP.Lex(Tok);
1129
17
    }
1130
22
  } else if (Tok.is(tok::string_literal)) {
1131
16
    ExprResult StringResult = ParseStringLiteralExpression();
1132
16
    if (StringResult.isInvalid())
1133
0
      return false;
1134
16
    SegmentName = cast<StringLiteral>(StringResult.get());
1135
16
    if (SegmentName->getCharByteWidth() != 1) {
1136
3
      PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1137
3
          << PragmaName;
1138
3
      return false;
1139
3
    }
1140
    // FIXME: Add support for the '[, func-name]' part of the pragma.
1141
16
  }
1142
1143
36
  if (!SegmentName) {
1144
6
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
1145
6
    return false;
1146
6
  }
1147
1148
30
  if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1149
30
                       PragmaName) ||
1150
30
      ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1151
27
                       PragmaName))
1152
6
    return false;
1153
1154
24
  Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
1155
24
  return true;
1156
30
}
1157
1158
bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,
1159
24
                                     SourceLocation PragmaLocation) {
1160
24
  Token FirstTok = Tok;
1161
24
  if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1162
24
                       PragmaName))
1163
0
    return false;
1164
1165
24
  StringRef Section;
1166
24
  if (Tok.is(tok::string_literal)) {
1167
5
    ExprResult StringResult = ParseStringLiteralExpression();
1168
5
    if (StringResult.isInvalid())
1169
0
      return false; // Already diagnosed.
1170
5
    StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
1171
5
    if (SegmentName->getCharByteWidth() != 1) {
1172
0
      PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1173
0
          << PragmaName;
1174
0
      return false;
1175
0
    }
1176
5
    Section = SegmentName->getString();
1177
19
  } else if (Tok.is(tok::identifier)) {
1178
17
    Section = Tok.getIdentifierInfo()->getName();
1179
17
    PP.Lex(Tok);
1180
17
  } else {
1181
2
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
1182
2
        << PragmaName;
1183
2
    return false;
1184
2
  }
1185
1186
22
  if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
1187
22
                       PragmaName))
1188
1
    return false;
1189
1190
21
  SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> Functions;
1191
22
  while (true) {
1192
22
    if (Tok.isNot(tok::identifier)) {
1193
0
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1194
0
          << PragmaName;
1195
0
      return false;
1196
0
    }
1197
1198
22
    IdentifierInfo *II = Tok.getIdentifierInfo();
1199
22
    Functions.emplace_back(II, Tok.getLocation());
1200
1201
22
    PP.Lex(Tok);
1202
22
    if (Tok.isNot(tok::comma))
1203
21
      break;
1204
1
    PP.Lex(Tok);
1205
1
  }
1206
1207
21
  if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1208
21
                       PragmaName) ||
1209
21
      ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1210
19
                       PragmaName))
1211
3
    return false;
1212
1213
18
  Actions.ActOnPragmaMSAllocText(FirstTok.getLocation(), Section, Functions);
1214
18
  return true;
1215
21
}
1216
1217
namespace {
1218
struct PragmaLoopHintInfo {
1219
  Token PragmaName;
1220
  Token Option;
1221
  ArrayRef<Token> Toks;
1222
};
1223
} // end anonymous namespace
1224
1225
2
static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
1226
2
  StringRef Str = PragmaName.getIdentifierInfo()->getName();
1227
2
  std::string ClangLoopStr = (llvm::Twine("clang loop ") + Str).str();
1228
2
  return std::string(llvm::StringSwitch<StringRef>(Str)
1229
2
                         .Case("loop", ClangLoopStr)
1230
2
                         .Case("unroll_and_jam", Str)
1231
2
                         .Case("unroll", Str)
1232
2
                         .Default(""));
1233
2
}
1234
1235
405
bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
1236
405
  assert(Tok.is(tok::annot_pragma_loop_hint));
1237
0
  PragmaLoopHintInfo *Info =
1238
405
      static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
1239
1240
405
  IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
1241
405
  Hint.PragmaNameLoc = IdentifierLoc::create(
1242
405
      Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
1243
1244
  // It is possible that the loop hint has no option identifier, such as
1245
  // #pragma unroll(4).
1246
405
  IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
1247
405
                                   ? 
Info->Option.getIdentifierInfo()310
1248
405
                                   : 
nullptr95
;
1249
405
  Hint.OptionLoc = IdentifierLoc::create(
1250
405
      Actions.Context, Info->Option.getLocation(), OptionInfo);
1251
1252
405
  llvm::ArrayRef<Token> Toks = Info->Toks;
1253
1254
  // Return a valid hint if pragma unroll or nounroll were specified
1255
  // without an argument.
1256
405
  auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
1257
405
                        .Cases("unroll", "nounroll", "unroll_and_jam",
1258
405
                               "nounroll_and_jam", true)
1259
405
                        .Default(false);
1260
1261
405
  if (Toks.empty() && 
IsLoopHint38
) {
1262
38
    ConsumeAnnotationToken();
1263
38
    Hint.Range = Info->PragmaName.getLocation();
1264
38
    return true;
1265
38
  }
1266
1267
  // The constant expression is always followed by an eof token, which increases
1268
  // the TokSize by 1.
1269
367
  assert(!Toks.empty() &&
1270
367
         "PragmaLoopHintInfo::Toks must contain at least one token.");
1271
1272
  // If no option is specified the argument is assumed to be a constant expr.
1273
0
  bool OptionUnroll = false;
1274
367
  bool OptionUnrollAndJam = false;
1275
367
  bool OptionDistribute = false;
1276
367
  bool OptionPipelineDisabled = false;
1277
367
  bool StateOption = false;
1278
367
  if (OptionInfo) { // Pragma Unroll does not specify an option.
1279
310
    OptionUnroll = OptionInfo->isStr("unroll");
1280
310
    OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
1281
310
    OptionDistribute = OptionInfo->isStr("distribute");
1282
310
    OptionPipelineDisabled = OptionInfo->isStr("pipeline");
1283
310
    StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1284
310
                      .Case("vectorize", true)
1285
310
                      .Case("interleave", true)
1286
310
                      .Case("vectorize_predicate", true)
1287
310
                      .Default(false) ||
1288
310
                  
OptionUnroll205
||
OptionUnrollAndJam166
||
OptionDistribute166
||
1289
310
                  
OptionPipelineDisabled141
;
1290
310
  }
1291
1292
367
  bool AssumeSafetyArg = !OptionUnroll && 
!OptionUnrollAndJam328
&&
1293
367
                         
!OptionDistribute328
&&
!OptionPipelineDisabled303
;
1294
  // Verify loop hint has an argument.
1295
367
  if (Toks[0].is(tok::eof)) {
1296
7
    ConsumeAnnotationToken();
1297
7
    Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
1298
7
        << /*StateArgument=*/StateOption
1299
7
        << /*FullKeyword=*/(OptionUnroll || 
OptionUnrollAndJam6
)
1300
7
        << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1301
7
    return false;
1302
7
  }
1303
1304
  // Validate the argument.
1305
360
  if (StateOption) {
1306
174
    ConsumeAnnotationToken();
1307
174
    SourceLocation StateLoc = Toks[0].getLocation();
1308
174
    IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1309
1310
174
    bool Valid = StateInfo &&
1311
174
                 llvm::StringSwitch<bool>(StateInfo->getName())
1312
171
                     .Case("disable", true)
1313
171
                     .Case("enable", !OptionPipelineDisabled)
1314
171
                     .Case("full", OptionUnroll || 
OptionUnrollAndJam134
)
1315
171
                     .Case("assume_safety", AssumeSafetyArg)
1316
171
                     .Default(false);
1317
174
    if (!Valid) {
1318
14
      if (OptionPipelineDisabled) {
1319
2
        Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
1320
12
      } else {
1321
12
        Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
1322
12
            << /*FullKeyword=*/(OptionUnroll || 
OptionUnrollAndJam8
)
1323
12
            << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1324
12
      }
1325
14
      return false;
1326
14
    }
1327
160
    if (Toks.size() > 2)
1328
0
      Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1329
0
          << PragmaLoopHintString(Info->PragmaName, Info->Option);
1330
160
    Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1331
186
  } else if (OptionInfo && 
OptionInfo->getName() == "vectorize_width"131
) {
1332
60
    PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1333
60
                        /*IsReinject=*/false);
1334
60
    ConsumeAnnotationToken();
1335
1336
60
    SourceLocation StateLoc = Toks[0].getLocation();
1337
60
    IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1338
60
    StringRef IsScalableStr = StateInfo ? 
StateInfo->getName()26
:
""34
;
1339
1340
    // Look for vectorize_width(fixed|scalable)
1341
60
    if (IsScalableStr == "scalable" || 
IsScalableStr == "fixed"57
) {
1342
6
      PP.Lex(Tok); // Identifier
1343
1344
6
      if (Toks.size() > 2) {
1345
0
        Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1346
0
            << PragmaLoopHintString(Info->PragmaName, Info->Option);
1347
0
        while (Tok.isNot(tok::eof))
1348
0
          ConsumeAnyToken();
1349
0
      }
1350
1351
6
      Hint.StateLoc =
1352
6
          IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1353
1354
6
      ConsumeToken(); // Consume the constant expression eof terminator.
1355
54
    } else {
1356
      // Enter constant expression including eof terminator into token stream.
1357
54
      ExprResult R = ParseConstantExpression();
1358
1359
54
      if (R.isInvalid() && 
!Tok.is(tok::comma)5
)
1360
5
        Diag(Toks[0].getLocation(),
1361
5
             diag::note_pragma_loop_invalid_vectorize_option);
1362
1363
54
      bool Arg2Error = false;
1364
54
      if (Tok.is(tok::comma)) {
1365
6
        PP.Lex(Tok); // ,
1366
1367
6
        StateInfo = Tok.getIdentifierInfo();
1368
6
        IsScalableStr = StateInfo->getName();
1369
1370
6
        if (IsScalableStr != "scalable" && 
IsScalableStr != "fixed"2
) {
1371
0
          Diag(Tok.getLocation(),
1372
0
               diag::err_pragma_loop_invalid_vectorize_option);
1373
0
          Arg2Error = true;
1374
0
        } else
1375
6
          Hint.StateLoc =
1376
6
              IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1377
1378
6
        PP.Lex(Tok); // Identifier
1379
6
      }
1380
1381
      // Tokens following an error in an ill-formed constant expression will
1382
      // remain in the token stream and must be removed.
1383
54
      if (Tok.isNot(tok::eof)) {
1384
0
        Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1385
0
            << PragmaLoopHintString(Info->PragmaName, Info->Option);
1386
0
        while (Tok.isNot(tok::eof))
1387
0
          ConsumeAnyToken();
1388
0
      }
1389
1390
54
      ConsumeToken(); // Consume the constant expression eof terminator.
1391
1392
54
      if (Arg2Error || R.isInvalid() ||
1393
54
          
Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation())49
)
1394
8
        return false;
1395
1396
      // Argument is a constant expression with an integer type.
1397
46
      Hint.ValueExpr = R.get();
1398
46
    }
1399
126
  } else {
1400
    // Enter constant expression including eof terminator into token stream.
1401
126
    PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1402
126
                        /*IsReinject=*/false);
1403
126
    ConsumeAnnotationToken();
1404
126
    ExprResult R = ParseConstantExpression();
1405
1406
    // Tokens following an error in an ill-formed constant expression will
1407
    // remain in the token stream and must be removed.
1408
126
    if (Tok.isNot(tok::eof)) {
1409
2
      Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1410
2
          << PragmaLoopHintString(Info->PragmaName, Info->Option);
1411
4
      while (Tok.isNot(tok::eof))
1412
2
        ConsumeAnyToken();
1413
2
    }
1414
1415
126
    ConsumeToken(); // Consume the constant expression eof terminator.
1416
1417
126
    if (R.isInvalid() ||
1418
126
        
Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation())119
)
1419
19
      return false;
1420
1421
    // Argument is a constant expression with an integer type.
1422
107
    Hint.ValueExpr = R.get();
1423
107
  }
1424
1425
319
  Hint.Range = SourceRange(Info->PragmaName.getLocation(),
1426
319
                           Info->Toks.back().getLocation());
1427
319
  return true;
1428
360
}
1429
1430
namespace {
1431
struct PragmaAttributeInfo {
1432
  enum ActionType { Push, Pop, Attribute };
1433
  ParsedAttributes &Attributes;
1434
  ActionType Action;
1435
  const IdentifierInfo *Namespace = nullptr;
1436
  ArrayRef<Token> Tokens;
1437
1438
3.14k
  PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1439
};
1440
1441
#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1442
1443
} // end anonymous namespace
1444
1445
12.3k
static StringRef getIdentifier(const Token &Tok) {
1446
12.3k
  if (Tok.is(tok::identifier))
1447
11.3k
    return Tok.getIdentifierInfo()->getName();
1448
940
  const char *S = tok::getKeywordSpelling(Tok.getKind());
1449
940
  if (!S)
1450
14
    return "";
1451
926
  return S;
1452
940
}
1453
1454
11.0k
static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1455
11.0k
  using namespace attr;
1456
11.0k
  switch (Rule) {
1457
0
#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)                           \
1458
11.0k
  case Value:                                                                  \
1459
11.0k
    return IsAbstract;
1460
11.0k
#include 
"clang/Basic/AttrSubMatchRulesList.inc"0
1461
11.0k
  }
1462
0
  llvm_unreachable("Invalid attribute subject match rule");
1463
0
  return false;
1464
11.0k
}
1465
1466
static void diagnoseExpectedAttributeSubjectSubRule(
1467
    Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1468
5
    SourceLocation SubRuleLoc) {
1469
5
  auto Diagnostic =
1470
5
      PRef.Diag(SubRuleLoc,
1471
5
                diag::err_pragma_attribute_expected_subject_sub_identifier)
1472
5
      << PrimaryRuleName;
1473
5
  if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1474
3
    Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1475
2
  else
1476
2
    Diagnostic << /*SubRulesSupported=*/0;
1477
5
}
1478
1479
static void diagnoseUnknownAttributeSubjectSubRule(
1480
    Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1481
7
    StringRef SubRuleName, SourceLocation SubRuleLoc) {
1482
1483
7
  auto Diagnostic =
1484
7
      PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1485
7
      << SubRuleName << PrimaryRuleName;
1486
7
  if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1487
4
    Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1488
3
  else
1489
3
    Diagnostic << /*SubRulesSupported=*/0;
1490
7
}
1491
1492
bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1493
    attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1494
1.10k
    SourceLocation &LastMatchRuleEndLoc) {
1495
1.10k
  bool IsAny = false;
1496
1.10k
  BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1497
1.10k
  if (getIdentifier(Tok) == "any") {
1498
1.02k
    AnyLoc = ConsumeToken();
1499
1.02k
    IsAny = true;
1500
1.02k
    if (AnyParens.expectAndConsume())
1501
4
      return true;
1502
1.02k
  }
1503
1504
11.0k
  
do 1.10k
{
1505
    // Parse the subject matcher rule.
1506
11.0k
    StringRef Name = getIdentifier(Tok);
1507
11.0k
    if (Name.empty()) {
1508
7
      Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1509
7
      return true;
1510
7
    }
1511
11.0k
    std::pair<Optional<attr::SubjectMatchRule>,
1512
11.0k
              Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1513
11.0k
        Rule = isAttributeSubjectMatchRule(Name);
1514
11.0k
    if (!Rule.first) {
1515
4
      Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1516
4
      return true;
1517
4
    }
1518
11.0k
    attr::SubjectMatchRule PrimaryRule = *Rule.first;
1519
11.0k
    SourceLocation RuleLoc = ConsumeToken();
1520
1521
11.0k
    BalancedDelimiterTracker Parens(*this, tok::l_paren);
1522
11.0k
    if (isAbstractAttrMatcherRule(PrimaryRule)) {
1523
5
      if (Parens.expectAndConsume())
1524
2
        return true;
1525
11.0k
    } else if (Parens.consumeOpen()) {
1526
10.9k
      if (!SubjectMatchRules
1527
10.9k
               .insert(
1528
10.9k
                   std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1529
10.9k
               .second)
1530
7
        Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1531
7
            << Name
1532
7
            << FixItHint::CreateRemoval(SourceRange(
1533
7
                   RuleLoc, Tok.is(tok::comma) ? 
Tok.getLocation()3
:
RuleLoc4
));
1534
10.9k
      LastMatchRuleEndLoc = RuleLoc;
1535
10.9k
      continue;
1536
10.9k
    }
1537
1538
    // Parse the sub-rules.
1539
113
    StringRef SubRuleName = getIdentifier(Tok);
1540
113
    if (SubRuleName.empty()) {
1541
3
      diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1542
3
                                              Tok.getLocation());
1543
3
      return true;
1544
3
    }
1545
110
    attr::SubjectMatchRule SubRule;
1546
110
    if (SubRuleName == "unless") {
1547
50
      SourceLocation SubRuleLoc = ConsumeToken();
1548
50
      BalancedDelimiterTracker Parens(*this, tok::l_paren);
1549
50
      if (Parens.expectAndConsume())
1550
2
        return true;
1551
48
      SubRuleName = getIdentifier(Tok);
1552
48
      if (SubRuleName.empty()) {
1553
2
        diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1554
2
                                                SubRuleLoc);
1555
2
        return true;
1556
2
      }
1557
46
      auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1558
46
      if (!SubRuleOrNone) {
1559
3
        std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1560
3
        diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1561
3
                                               SubRuleUnlessName, SubRuleLoc);
1562
3
        return true;
1563
3
      }
1564
43
      SubRule = *SubRuleOrNone;
1565
43
      ConsumeToken();
1566
43
      if (Parens.consumeClose())
1567
1
        return true;
1568
60
    } else {
1569
60
      auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1570
60
      if (!SubRuleOrNone) {
1571
4
        diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1572
4
                                               SubRuleName, Tok.getLocation());
1573
4
        return true;
1574
4
      }
1575
56
      SubRule = *SubRuleOrNone;
1576
56
      ConsumeToken();
1577
56
    }
1578
98
    SourceLocation RuleEndLoc = Tok.getLocation();
1579
98
    LastMatchRuleEndLoc = RuleEndLoc;
1580
98
    if (Parens.consumeClose())
1581
1
      return true;
1582
97
    if (!SubjectMatchRules
1583
97
             .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1584
97
             .second) {
1585
8
      Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1586
8
          << attr::getSubjectMatchRuleSpelling(SubRule)
1587
8
          << FixItHint::CreateRemoval(SourceRange(
1588
8
                 RuleLoc, Tok.is(tok::comma) ? 
Tok.getLocation()3
:
RuleEndLoc5
));
1589
8
      continue;
1590
8
    }
1591
11.0k
  } while (IsAny && 
TryConsumeToken(tok::comma)10.9k
);
1592
1593
1.07k
  if (IsAny)
1594
993
    if (AnyParens.consumeClose())
1595
2
      return true;
1596
1597
1.07k
  return false;
1598
1.07k
}
1599
1600
namespace {
1601
1602
/// Describes the stage at which attribute subject rule parsing was interrupted.
1603
enum class MissingAttributeSubjectRulesRecoveryPoint {
1604
  Comma,
1605
  ApplyTo,
1606
  Equals,
1607
  Any,
1608
  None,
1609
};
1610
1611
MissingAttributeSubjectRulesRecoveryPoint
1612
42
getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1613
42
  if (const auto *II = Tok.getIdentifierInfo()) {
1614
17
    if (II->isStr("apply_to"))
1615
2
      return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1616
15
    if (II->isStr("any"))
1617
6
      return MissingAttributeSubjectRulesRecoveryPoint::Any;
1618
15
  }
1619
34
  if (Tok.is(tok::equal))
1620
5
    return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1621
29
  return MissingAttributeSubjectRulesRecoveryPoint::None;
1622
34
}
1623
1624
/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1625
/// suggests the possible attribute subject rules in a fix-it together with
1626
/// any other missing tokens.
1627
DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1628
    unsigned DiagID, ParsedAttributes &Attrs,
1629
42
    MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1630
42
  SourceLocation Loc = PRef.getEndOfPreviousToken();
1631
42
  if (Loc.isInvalid())
1632
0
    Loc = PRef.getCurToken().getLocation();
1633
42
  auto Diagnostic = PRef.Diag(Loc, DiagID);
1634
42
  std::string FixIt;
1635
42
  MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1636
42
      getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1637
42
  if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1638
19
    FixIt = ", ";
1639
42
  if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1640
42
      
EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo34
)
1641
32
    FixIt += "apply_to";
1642
42
  if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1643
42
      EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1644
35
    FixIt += " = ";
1645
42
  SourceRange FixItRange(Loc);
1646
42
  if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1647
    // Gather the subject match rules that are supported by the attribute.
1648
    // Add all the possible rules initially.
1649
29
    llvm::BitVector IsMatchRuleAvailable(attr::SubjectMatchRule_Last + 1, true);
1650
    // Remove the ones that are not supported by any of the attributes.
1651
30
    for (const ParsedAttr &Attribute : Attrs) {
1652
30
      SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> MatchRules;
1653
30
      Attribute.getMatchRules(PRef.getLangOpts(), MatchRules);
1654
30
      llvm::BitVector IsSupported(attr::SubjectMatchRule_Last + 1);
1655
76
      for (const auto &Rule : MatchRules) {
1656
        // Ensure that the missing rule is reported in the fix-it only when it's
1657
        // supported in the current language mode.
1658
76
        if (!Rule.second)
1659
4
          continue;
1660
72
        IsSupported[Rule.first] = true;
1661
72
      }
1662
30
      IsMatchRuleAvailable &= IsSupported;
1663
30
    }
1664
29
    if (IsMatchRuleAvailable.count() == 0) {
1665
      // FIXME: We can emit a "fix-it" with a subject list placeholder when
1666
      // placeholders will be supported by the fix-its.
1667
9
      return Diagnostic;
1668
9
    }
1669
20
    FixIt += "any(";
1670
20
    bool NeedsComma = false;
1671
520
    for (unsigned I = 0; I <= attr::SubjectMatchRule_Last; 
I++500
) {
1672
500
      if (!IsMatchRuleAvailable[I])
1673
429
        continue;
1674
71
      if (NeedsComma)
1675
51
        FixIt += ", ";
1676
20
      else
1677
20
        NeedsComma = true;
1678
71
      FixIt += attr::getSubjectMatchRuleSpelling(
1679
71
          static_cast<attr::SubjectMatchRule>(I));
1680
71
    }
1681
20
    FixIt += ")";
1682
    // Check if we need to remove the range
1683
20
    PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1684
20
    FixItRange.setEnd(PRef.getCurToken().getLocation());
1685
20
  }
1686
33
  if (FixItRange.getBegin() == FixItRange.getEnd())
1687
20
    Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1688
13
  else
1689
13
    Diagnostic << FixItHint::CreateReplacement(
1690
13
        CharSourceRange::getCharRange(FixItRange), FixIt);
1691
33
  return Diagnostic;
1692
42
}
1693
1694
} // end anonymous namespace
1695
1696
3.12k
void Parser::HandlePragmaAttribute() {
1697
3.12k
  assert(Tok.is(tok::annot_pragma_attribute) &&
1698
3.12k
         "Expected #pragma attribute annotation token");
1699
0
  SourceLocation PragmaLoc = Tok.getLocation();
1700
3.12k
  auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1701
3.12k
  if (Info->Action == PragmaAttributeInfo::Pop) {
1702
1.06k
    ConsumeAnnotationToken();
1703
1.06k
    Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
1704
1.06k
    return;
1705
1.06k
  }
1706
  // Parse the actual attribute with its arguments.
1707
2.06k
  assert((Info->Action == PragmaAttributeInfo::Push ||
1708
2.06k
          Info->Action == PragmaAttributeInfo::Attribute) &&
1709
2.06k
         "Unexpected #pragma attribute command");
1710
1711
2.06k
  if (Info->Action == PragmaAttributeInfo::Push && 
Info->Tokens.empty()1.17k
) {
1712
890
    ConsumeAnnotationToken();
1713
890
    Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1714
890
    return;
1715
890
  }
1716
1717
1.17k
  PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
1718
1.17k
                      /*IsReinject=*/false);
1719
1.17k
  ConsumeAnnotationToken();
1720
1721
1.17k
  ParsedAttributes &Attrs = Info->Attributes;
1722
1.17k
  Attrs.clearListOnly();
1723
1724
1.17k
  auto SkipToEnd = [this]() {
1725
102
    SkipUntil(tok::eof, StopBeforeMatch);
1726
102
    ConsumeToken();
1727
102
  };
1728
1729
1.17k
  if (Tok.is(tok::l_square) && 
NextToken().is(tok::l_square)30
) {
1730
    // Parse the CXX11 style attribute.
1731
30
    ParseCXX11AttributeSpecifier(Attrs);
1732
1.14k
  } else if (Tok.is(tok::kw___attribute)) {
1733
1.13k
    ConsumeToken();
1734
1.13k
    if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1735
1.13k
                         "attribute"))
1736
1
      return SkipToEnd();
1737
1.13k
    if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1738
1
      return SkipToEnd();
1739
1740
    // FIXME: The practical usefulness of completion here is limited because
1741
    // we only get here if the line has balanced parens.
1742
1.13k
    if (Tok.is(tok::code_completion)) {
1743
1
      cutOffParsing();
1744
      // FIXME: suppress completion of unsupported attributes?
1745
1
      Actions.CodeCompleteAttribute(AttributeCommonInfo::Syntax::AS_GNU);
1746
1
      return SkipToEnd();
1747
1
    }
1748
1749
    // Parse the comma-separated list of attributes.
1750
1.13k
    
do 1.12k
{
1751
1.13k
      if (Tok.isNot(tok::identifier)) {
1752
3
        Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1753
3
        SkipToEnd();
1754
3
        return;
1755
3
      }
1756
1.13k
      IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1757
1.13k
      SourceLocation AttrNameLoc = ConsumeToken();
1758
1759
1.13k
      if (Tok.isNot(tok::l_paren))
1760
40
        Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
1761
40
                     ParsedAttr::AS_GNU);
1762
1.09k
      else
1763
1.09k
        ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1764
1.09k
                              /*ScopeName=*/nullptr,
1765
1.09k
                              /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU,
1766
1.09k
                              /*Declarator=*/nullptr);
1767
1.13k
    } while (TryConsumeToken(tok::comma));
1768
1769
1.12k
    if (ExpectAndConsume(tok::r_paren))
1770
2
      return SkipToEnd();
1771
1.12k
    if (ExpectAndConsume(tok::r_paren))
1772
1
      return SkipToEnd();
1773
1.12k
  } else 
if (11
Tok.is(tok::kw___declspec)11
) {
1774
5
    ParseMicrosoftDeclSpecs(Attrs);
1775
6
  } else {
1776
6
    Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1777
6
    if (Tok.getIdentifierInfo()) {
1778
      // If we suspect that this is an attribute suggest the use of
1779
      // '__attribute__'.
1780
5
      if (ParsedAttr::getParsedKind(
1781
5
              Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1782
5
              ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
1783
4
        SourceLocation InsertStartLoc = Tok.getLocation();
1784
4
        ConsumeToken();
1785
4
        if (Tok.is(tok::l_paren)) {
1786
2
          ConsumeAnyToken();
1787
2
          SkipUntil(tok::r_paren, StopBeforeMatch);
1788
2
          if (Tok.isNot(tok::r_paren))
1789
0
            return SkipToEnd();
1790
2
        }
1791
4
        Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1792
4
            << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1793
4
            << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1794
4
      }
1795
5
    }
1796
6
    SkipToEnd();
1797
6
    return;
1798
6
  }
1799
1800
1.15k
  if (Attrs.empty() || 
Attrs.begin()->isInvalid()1.15k
) {
1801
4
    SkipToEnd();
1802
4
    return;
1803
4
  }
1804
1805
1.16k
  
for (const ParsedAttr &Attribute : Attrs)1.15k
{
1806
1.16k
    if (!Attribute.isSupportedByPragmaAttribute()) {
1807
5
      Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1808
5
          << Attribute;
1809
5
      SkipToEnd();
1810
5
      return;
1811
5
    }
1812
1.16k
  }
1813
1814
  // Parse the subject-list.
1815
1.14k
  if (!TryConsumeToken(tok::comma)) {
1816
19
    createExpectedAttributeSubjectRulesTokenDiagnostic(
1817
19
        diag::err_expected, Attrs,
1818
19
        MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1819
19
        << tok::comma;
1820
19
    SkipToEnd();
1821
19
    return;
1822
19
  }
1823
1824
1.13k
  if (Tok.isNot(tok::identifier)) {
1825
8
    createExpectedAttributeSubjectRulesTokenDiagnostic(
1826
8
        diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
1827
8
        MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1828
8
    SkipToEnd();
1829
8
    return;
1830
8
  }
1831
1.12k
  const IdentifierInfo *II = Tok.getIdentifierInfo();
1832
1.12k
  if (!II->isStr("apply_to")) {
1833
7
    createExpectedAttributeSubjectRulesTokenDiagnostic(
1834
7
        diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
1835
7
        MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1836
7
    SkipToEnd();
1837
7
    return;
1838
7
  }
1839
1.11k
  ConsumeToken();
1840
1841
1.11k
  if (!TryConsumeToken(tok::equal)) {
1842
8
    createExpectedAttributeSubjectRulesTokenDiagnostic(
1843
8
        diag::err_expected, Attrs,
1844
8
        MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1845
8
        << tok::equal;
1846
8
    SkipToEnd();
1847
8
    return;
1848
8
  }
1849
1850
1.10k
  attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1851
1.10k
  SourceLocation AnyLoc, LastMatchRuleEndLoc;
1852
1.10k
  if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1853
1.10k
                                              LastMatchRuleEndLoc)) {
1854
35
    SkipToEnd();
1855
35
    return;
1856
35
  }
1857
1858
  // Tokens following an ill-formed attribute will remain in the token stream
1859
  // and must be removed.
1860
1.07k
  if (Tok.isNot(tok::eof)) {
1861
1
    Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1862
1
    SkipToEnd();
1863
1
    return;
1864
1
  }
1865
1866
  // Consume the eof terminator token.
1867
1.07k
  ConsumeToken();
1868
1869
  // Handle a mixed push/attribute by desurging to a push, then an attribute.
1870
1.07k
  if (Info->Action == PragmaAttributeInfo::Push)
1871
180
    Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1872
1873
1.07k
  for (ParsedAttr &Attribute : Attrs) {
1874
1.07k
    Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
1875
1.07k
                                          SubjectMatchRules);
1876
1.07k
  }
1877
1.07k
}
1878
1879
// #pragma GCC visibility comes in two variants:
1880
//   'push' '(' [visibility] ')'
1881
//   'pop'
1882
void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
1883
                                              PragmaIntroducer Introducer,
1884
130
                                              Token &VisTok) {
1885
130
  SourceLocation VisLoc = VisTok.getLocation();
1886
1887
130
  Token Tok;
1888
130
  PP.LexUnexpandedToken(Tok);
1889
1890
130
  const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1891
1892
130
  const IdentifierInfo *VisType;
1893
130
  if (PushPop && PushPop->isStr("pop")) {
1894
62
    VisType = nullptr;
1895
68
  } else if (PushPop && PushPop->isStr("push")) {
1896
67
    PP.LexUnexpandedToken(Tok);
1897
67
    if (Tok.isNot(tok::l_paren)) {
1898
1
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1899
1
        << "visibility";
1900
1
      return;
1901
1
    }
1902
66
    PP.LexUnexpandedToken(Tok);
1903
66
    VisType = Tok.getIdentifierInfo();
1904
66
    if (!VisType) {
1905
1
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1906
1
        << "visibility";
1907
1
      return;
1908
1
    }
1909
65
    PP.LexUnexpandedToken(Tok);
1910
65
    if (Tok.isNot(tok::r_paren)) {
1911
1
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1912
1
        << "visibility";
1913
1
      return;
1914
1
    }
1915
65
  } else {
1916
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1917
1
      << "visibility";
1918
1
    return;
1919
1
  }
1920
126
  SourceLocation EndLoc = Tok.getLocation();
1921
126
  PP.LexUnexpandedToken(Tok);
1922
126
  if (Tok.isNot(tok::eod)) {
1923
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1924
1
      << "visibility";
1925
1
    return;
1926
1
  }
1927
1928
125
  auto Toks = std::make_unique<Token[]>(1);
1929
125
  Toks[0].startToken();
1930
125
  Toks[0].setKind(tok::annot_pragma_vis);
1931
125
  Toks[0].setLocation(VisLoc);
1932
125
  Toks[0].setAnnotationEndLoc(EndLoc);
1933
125
  Toks[0].setAnnotationValue(
1934
125
      const_cast<void *>(static_cast<const void *>(VisType)));
1935
125
  PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
1936
125
                      /*IsReinject=*/false);
1937
125
}
1938
1939
// #pragma pack(...) comes in the following delicious flavors:
1940
//   pack '(' [integer] ')'
1941
//   pack '(' 'show' ')'
1942
//   pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
1943
void PragmaPackHandler::HandlePragma(Preprocessor &PP,
1944
                                     PragmaIntroducer Introducer,
1945
259k
                                     Token &PackTok) {
1946
259k
  SourceLocation PackLoc = PackTok.getLocation();
1947
1948
259k
  Token Tok;
1949
259k
  PP.Lex(Tok);
1950
259k
  if (Tok.isNot(tok::l_paren)) {
1951
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
1952
1
    return;
1953
1
  }
1954
1955
259k
  Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1956
259k
  StringRef SlotLabel;
1957
259k
  Token Alignment;
1958
259k
  Alignment.startToken();
1959
259k
  PP.Lex(Tok);
1960
259k
  if (Tok.is(tok::numeric_constant)) {
1961
2.08k
    Alignment = Tok;
1962
1963
2.08k
    PP.Lex(Tok);
1964
1965
    // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1966
    // the push/pop stack.
1967
    // In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4)
1968
2.08k
    Action = (PP.getLangOpts().ApplePragmaPack || 
PP.getLangOpts().XLPragmaPack2.08k
)
1969
2.08k
                 ? 
Sema::PSK_Push_Set61
1970
2.08k
                 : 
Sema::PSK_Set2.02k
;
1971
257k
  } else if (Tok.is(tok::identifier)) {
1972
255k
    const IdentifierInfo *II = Tok.getIdentifierInfo();
1973
255k
    if (II->isStr("show")) {
1974
80
      Action = Sema::PSK_Show;
1975
80
      PP.Lex(Tok);
1976
255k
    } else {
1977
255k
      if (II->isStr("push")) {
1978
127k
        Action = Sema::PSK_Push;
1979
127k
      } else if (II->isStr("pop")) {
1980
127k
        Action = Sema::PSK_Pop;
1981
127k
      } else {
1982
1
        PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
1983
1
        return;
1984
1
      }
1985
255k
      PP.Lex(Tok);
1986
1987
255k
      if (Tok.is(tok::comma)) {
1988
127k
        PP.Lex(Tok);
1989
1990
127k
        if (Tok.is(tok::numeric_constant)) {
1991
127k
          Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
1992
127k
          Alignment = Tok;
1993
1994
127k
          PP.Lex(Tok);
1995
127k
        } else 
if (28
Tok.is(tok::identifier)28
) {
1996
24
          SlotLabel = Tok.getIdentifierInfo()->getName();
1997
24
          PP.Lex(Tok);
1998
1999
24
          if (Tok.is(tok::comma)) {
2000
14
            PP.Lex(Tok);
2001
2002
14
            if (Tok.isNot(tok::numeric_constant)) {
2003
3
              PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
2004
3
              return;
2005
3
            }
2006
2007
11
            Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
2008
11
            Alignment = Tok;
2009
2010
11
            PP.Lex(Tok);
2011
11
          }
2012
24
        } else {
2013
4
          PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
2014
4
          return;
2015
4
        }
2016
127k
      }
2017
255k
    }
2018
255k
  } else 
if (1.88k
PP.getLangOpts().ApplePragmaPack1.88k
||
2019
1.88k
             
PP.getLangOpts().XLPragmaPack1.88k
) {
2020
    // In MSVC/gcc, #pragma pack() resets the alignment without affecting
2021
    // the push/pop stack.
2022
    // In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma
2023
    // pack(pop).
2024
11
    Action = Sema::PSK_Pop;
2025
11
  }
2026
2027
259k
  if (Tok.isNot(tok::r_paren)) {
2028
4
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
2029
4
    return;
2030
4
  }
2031
2032
259k
  SourceLocation RParenLoc = Tok.getLocation();
2033
259k
  PP.Lex(Tok);
2034
259k
  if (Tok.isNot(tok::eod)) {
2035
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
2036
0
    return;
2037
0
  }
2038
2039
259k
  PragmaPackInfo *Info =
2040
259k
      PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
2041
259k
  Info->Action = Action;
2042
259k
  Info->SlotLabel = SlotLabel;
2043
259k
  Info->Alignment = Alignment;
2044
2045
259k
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2046
259k
                              1);
2047
259k
  Toks[0].startToken();
2048
259k
  Toks[0].setKind(tok::annot_pragma_pack);
2049
259k
  Toks[0].setLocation(PackLoc);
2050
259k
  Toks[0].setAnnotationEndLoc(RParenLoc);
2051
259k
  Toks[0].setAnnotationValue(static_cast<void*>(Info));
2052
259k
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2053
259k
                      /*IsReinject=*/false);
2054
259k
}
2055
2056
// #pragma ms_struct on
2057
// #pragma ms_struct off
2058
void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
2059
                                         PragmaIntroducer Introducer,
2060
16
                                         Token &MSStructTok) {
2061
16
  PragmaMSStructKind Kind = PMSST_OFF;
2062
2063
16
  Token Tok;
2064
16
  PP.Lex(Tok);
2065
16
  if (Tok.isNot(tok::identifier)) {
2066
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
2067
1
    return;
2068
1
  }
2069
15
  SourceLocation EndLoc = Tok.getLocation();
2070
15
  const IdentifierInfo *II = Tok.getIdentifierInfo();
2071
15
  if (II->isStr("on")) {
2072
11
    Kind = PMSST_ON;
2073
11
    PP.Lex(Tok);
2074
11
  }
2075
4
  else if (II->isStr("off") || 
II->isStr("reset")1
)
2076
4
    PP.Lex(Tok);
2077
0
  else {
2078
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
2079
0
    return;
2080
0
  }
2081
2082
15
  if (Tok.isNot(tok::eod)) {
2083
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2084
1
      << "ms_struct";
2085
1
    return;
2086
1
  }
2087
2088
14
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2089
14
                              1);
2090
14
  Toks[0].startToken();
2091
14
  Toks[0].setKind(tok::annot_pragma_msstruct);
2092
14
  Toks[0].setLocation(MSStructTok.getLocation());
2093
14
  Toks[0].setAnnotationEndLoc(EndLoc);
2094
14
  Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2095
14
                             static_cast<uintptr_t>(Kind)));
2096
14
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2097
14
                      /*IsReinject=*/false);
2098
14
}
2099
2100
// #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
2101
void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
2102
                                             PragmaIntroducer Introducer,
2103
63
                                             Token &FirstToken) {
2104
2105
63
  Token Tok;
2106
63
  auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
2107
2108
63
  PP.Lex(Tok); // eat 'section'
2109
154
  while (Tok.isNot(tok::eod)) {
2110
102
    if (Tok.isNot(tok::identifier)) {
2111
0
      PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
2112
0
      return;
2113
0
    }
2114
2115
102
    const IdentifierInfo *SecType = Tok.getIdentifierInfo();
2116
102
    if (SecType->isStr("bss"))
2117
25
      SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
2118
77
    else if (SecType->isStr("data"))
2119
22
      SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
2120
55
    else if (SecType->isStr("rodata"))
2121
23
      SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
2122
32
    else if (SecType->isStr("relro"))
2123
3
      SecKind = Sema::PragmaClangSectionKind::PCSK_Relro;
2124
29
    else if (SecType->isStr("text"))
2125
23
      SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
2126
6
    else {
2127
6
      PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
2128
6
      return;
2129
6
    }
2130
2131
96
    SourceLocation PragmaLocation = Tok.getLocation();
2132
96
    PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
2133
96
    if (Tok.isNot(tok::equal)) {
2134
5
      PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
2135
5
      return;
2136
5
    }
2137
2138
91
    std::string SecName;
2139
91
    if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
2140
0
      return;
2141
2142
91
    Actions.ActOnPragmaClangSection(
2143
91
        PragmaLocation,
2144
91
        (SecName.size() ? 
Sema::PragmaClangSectionAction::PCSA_Set46
2145
91
                        : 
Sema::PragmaClangSectionAction::PCSA_Clear45
),
2146
91
        SecKind, SecName);
2147
91
  }
2148
63
}
2149
2150
// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
2151
// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
2152
// #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'
2153
static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
2154
2.82k
                             bool IsOptions) {
2155
2.82k
  Token Tok;
2156
2157
2.82k
  if (IsOptions) {
2158
2.72k
    PP.Lex(Tok);
2159
2.72k
    if (Tok.isNot(tok::identifier) ||
2160
2.72k
        
!Tok.getIdentifierInfo()->isStr("align")2.72k
) {
2161
1
      PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
2162
1
      return;
2163
1
    }
2164
2.72k
  }
2165
2166
2.82k
  PP.Lex(Tok);
2167
2.82k
  if (PP.getLangOpts().XLPragmaPack) {
2168
86
    if (Tok.isNot(tok::l_paren)) {
2169
2
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align";
2170
2
      return;
2171
2
    }
2172
2.73k
  } else if (Tok.isNot(tok::equal)) {
2173
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
2174
2
      << IsOptions;
2175
2
    return;
2176
2
  }
2177
2178
2.81k
  PP.Lex(Tok);
2179
2.81k
  if (Tok.isNot(tok::identifier)) {
2180
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2181
2
      << (IsOptions ? 
"options"1
:
"align"1
);
2182
2
    return;
2183
2
  }
2184
2185
2.81k
  Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
2186
2.81k
  const IdentifierInfo *II = Tok.getIdentifierInfo();
2187
2.81k
  if (II->isStr("native"))
2188
1
    Kind = Sema::POAK_Native;
2189
2.81k
  else if (II->isStr("natural"))
2190
29
    Kind = Sema::POAK_Natural;
2191
2.78k
  else if (II->isStr("packed"))
2192
25
    Kind = Sema::POAK_Packed;
2193
2.75k
  else if (II->isStr("power"))
2194
1.34k
    Kind = Sema::POAK_Power;
2195
1.41k
  else if (II->isStr("mac68k"))
2196
9
    Kind = Sema::POAK_Mac68k;
2197
1.40k
  else if (II->isStr("reset"))
2198
1.40k
    Kind = Sema::POAK_Reset;
2199
2
  else {
2200
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
2201
2
      << IsOptions;
2202
2
    return;
2203
2
  }
2204
2205
2.81k
  if (PP.getLangOpts().XLPragmaPack) {
2206
84
    PP.Lex(Tok);
2207
84
    if (Tok.isNot(tok::r_paren)) {
2208
0
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align";
2209
0
      return;
2210
0
    }
2211
84
  }
2212
2213
2.81k
  SourceLocation EndLoc = Tok.getLocation();
2214
2.81k
  PP.Lex(Tok);
2215
2.81k
  if (Tok.isNot(tok::eod)) {
2216
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2217
2
      << (IsOptions ? 
"options"1
:
"align"1
);
2218
2
    return;
2219
2
  }
2220
2221
2.81k
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2222
2.81k
                              1);
2223
2.81k
  Toks[0].startToken();
2224
2.81k
  Toks[0].setKind(tok::annot_pragma_align);
2225
2.81k
  Toks[0].setLocation(FirstTok.getLocation());
2226
2.81k
  Toks[0].setAnnotationEndLoc(EndLoc);
2227
2.81k
  Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2228
2.81k
                             static_cast<uintptr_t>(Kind)));
2229
2.81k
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2230
2.81k
                      /*IsReinject=*/false);
2231
2.81k
}
2232
2233
void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
2234
                                      PragmaIntroducer Introducer,
2235
100
                                      Token &AlignTok) {
2236
100
  ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
2237
100
}
2238
2239
void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
2240
                                        PragmaIntroducer Introducer,
2241
2.72k
                                        Token &OptionsTok) {
2242
2.72k
  ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
2243
2.72k
}
2244
2245
// #pragma unused(identifier)
2246
void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
2247
                                       PragmaIntroducer Introducer,
2248
23
                                       Token &UnusedTok) {
2249
  // FIXME: Should we be expanding macros here? My guess is no.
2250
23
  SourceLocation UnusedLoc = UnusedTok.getLocation();
2251
2252
  // Lex the left '('.
2253
23
  Token Tok;
2254
23
  PP.Lex(Tok);
2255
23
  if (Tok.isNot(tok::l_paren)) {
2256
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
2257
1
    return;
2258
1
  }
2259
2260
  // Lex the declaration reference(s).
2261
22
  SmallVector<Token, 5> Identifiers;
2262
22
  SourceLocation RParenLoc;
2263
22
  bool LexID = true;
2264
2265
55
  while (true) {
2266
55
    PP.Lex(Tok);
2267
2268
55
    if (LexID) {
2269
29
      if (Tok.is(tok::identifier)) {
2270
26
        Identifiers.push_back(Tok);
2271
26
        LexID = false;
2272
26
        continue;
2273
26
      }
2274
2275
      // Illegal token!
2276
3
      PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
2277
3
      return;
2278
29
    }
2279
2280
    // We are execting a ')' or a ','.
2281
26
    if (Tok.is(tok::comma)) {
2282
7
      LexID = true;
2283
7
      continue;
2284
7
    }
2285
2286
19
    if (Tok.is(tok::r_paren)) {
2287
19
      RParenLoc = Tok.getLocation();
2288
19
      break;
2289
19
    }
2290
2291
    // Illegal token!
2292
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
2293
0
    return;
2294
19
  }
2295
2296
19
  PP.Lex(Tok);
2297
19
  if (Tok.isNot(tok::eod)) {
2298
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2299
0
        "unused";
2300
0
    return;
2301
0
  }
2302
2303
  // Verify that we have a location for the right parenthesis.
2304
19
  assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
2305
0
  assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
2306
2307
  // For each identifier token, insert into the token stream a
2308
  // annot_pragma_unused token followed by the identifier token.
2309
  // This allows us to cache a "#pragma unused" that occurs inside an inline
2310
  // C++ member function.
2311
2312
0
  MutableArrayRef<Token> Toks(
2313
19
      PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
2314
19
      2 * Identifiers.size());
2315
44
  for (unsigned i=0; i != Identifiers.size(); 
i++25
) {
2316
25
    Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
2317
25
    pragmaUnusedTok.startToken();
2318
25
    pragmaUnusedTok.setKind(tok::annot_pragma_unused);
2319
25
    pragmaUnusedTok.setLocation(UnusedLoc);
2320
25
    idTok = Identifiers[i];
2321
25
  }
2322
19
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2323
19
                      /*IsReinject=*/false);
2324
19
}
2325
2326
// #pragma weak identifier
2327
// #pragma weak identifier '=' identifier
2328
void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
2329
                                     PragmaIntroducer Introducer,
2330
132
                                     Token &WeakTok) {
2331
132
  SourceLocation WeakLoc = WeakTok.getLocation();
2332
2333
132
  Token Tok;
2334
132
  PP.Lex(Tok);
2335
132
  if (Tok.isNot(tok::identifier)) {
2336
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
2337
1
    return;
2338
1
  }
2339
2340
131
  Token WeakName = Tok;
2341
131
  bool HasAlias = false;
2342
131
  Token AliasName;
2343
2344
131
  PP.Lex(Tok);
2345
131
  if (Tok.is(tok::equal)) {
2346
38
    HasAlias = true;
2347
38
    PP.Lex(Tok);
2348
38
    if (Tok.isNot(tok::identifier)) {
2349
2
      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2350
2
          << "weak";
2351
2
      return;
2352
2
    }
2353
36
    AliasName = Tok;
2354
36
    PP.Lex(Tok);
2355
36
  }
2356
2357
129
  if (Tok.isNot(tok::eod)) {
2358
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
2359
2
    return;
2360
2
  }
2361
2362
127
  if (HasAlias) {
2363
35
    MutableArrayRef<Token> Toks(
2364
35
        PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
2365
35
    Token &pragmaUnusedTok = Toks[0];
2366
35
    pragmaUnusedTok.startToken();
2367
35
    pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
2368
35
    pragmaUnusedTok.setLocation(WeakLoc);
2369
35
    pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
2370
35
    Toks[1] = WeakName;
2371
35
    Toks[2] = AliasName;
2372
35
    PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2373
35
                        /*IsReinject=*/false);
2374
92
  } else {
2375
92
    MutableArrayRef<Token> Toks(
2376
92
        PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
2377
92
    Token &pragmaUnusedTok = Toks[0];
2378
92
    pragmaUnusedTok.startToken();
2379
92
    pragmaUnusedTok.setKind(tok::annot_pragma_weak);
2380
92
    pragmaUnusedTok.setLocation(WeakLoc);
2381
92
    pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
2382
92
    Toks[1] = WeakName;
2383
92
    PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2384
92
                        /*IsReinject=*/false);
2385
92
  }
2386
127
}
2387
2388
// #pragma redefine_extname identifier identifier
2389
void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
2390
                                                PragmaIntroducer Introducer,
2391
11
                                                Token &RedefToken) {
2392
11
  SourceLocation RedefLoc = RedefToken.getLocation();
2393
2394
11
  Token Tok;
2395
11
  PP.Lex(Tok);
2396
11
  if (Tok.isNot(tok::identifier)) {
2397
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2398
0
      "redefine_extname";
2399
0
    return;
2400
0
  }
2401
2402
11
  Token RedefName = Tok;
2403
11
  PP.Lex(Tok);
2404
2405
11
  if (Tok.isNot(tok::identifier)) {
2406
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2407
0
        << "redefine_extname";
2408
0
    return;
2409
0
  }
2410
2411
11
  Token AliasName = Tok;
2412
11
  PP.Lex(Tok);
2413
2414
11
  if (Tok.isNot(tok::eod)) {
2415
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2416
0
      "redefine_extname";
2417
0
    return;
2418
0
  }
2419
2420
11
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
2421
11
                              3);
2422
11
  Token &pragmaRedefTok = Toks[0];
2423
11
  pragmaRedefTok.startToken();
2424
11
  pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2425
11
  pragmaRedefTok.setLocation(RedefLoc);
2426
11
  pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
2427
11
  Toks[1] = RedefName;
2428
11
  Toks[2] = AliasName;
2429
11
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2430
11
                      /*IsReinject=*/false);
2431
11
}
2432
2433
void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2434
                                           PragmaIntroducer Introducer,
2435
43
                                           Token &Tok) {
2436
43
  tok::OnOffSwitch OOS;
2437
43
  if (PP.LexOnOffSwitch(OOS))
2438
2
    return;
2439
2440
41
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2441
41
                              1);
2442
41
  Toks[0].startToken();
2443
41
  Toks[0].setKind(tok::annot_pragma_fp_contract);
2444
41
  Toks[0].setLocation(Tok.getLocation());
2445
41
  Toks[0].setAnnotationEndLoc(Tok.getLocation());
2446
41
  Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2447
41
                             static_cast<uintptr_t>(OOS)));
2448
41
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2449
41
                      /*IsReinject=*/false);
2450
41
}
2451
2452
void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2453
                                                PragmaIntroducer Introducer,
2454
1.81k
                                                Token &Tok) {
2455
1.81k
  PP.LexUnexpandedToken(Tok);
2456
1.81k
  if (Tok.isNot(tok::identifier)) {
2457
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2458
0
      "OPENCL";
2459
0
    return;
2460
0
  }
2461
1.81k
  IdentifierInfo *Ext = Tok.getIdentifierInfo();
2462
1.81k
  SourceLocation NameLoc = Tok.getLocation();
2463
2464
1.81k
  PP.Lex(Tok);
2465
1.81k
  if (Tok.isNot(tok::colon)) {
2466
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
2467
0
    return;
2468
0
  }
2469
2470
1.81k
  PP.Lex(Tok);
2471
1.81k
  if (Tok.isNot(tok::identifier)) {
2472
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
2473
0
    return;
2474
0
  }
2475
1.81k
  IdentifierInfo *Pred = Tok.getIdentifierInfo();
2476
2477
1.81k
  OpenCLExtState State;
2478
1.81k
  if (Pred->isStr("enable")) {
2479
1.43k
    State = Enable;
2480
1.43k
  } else 
if (388
Pred->isStr("disable")388
) {
2481
319
    State = Disable;
2482
319
  } else 
if (69
Pred->isStr("begin")69
)
2483
32
    State = Begin;
2484
37
  else if (Pred->isStr("end"))
2485
36
    State = End;
2486
1
  else {
2487
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2488
1
      << Ext->isStr("all");
2489
1
    return;
2490
1
  }
2491
1.81k
  SourceLocation StateLoc = Tok.getLocation();
2492
2493
1.81k
  PP.Lex(Tok);
2494
1.81k
  if (Tok.isNot(tok::eod)) {
2495
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2496
0
      "OPENCL EXTENSION";
2497
0
    return;
2498
0
  }
2499
2500
1.81k
  auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2501
1.81k
  Info->first = Ext;
2502
1.81k
  Info->second = State;
2503
1.81k
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2504
1.81k
                              1);
2505
1.81k
  Toks[0].startToken();
2506
1.81k
  Toks[0].setKind(tok::annot_pragma_opencl_extension);
2507
1.81k
  Toks[0].setLocation(NameLoc);
2508
1.81k
  Toks[0].setAnnotationValue(static_cast<void*>(Info));
2509
1.81k
  Toks[0].setAnnotationEndLoc(StateLoc);
2510
1.81k
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2511
1.81k
                      /*IsReinject=*/false);
2512
2513
1.81k
  if (PP.getPPCallbacks())
2514
1.81k
    PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2515
1.81k
                                               StateLoc, State);
2516
1.81k
}
2517
2518
/// Handle '#pragma omp ...' when OpenMP is disabled.
2519
///
2520
void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2521
                                         PragmaIntroducer Introducer,
2522
95
                                         Token &FirstTok) {
2523
95
  if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2524
95
                                     FirstTok.getLocation())) {
2525
2
    PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
2526
2
    PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2527
2
                                    diag::Severity::Ignored, SourceLocation());
2528
2
  }
2529
95
  PP.DiscardUntilEndOfDirective();
2530
95
}
2531
2532
/// Handle '#pragma omp ...' when OpenMP is enabled.
2533
///
2534
void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2535
                                       PragmaIntroducer Introducer,
2536
273k
                                       Token &FirstTok) {
2537
273k
  SmallVector<Token, 16> Pragma;
2538
273k
  Token Tok;
2539
273k
  Tok.startToken();
2540
273k
  Tok.setKind(tok::annot_pragma_openmp);
2541
273k
  Tok.setLocation(Introducer.Loc);
2542
2543
2.24M
  while (Tok.isNot(tok::eod) && 
Tok.isNot(tok::eof)1.97M
) {
2544
1.97M
    Pragma.push_back(Tok);
2545
1.97M
    PP.Lex(Tok);
2546
1.97M
    if (Tok.is(tok::annot_pragma_openmp)) {
2547
6
      PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
2548
6
      unsigned InnerPragmaCnt = 1;
2549
18
      while (InnerPragmaCnt != 0) {
2550
12
        PP.Lex(Tok);
2551
12
        if (Tok.is(tok::annot_pragma_openmp))
2552
0
          ++InnerPragmaCnt;
2553
12
        else if (Tok.is(tok::annot_pragma_openmp_end))
2554
6
          --InnerPragmaCnt;
2555
12
      }
2556
6
      PP.Lex(Tok);
2557
6
    }
2558
1.97M
  }
2559
273k
  SourceLocation EodLoc = Tok.getLocation();
2560
273k
  Tok.startToken();
2561
273k
  Tok.setKind(tok::annot_pragma_openmp_end);
2562
273k
  Tok.setLocation(EodLoc);
2563
273k
  Pragma.push_back(Tok);
2564
2565
273k
  auto Toks = std::make_unique<Token[]>(Pragma.size());
2566
273k
  std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2567
273k
  PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2568
273k
                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2569
273k
}
2570
2571
/// Handle '#pragma pointers_to_members'
2572
// The grammar for this pragma is as follows:
2573
//
2574
// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2575
//
2576
// #pragma pointers_to_members '(' 'best_case' ')'
2577
// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2578
// #pragma pointers_to_members '(' inheritance-model ')'
2579
void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2580
                                             PragmaIntroducer Introducer,
2581
27
                                             Token &Tok) {
2582
27
  SourceLocation PointersToMembersLoc = Tok.getLocation();
2583
27
  PP.Lex(Tok);
2584
27
  if (Tok.isNot(tok::l_paren)) {
2585
0
    PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2586
0
      << "pointers_to_members";
2587
0
    return;
2588
0
  }
2589
27
  PP.Lex(Tok);
2590
27
  const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2591
27
  if (!Arg) {
2592
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2593
0
      << "pointers_to_members";
2594
0
    return;
2595
0
  }
2596
27
  PP.Lex(Tok);
2597
2598
27
  LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
2599
27
  if (Arg->isStr("best_case")) {
2600
10
    RepresentationMethod = LangOptions::PPTMK_BestCase;
2601
17
  } else {
2602
17
    if (Arg->isStr("full_generality")) {
2603
13
      if (Tok.is(tok::comma)) {
2604
13
        PP.Lex(Tok);
2605
2606
13
        Arg = Tok.getIdentifierInfo();
2607
13
        if (!Arg) {
2608
0
          PP.Diag(Tok.getLocation(),
2609
0
                  diag::err_pragma_pointers_to_members_unknown_kind)
2610
0
              << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2611
0
          return;
2612
0
        }
2613
13
        PP.Lex(Tok);
2614
13
      } else 
if (0
Tok.is(tok::r_paren)0
) {
2615
        // #pragma pointers_to_members(full_generality) implicitly specifies
2616
        // virtual_inheritance.
2617
0
        Arg = nullptr;
2618
0
        RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
2619
0
      } else {
2620
0
        PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2621
0
            << "full_generality";
2622
0
        return;
2623
0
      }
2624
13
    }
2625
2626
17
    if (Arg) {
2627
17
      if (Arg->isStr("single_inheritance")) {
2628
2
        RepresentationMethod =
2629
2
            LangOptions::PPTMK_FullGeneralitySingleInheritance;
2630
15
      } else if (Arg->isStr("multiple_inheritance")) {
2631
2
        RepresentationMethod =
2632
2
            LangOptions::PPTMK_FullGeneralityMultipleInheritance;
2633
13
      } else if (Arg->isStr("virtual_inheritance")) {
2634
11
        RepresentationMethod =
2635
11
            LangOptions::PPTMK_FullGeneralityVirtualInheritance;
2636
11
      } else {
2637
2
        PP.Diag(Tok.getLocation(),
2638
2
                diag::err_pragma_pointers_to_members_unknown_kind)
2639
2
            << Arg << /*HasPointerDeclaration*/ 1;
2640
2
        return;
2641
2
      }
2642
17
    }
2643
17
  }
2644
2645
25
  if (Tok.isNot(tok::r_paren)) {
2646
0
    PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2647
0
        << (Arg ? Arg->getName() : "full_generality");
2648
0
    return;
2649
0
  }
2650
2651
25
  SourceLocation EndLoc = Tok.getLocation();
2652
25
  PP.Lex(Tok);
2653
25
  if (Tok.isNot(tok::eod)) {
2654
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2655
0
      << "pointers_to_members";
2656
0
    return;
2657
0
  }
2658
2659
25
  Token AnnotTok;
2660
25
  AnnotTok.startToken();
2661
25
  AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2662
25
  AnnotTok.setLocation(PointersToMembersLoc);
2663
25
  AnnotTok.setAnnotationEndLoc(EndLoc);
2664
25
  AnnotTok.setAnnotationValue(
2665
25
      reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2666
25
  PP.EnterToken(AnnotTok, /*IsReinject=*/true);
2667
25
}
2668
2669
/// Handle '#pragma vtordisp'
2670
// The grammar for this pragma is as follows:
2671
//
2672
// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2673
//
2674
// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2675
// #pragma vtordisp '(' 'pop' ')'
2676
// #pragma vtordisp '(' ')'
2677
void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2678
52
                                    PragmaIntroducer Introducer, Token &Tok) {
2679
52
  SourceLocation VtorDispLoc = Tok.getLocation();
2680
52
  PP.Lex(Tok);
2681
52
  if (Tok.isNot(tok::l_paren)) {
2682
1
    PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2683
1
    return;
2684
1
  }
2685
51
  PP.Lex(Tok);
2686
2687
51
  Sema::PragmaMsStackAction Action = Sema::PSK_Set;
2688
51
  const IdentifierInfo *II = Tok.getIdentifierInfo();
2689
51
  if (II) {
2690
41
    if (II->isStr("push")) {
2691
      // #pragma vtordisp(push, mode)
2692
20
      PP.Lex(Tok);
2693
20
      if (Tok.isNot(tok::comma)) {
2694
0
        PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2695
0
        return;
2696
0
      }
2697
20
      PP.Lex(Tok);
2698
20
      Action = Sema::PSK_Push_Set;
2699
      // not push, could be on/off
2700
21
    } else if (II->isStr("pop")) {
2701
      // #pragma vtordisp(pop)
2702
20
      PP.Lex(Tok);
2703
20
      Action = Sema::PSK_Pop;
2704
20
    }
2705
    // not push or pop, could be on/off
2706
41
  } else {
2707
10
    if (Tok.is(tok::r_paren)) {
2708
      // #pragma vtordisp()
2709
4
      Action = Sema::PSK_Reset;
2710
4
    }
2711
10
  }
2712
2713
2714
51
  uint64_t Value = 0;
2715
51
  if (Action & Sema::PSK_Push || 
Action & Sema::PSK_Set31
) {
2716
27
    const IdentifierInfo *II = Tok.getIdentifierInfo();
2717
27
    if (II && 
II->isStr("off")1
) {
2718
0
      PP.Lex(Tok);
2719
0
      Value = 0;
2720
27
    } else if (II && 
II->isStr("on")1
) {
2721
0
      PP.Lex(Tok);
2722
0
      Value = 1;
2723
27
    } else if (Tok.is(tok::numeric_constant) &&
2724
27
               
PP.parseSimpleIntegerLiteral(Tok, Value)24
) {
2725
24
      if (Value > 2) {
2726
2
        PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2727
2
            << 0 << 2 << "vtordisp";
2728
2
        return;
2729
2
      }
2730
24
    } else {
2731
3
      PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2732
3
          << "vtordisp";
2733
3
      return;
2734
3
    }
2735
27
  }
2736
2737
  // Finish the pragma: ')' $
2738
46
  if (Tok.isNot(tok::r_paren)) {
2739
0
    PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2740
0
    return;
2741
0
  }
2742
46
  SourceLocation EndLoc = Tok.getLocation();
2743
46
  PP.Lex(Tok);
2744
46
  if (Tok.isNot(tok::eod)) {
2745
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2746
1
        << "vtordisp";
2747
1
    return;
2748
1
  }
2749
2750
  // Enter the annotation.
2751
45
  Token AnnotTok;
2752
45
  AnnotTok.startToken();
2753
45
  AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2754
45
  AnnotTok.setLocation(VtorDispLoc);
2755
45
  AnnotTok.setAnnotationEndLoc(EndLoc);
2756
45
  AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
2757
45
      static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
2758
45
  PP.EnterToken(AnnotTok, /*IsReinject=*/false);
2759
45
}
2760
2761
/// Handle all MS pragmas.  Simply forwards the tokens after inserting
2762
/// an annotation token.
2763
void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2764
197
                                  PragmaIntroducer Introducer, Token &Tok) {
2765
197
  Token EoF, AnnotTok;
2766
197
  EoF.startToken();
2767
197
  EoF.setKind(tok::eof);
2768
197
  AnnotTok.startToken();
2769
197
  AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2770
197
  AnnotTok.setLocation(Tok.getLocation());
2771
197
  AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2772
197
  SmallVector<Token, 8> TokenVector;
2773
  // Suck up all of the tokens before the eod.
2774
1.18k
  for (; Tok.isNot(tok::eod); 
PP.Lex(Tok)986
) {
2775
986
    TokenVector.push_back(Tok);
2776
986
    AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2777
986
  }
2778
  // Add a sentinel EoF token to the end of the list.
2779
197
  TokenVector.push_back(EoF);
2780
  // We must allocate this array with new because EnterTokenStream is going to
2781
  // delete it later.
2782
197
  markAsReinjectedForRelexing(TokenVector);
2783
197
  auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
2784
197
  std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
2785
197
  auto Value = new (PP.getPreprocessorAllocator())
2786
197
      std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2787
197
                                                  TokenVector.size());
2788
197
  AnnotTok.setAnnotationValue(Value);
2789
197
  PP.EnterToken(AnnotTok, /*IsReinject*/ false);
2790
197
}
2791
2792
/// Handle the \#pragma float_control extension.
2793
///
2794
/// The syntax is:
2795
/// \code
2796
///   #pragma float_control(keyword[, setting] [,push])
2797
/// \endcode
2798
/// Where 'keyword' and 'setting' are identifiers.
2799
// 'keyword' can be: precise, except, push, pop
2800
// 'setting' can be: on, off
2801
/// The optional arguments 'setting' and 'push' are supported only
2802
/// when the keyword is 'precise' or 'except'.
2803
void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
2804
                                             PragmaIntroducer Introducer,
2805
485
                                             Token &Tok) {
2806
485
  Sema::PragmaMsStackAction Action = Sema::PSK_Set;
2807
485
  SourceLocation FloatControlLoc = Tok.getLocation();
2808
485
  Token PragmaName = Tok;
2809
485
  if (!PP.getTargetInfo().hasStrictFP() && 
!PP.getLangOpts().ExpStrictFP12
) {
2810
3
    PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
2811
3
        << PragmaName.getIdentifierInfo()->getName();
2812
3
    return;
2813
3
  }
2814
482
  PP.Lex(Tok);
2815
482
  if (Tok.isNot(tok::l_paren)) {
2816
0
    PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
2817
0
    return;
2818
0
  }
2819
2820
  // Read the identifier.
2821
482
  PP.Lex(Tok);
2822
482
  if (Tok.isNot(tok::identifier)) {
2823
0
    PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2824
0
    return;
2825
0
  }
2826
2827
  // Verify that this is one of the float control options.
2828
482
  IdentifierInfo *II = Tok.getIdentifierInfo();
2829
482
  PragmaFloatControlKind Kind =
2830
482
      llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
2831
482
          .Case("precise", PFC_Precise)
2832
482
          .Case("except", PFC_Except)
2833
482
          .Case("push", PFC_Push)
2834
482
          .Case("pop", PFC_Pop)
2835
482
          .Default(PFC_Unknown);
2836
482
  PP.Lex(Tok); // the identifier
2837
482
  if (Kind == PFC_Unknown) {
2838
0
    PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2839
0
    return;
2840
482
  } else if (Kind == PFC_Push || 
Kind == PFC_Pop419
) {
2841
154
    if (Tok.isNot(tok::r_paren)) {
2842
0
      PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2843
0
      return;
2844
0
    }
2845
154
    PP.Lex(Tok); // Eat the r_paren
2846
154
    Action = (Kind == PFC_Pop) ? 
Sema::PSK_Pop91
:
Sema::PSK_Push63
;
2847
328
  } else {
2848
328
    if (Tok.is(tok::r_paren))
2849
      // Selecting Precise or Except
2850
0
      PP.Lex(Tok); // the r_paren
2851
328
    else if (Tok.isNot(tok::comma)) {
2852
0
      PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2853
0
      return;
2854
328
    } else {
2855
328
      PP.Lex(Tok); // ,
2856
328
      if (!Tok.isAnyIdentifier()) {
2857
0
        PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2858
0
        return;
2859
0
      }
2860
328
      StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
2861
328
      if (PushOnOff == "on")
2862
        // Kind is set correctly
2863
181
        ;
2864
147
      else if (PushOnOff == "off") {
2865
147
        if (Kind == PFC_Precise)
2866
118
          Kind = PFC_NoPrecise;
2867
147
        if (Kind == PFC_Except)
2868
29
          Kind = PFC_NoExcept;
2869
147
      } else 
if (0
PushOnOff == "push"0
) {
2870
0
        Action = Sema::PSK_Push_Set;
2871
0
      } else {
2872
0
        PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2873
0
        return;
2874
0
      }
2875
328
      PP.Lex(Tok); // the identifier
2876
328
      if (Tok.is(tok::comma)) {
2877
12
        PP.Lex(Tok); // ,
2878
12
        if (!Tok.isAnyIdentifier()) {
2879
0
          PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2880
0
          return;
2881
0
        }
2882
12
        StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
2883
12
        if (ExpectedPush == "push") {
2884
12
          Action = Sema::PSK_Push_Set;
2885
12
        } else {
2886
0
          PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2887
0
          return;
2888
0
        }
2889
12
        PP.Lex(Tok); // the push identifier
2890
12
      }
2891
328
      if (Tok.isNot(tok::r_paren)) {
2892
1
        PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2893
1
        return;
2894
1
      }
2895
327
      PP.Lex(Tok); // the r_paren
2896
327
    }
2897
328
  }
2898
481
  SourceLocation EndLoc = Tok.getLocation();
2899
481
  if (Tok.isNot(tok::eod)) {
2900
5
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2901
5
        << "float_control";
2902
5
    return;
2903
5
  }
2904
2905
  // Note: there is no accomodation for PP callback for this pragma.
2906
2907
  // Enter the annotation.
2908
476
  auto TokenArray = std::make_unique<Token[]>(1);
2909
476
  TokenArray[0].startToken();
2910
476
  TokenArray[0].setKind(tok::annot_pragma_float_control);
2911
476
  TokenArray[0].setLocation(FloatControlLoc);
2912
476
  TokenArray[0].setAnnotationEndLoc(EndLoc);
2913
  // Create an encoding of Action and Value by shifting the Action into
2914
  // the high 16 bits then union with the Kind.
2915
476
  TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(
2916
476
      static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
2917
476
  PP.EnterTokenStream(std::move(TokenArray), 1,
2918
476
                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2919
476
}
2920
2921
/// Handle the Microsoft \#pragma detect_mismatch extension.
2922
///
2923
/// The syntax is:
2924
/// \code
2925
///   #pragma detect_mismatch("name", "value")
2926
/// \endcode
2927
/// Where 'name' and 'value' are quoted strings.  The values are embedded in
2928
/// the object file and passed along to the linker.  If the linker detects a
2929
/// mismatch in the object file's values for the given name, a LNK2038 error
2930
/// is emitted.  See MSDN for more details.
2931
void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
2932
                                               PragmaIntroducer Introducer,
2933
19
                                               Token &Tok) {
2934
19
  SourceLocation DetectMismatchLoc = Tok.getLocation();
2935
19
  PP.Lex(Tok);
2936
19
  if (Tok.isNot(tok::l_paren)) {
2937
0
    PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
2938
0
    return;
2939
0
  }
2940
2941
  // Read the name to embed, which must be a string literal.
2942
19
  std::string NameString;
2943
19
  if (!PP.LexStringLiteral(Tok, NameString,
2944
19
                           "pragma detect_mismatch",
2945
19
                           /*AllowMacroExpansion=*/true))
2946
1
    return;
2947
2948
  // Read the comma followed by a second string literal.
2949
18
  std::string ValueString;
2950
18
  if (Tok.isNot(tok::comma)) {
2951
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2952
1
    return;
2953
1
  }
2954
2955
17
  if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
2956
17
                           /*AllowMacroExpansion=*/true))
2957
1
    return;
2958
2959
16
  if (Tok.isNot(tok::r_paren)) {
2960
0
    PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2961
0
    return;
2962
0
  }
2963
16
  PP.Lex(Tok);  // Eat the r_paren.
2964
2965
16
  if (Tok.isNot(tok::eod)) {
2966
0
    PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2967
0
    return;
2968
0
  }
2969
2970
  // If the pragma is lexically sound, notify any interested PPCallbacks.
2971
16
  if (PP.getPPCallbacks())
2972
16
    PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
2973
16
                                              ValueString);
2974
2975
16
  Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
2976
16
}
2977
2978
/// Handle the microsoft \#pragma comment extension.
2979
///
2980
/// The syntax is:
2981
/// \code
2982
///   #pragma comment(linker, "foo")
2983
/// \endcode
2984
/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
2985
/// "foo" is a string, which is fully macro expanded, and permits string
2986
/// concatenation, embedded escape characters etc.  See MSDN for more details.
2987
void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
2988
                                        PragmaIntroducer Introducer,
2989
120
                                        Token &Tok) {
2990
120
  SourceLocation CommentLoc = Tok.getLocation();
2991
120
  PP.Lex(Tok);
2992
120
  if (Tok.isNot(tok::l_paren)) {
2993
0
    PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2994
0
    return;
2995
0
  }
2996
2997
  // Read the identifier.
2998
120
  PP.Lex(Tok);
2999
120
  if (Tok.isNot(tok::identifier)) {
3000
0
    PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
3001
0
    return;
3002
0
  }
3003
3004
  // Verify that this is one of the 5 explicitly listed options.
3005
120
  IdentifierInfo *II = Tok.getIdentifierInfo();
3006
120
  PragmaMSCommentKind Kind =
3007
120
    llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
3008
120
    .Case("linker",   PCK_Linker)
3009
120
    .Case("lib",      PCK_Lib)
3010
120
    .Case("compiler", PCK_Compiler)
3011
120
    .Case("exestr",   PCK_ExeStr)
3012
120
    .Case("user",     PCK_User)
3013
120
    .Default(PCK_Unknown);
3014
120
  if (Kind == PCK_Unknown) {
3015
7
    PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
3016
7
    return;
3017
7
  }
3018
3019
113
  if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && 
Kind != PCK_Lib73
) {
3020
44
    PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
3021
44
        << II->getName();
3022
44
    return;
3023
44
  }
3024
3025
  // Read the optional string if present.
3026
69
  PP.Lex(Tok);
3027
69
  std::string ArgumentString;
3028
69
  if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
3029
64
                                                 "pragma comment",
3030
64
                                                 /*AllowMacroExpansion=*/true))
3031
1
    return;
3032
3033
  // FIXME: warn that 'exestr' is deprecated.
3034
  // FIXME: If the kind is "compiler" warn if the string is present (it is
3035
  // ignored).
3036
  // The MSDN docs say that "lib" and "linker" require a string and have a short
3037
  // list of linker options they support, but in practice MSVC doesn't
3038
  // issue a diagnostic.  Therefore neither does clang.
3039
3040
68
  if (Tok.isNot(tok::r_paren)) {
3041
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
3042
1
    return;
3043
1
  }
3044
67
  PP.Lex(Tok);  // eat the r_paren.
3045
3046
67
  if (Tok.isNot(tok::eod)) {
3047
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
3048
1
    return;
3049
1
  }
3050
3051
  // If the pragma is lexically sound, notify any interested PPCallbacks.
3052
66
  if (PP.getPPCallbacks())
3053
66
    PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
3054
3055
66
  Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
3056
66
}
3057
3058
// #pragma clang optimize off
3059
// #pragma clang optimize on
3060
void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
3061
                                         PragmaIntroducer Introducer,
3062
33
                                         Token &FirstToken) {
3063
33
  Token Tok;
3064
33
  PP.Lex(Tok);
3065
33
  if (Tok.is(tok::eod)) {
3066
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3067
1
        << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
3068
1
    return;
3069
1
  }
3070
32
  if (Tok.isNot(tok::identifier)) {
3071
0
    PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
3072
0
      << PP.getSpelling(Tok);
3073
0
    return;
3074
0
  }
3075
32
  const IdentifierInfo *II = Tok.getIdentifierInfo();
3076
  // The only accepted values are 'on' or 'off'.
3077
32
  bool IsOn = false;
3078
32
  if (II->isStr("on")) {
3079
15
    IsOn = true;
3080
17
  } else if (!II->isStr("off")) {
3081
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
3082
1
      << PP.getSpelling(Tok);
3083
1
    return;
3084
1
  }
3085
31
  PP.Lex(Tok);
3086
3087
31
  if (Tok.isNot(tok::eod)) {
3088
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
3089
1
      << PP.getSpelling(Tok);
3090
1
    return;
3091
1
  }
3092
3093
30
  Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
3094
30
}
3095
3096
namespace {
3097
/// Used as the annotation value for tok::annot_pragma_fp.
3098
struct TokFPAnnotValue {
3099
  enum FlagKinds { Contract, Reassociate, Exceptions, EvalMethod };
3100
  enum FlagValues { On, Off, Fast };
3101
3102
  llvm::Optional<LangOptions::FPModeKind> ContractValue;
3103
  llvm::Optional<LangOptions::FPModeKind> ReassociateValue;
3104
  llvm::Optional<LangOptions::FPExceptionModeKind> ExceptionsValue;
3105
  llvm::Optional<LangOptions::FPEvalMethodKind> EvalMethodValue;
3106
};
3107
} // end anonymous namespace
3108
3109
void PragmaFPHandler::HandlePragma(Preprocessor &PP,
3110
184
                                   PragmaIntroducer Introducer, Token &Tok) {
3111
  // fp
3112
184
  Token PragmaName = Tok;
3113
184
  SmallVector<Token, 1> TokenList;
3114
3115
184
  PP.Lex(Tok);
3116
184
  if (Tok.isNot(tok::identifier)) {
3117
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
3118
1
        << /*MissingOption=*/true << "";
3119
1
    return;
3120
1
  }
3121
3122
183
  auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue;
3123
363
  while (Tok.is(tok::identifier)) {
3124
190
    IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3125
3126
190
    auto FlagKind =
3127
190
        llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
3128
190
            OptionInfo->getName())
3129
190
            .Case("contract", TokFPAnnotValue::Contract)
3130
190
            .Case("reassociate", TokFPAnnotValue::Reassociate)
3131
190
            .Case("exceptions", TokFPAnnotValue::Exceptions)
3132
190
            .Case("eval_method", TokFPAnnotValue::EvalMethod)
3133
190
            .Default(None);
3134
190
    if (!FlagKind) {
3135
1
      PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
3136
1
          << /*MissingOption=*/false << OptionInfo;
3137
1
      return;
3138
1
    }
3139
189
    PP.Lex(Tok);
3140
3141
    // Read '('
3142
189
    if (Tok.isNot(tok::l_paren)) {
3143
1
      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3144
1
      return;
3145
1
    }
3146
188
    PP.Lex(Tok);
3147
188
    bool isEvalMethodDouble =
3148
188
        Tok.is(tok::kw_double) && 
FlagKind == TokFPAnnotValue::EvalMethod41
;
3149
3150
    // Don't diagnose if we have an eval_metod pragma with "double" kind.
3151
188
    if (Tok.isNot(tok::identifier) && 
!isEvalMethodDouble42
) {
3152
1
      PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3153
1
          << PP.getSpelling(Tok) << OptionInfo->getName()
3154
1
          << static_cast<int>(*FlagKind);
3155
1
      return;
3156
1
    }
3157
187
    const IdentifierInfo *II = Tok.getIdentifierInfo();
3158
3159
187
    if (FlagKind == TokFPAnnotValue::Contract) {
3160
24
      AnnotValue->ContractValue =
3161
24
          llvm::StringSwitch<llvm::Optional<LangOptions::FPModeKind>>(
3162
24
              II->getName())
3163
24
              .Case("on", LangOptions::FPModeKind::FPM_On)
3164
24
              .Case("off", LangOptions::FPModeKind::FPM_Off)
3165
24
              .Case("fast", LangOptions::FPModeKind::FPM_Fast)
3166
24
              .Default(llvm::None);
3167
24
      if (!AnnotValue->ContractValue) {
3168
1
        PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3169
1
            << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3170
1
        return;
3171
1
      }
3172
163
    } else if (FlagKind == TokFPAnnotValue::Reassociate) {
3173
42
      AnnotValue->ReassociateValue =
3174
42
          llvm::StringSwitch<llvm::Optional<LangOptions::FPModeKind>>(
3175
42
              II->getName())
3176
42
              .Case("on", LangOptions::FPModeKind::FPM_On)
3177
42
              .Case("off", LangOptions::FPModeKind::FPM_Off)
3178
42
              .Default(llvm::None);
3179
42
      if (!AnnotValue->ReassociateValue) {
3180
1
        PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3181
1
            << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3182
1
        return;
3183
1
      }
3184
121
    } else if (FlagKind == TokFPAnnotValue::Exceptions) {
3185
17
      AnnotValue->ExceptionsValue =
3186
17
          llvm::StringSwitch<llvm::Optional<LangOptions::FPExceptionModeKind>>(
3187
17
              II->getName())
3188
17
              .Case("ignore", LangOptions::FPE_Ignore)
3189
17
              .Case("maytrap", LangOptions::FPE_MayTrap)
3190
17
              .Case("strict", LangOptions::FPE_Strict)
3191
17
              .Default(llvm::None);
3192
17
      if (!AnnotValue->ExceptionsValue) {
3193
1
        PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3194
1
            << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3195
1
        return;
3196
1
      }
3197
104
    } else if (FlagKind == TokFPAnnotValue::EvalMethod) {
3198
104
      AnnotValue->EvalMethodValue =
3199
104
          llvm::StringSwitch<llvm::Optional<LangOptions::FPEvalMethodKind>>(
3200
104
              II->getName())
3201
104
              .Case("source", LangOptions::FPEvalMethodKind::FEM_Source)
3202
104
              .Case("double", LangOptions::FPEvalMethodKind::FEM_Double)
3203
104
              .Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended)
3204
104
              .Default(llvm::None);
3205
104
      if (!AnnotValue->EvalMethodValue) {
3206
3
        PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3207
3
            << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3208
3
        return;
3209
3
      }
3210
104
    }
3211
181
    PP.Lex(Tok);
3212
3213
    // Read ')'
3214
181
    if (Tok.isNot(tok::r_paren)) {
3215
1
      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3216
1
      return;
3217
1
    }
3218
180
    PP.Lex(Tok);
3219
180
  }
3220
3221
173
  if (Tok.isNot(tok::eod)) {
3222
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3223
1
        << "clang fp";
3224
1
    return;
3225
1
  }
3226
3227
172
  Token FPTok;
3228
172
  FPTok.startToken();
3229
172
  FPTok.setKind(tok::annot_pragma_fp);
3230
172
  FPTok.setLocation(PragmaName.getLocation());
3231
172
  FPTok.setAnnotationEndLoc(PragmaName.getLocation());
3232
172
  FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
3233
172
  TokenList.push_back(FPTok);
3234
3235
172
  auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3236
172
  std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3237
3238
172
  PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3239
172
                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3240
172
}
3241
3242
void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,
3243
                                                PragmaIntroducer Introducer,
3244
81
                                                Token &Tok) {
3245
81
  Token PragmaName = Tok;
3246
81
  SmallVector<Token, 1> TokenList;
3247
81
  if (!PP.getTargetInfo().hasStrictFP() && 
!PP.getLangOpts().ExpStrictFP3
) {
3248
3
    PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
3249
3
        << PragmaName.getIdentifierInfo()->getName();
3250
3
    return;
3251
3
  }
3252
3253
78
  PP.Lex(Tok);
3254
78
  if (Tok.isNot(tok::identifier)) {
3255
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
3256
0
        << PragmaName.getIdentifierInfo()->getName();
3257
0
    return;
3258
0
  }
3259
78
  IdentifierInfo *II = Tok.getIdentifierInfo();
3260
3261
78
  auto RM =
3262
78
      llvm::StringSwitch<llvm::RoundingMode>(II->getName())
3263
78
          .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero)
3264
78
          .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven)
3265
78
          .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive)
3266
78
          .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative)
3267
78
          .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway)
3268
78
          .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic)
3269
78
          .Default(llvm::RoundingMode::Invalid);
3270
78
  if (RM == llvm::RoundingMode::Invalid) {
3271
1
    PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode);
3272
1
    return;
3273
1
  }
3274
77
  PP.Lex(Tok);
3275
3276
77
  if (Tok.isNot(tok::eod)) {
3277
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3278
0
        << "STDC FENV_ROUND";
3279
0
    return;
3280
0
  }
3281
3282
  // Until the pragma is fully implemented, issue a warning.
3283
77
  PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);
3284
3285
77
  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
3286
77
                              1);
3287
77
  Toks[0].startToken();
3288
77
  Toks[0].setKind(tok::annot_pragma_fenv_round);
3289
77
  Toks[0].setLocation(Tok.getLocation());
3290
77
  Toks[0].setAnnotationEndLoc(Tok.getLocation());
3291
77
  Toks[0].setAnnotationValue(
3292
77
      reinterpret_cast<void *>(static_cast<uintptr_t>(RM)));
3293
77
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
3294
77
                      /*IsReinject=*/false);
3295
77
}
3296
3297
169
void Parser::HandlePragmaFP() {
3298
169
  assert(Tok.is(tok::annot_pragma_fp));
3299
0
  auto *AnnotValue =
3300
169
      reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
3301
3302
169
  if (AnnotValue->ReassociateValue)
3303
39
    Actions.ActOnPragmaFPReassociate(Tok.getLocation(),
3304
39
                                     *AnnotValue->ReassociateValue ==
3305
39
                                         LangOptions::FPModeKind::FPM_On);
3306
169
  if (AnnotValue->ContractValue)
3307
18
    Actions.ActOnPragmaFPContract(Tok.getLocation(),
3308
18
                                  *AnnotValue->ContractValue);
3309
169
  if (AnnotValue->ExceptionsValue)
3310
16
    Actions.ActOnPragmaFPExceptions(Tok.getLocation(),
3311
16
                                    *AnnotValue->ExceptionsValue);
3312
169
  if (AnnotValue->EvalMethodValue)
3313
101
    Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(),
3314
101
                                    *AnnotValue->EvalMethodValue);
3315
169
  ConsumeAnnotationToken();
3316
169
}
3317
3318
/// Parses loop or unroll pragma hint value and fills in Info.
3319
static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
3320
                               Token Option, bool ValueInParens,
3321
390
                               PragmaLoopHintInfo &Info) {
3322
390
  SmallVector<Token, 1> ValueList;
3323
390
  int OpenParens = ValueInParens ? 
1367
:
023
;
3324
  // Read constant expression.
3325
871
  while (Tok.isNot(tok::eod)) {
3326
831
    if (Tok.is(tok::l_paren))
3327
8
      OpenParens++;
3328
823
    else if (Tok.is(tok::r_paren)) {
3329
357
      OpenParens--;
3330
357
      if (OpenParens == 0 && 
ValueInParens350
)
3331
350
        break;
3332
357
    }
3333
3334
481
    ValueList.push_back(Tok);
3335
481
    PP.Lex(Tok);
3336
481
  }
3337
3338
390
  if (ValueInParens) {
3339
    // Read ')'
3340
367
    if (Tok.isNot(tok::r_paren)) {
3341
17
      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3342
17
      return true;
3343
17
    }
3344
350
    PP.Lex(Tok);
3345
350
  }
3346
3347
373
  Token EOFTok;
3348
373
  EOFTok.startToken();
3349
373
  EOFTok.setKind(tok::eof);
3350
373
  EOFTok.setLocation(Tok.getLocation());
3351
373
  ValueList.push_back(EOFTok); // Terminates expression for parsing.
3352
3353
373
  markAsReinjectedForRelexing(ValueList);
3354
373
  Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
3355
3356
373
  Info.PragmaName = PragmaName;
3357
373
  Info.Option = Option;
3358
373
  return false;
3359
390
}
3360
3361
/// Handle the \#pragma clang loop directive.
3362
///  #pragma clang 'loop' loop-hints
3363
///
3364
///  loop-hints:
3365
///    loop-hint loop-hints[opt]
3366
///
3367
///  loop-hint:
3368
///    'vectorize' '(' loop-hint-keyword ')'
3369
///    'interleave' '(' loop-hint-keyword ')'
3370
///    'unroll' '(' unroll-hint-keyword ')'
3371
///    'vectorize_predicate' '(' loop-hint-keyword ')'
3372
///    'vectorize_width' '(' loop-hint-value ')'
3373
///    'interleave_count' '(' loop-hint-value ')'
3374
///    'unroll_count' '(' loop-hint-value ')'
3375
///    'pipeline' '(' disable ')'
3376
///    'pipeline_initiation_interval' '(' loop-hint-value ')'
3377
///
3378
///  loop-hint-keyword:
3379
///    'enable'
3380
///    'disable'
3381
///    'assume_safety'
3382
///
3383
///  unroll-hint-keyword:
3384
///    'enable'
3385
///    'disable'
3386
///    'full'
3387
///
3388
///  loop-hint-value:
3389
///    constant-expression
3390
///
3391
/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
3392
/// try vectorizing the instructions of the loop it precedes. Specifying
3393
/// interleave(enable) or interleave_count(_value_) instructs llvm to try
3394
/// interleaving multiple iterations of the loop it precedes. The width of the
3395
/// vector instructions is specified by vectorize_width() and the number of
3396
/// interleaved loop iterations is specified by interleave_count(). Specifying a
3397
/// value of 1 effectively disables vectorization/interleaving, even if it is
3398
/// possible and profitable, and 0 is invalid. The loop vectorizer currently
3399
/// only works on inner loops.
3400
///
3401
/// The unroll and unroll_count directives control the concatenation
3402
/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
3403
/// completely if the trip count is known at compile time and unroll partially
3404
/// if the trip count is not known.  Specifying unroll(full) is similar to
3405
/// unroll(enable) but will unroll the loop only if the trip count is known at
3406
/// compile time.  Specifying unroll(disable) disables unrolling for the
3407
/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
3408
/// loop the number of times indicated by the value.
3409
void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
3410
                                         PragmaIntroducer Introducer,
3411
274
                                         Token &Tok) {
3412
  // Incoming token is "loop" from "#pragma clang loop".
3413
274
  Token PragmaName = Tok;
3414
274
  SmallVector<Token, 1> TokenList;
3415
3416
  // Lex the optimization option and verify it is an identifier.
3417
274
  PP.Lex(Tok);
3418
274
  if (Tok.isNot(tok::identifier)) {
3419
1
    PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3420
1
        << /*MissingOption=*/true << "";
3421
1
    return;
3422
1
  }
3423
3424
589
  
while (273
Tok.is(tok::identifier)) {
3425
341
    Token Option = Tok;
3426
341
    IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3427
3428
341
    bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
3429
341
                           .Case("vectorize", true)
3430
341
                           .Case("interleave", true)
3431
341
                           .Case("unroll", true)
3432
341
                           .Case("distribute", true)
3433
341
                           .Case("vectorize_predicate", true)
3434
341
                           .Case("vectorize_width", true)
3435
341
                           .Case("interleave_count", true)
3436
341
                           .Case("unroll_count", true)
3437
341
                           .Case("pipeline", true)
3438
341
                           .Case("pipeline_initiation_interval", true)
3439
341
                           .Default(false);
3440
341
    if (!OptionValid) {
3441
4
      PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3442
4
          << /*MissingOption=*/false << OptionInfo;
3443
4
      return;
3444
4
    }
3445
337
    PP.Lex(Tok);
3446
3447
    // Read '('
3448
337
    if (Tok.isNot(tok::l_paren)) {
3449
7
      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3450
7
      return;
3451
7
    }
3452
330
    PP.Lex(Tok);
3453
3454
330
    auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3455
330
    if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
3456
330
                           *Info))
3457
14
      return;
3458
3459
    // Generate the loop hint token.
3460
316
    Token LoopHintTok;
3461
316
    LoopHintTok.startToken();
3462
316
    LoopHintTok.setKind(tok::annot_pragma_loop_hint);
3463
316
    LoopHintTok.setLocation(Introducer.Loc);
3464
316
    LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
3465
316
    LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
3466
316
    TokenList.push_back(LoopHintTok);
3467
316
  }
3468
3469
248
  if (Tok.isNot(tok::eod)) {
3470
4
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3471
4
        << "clang loop";
3472
4
    return;
3473
4
  }
3474
3475
244
  auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3476
244
  std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3477
3478
244
  PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3479
244
                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3480
244
}
3481
3482
/// Handle the loop unroll optimization pragmas.
3483
///  #pragma unroll
3484
///  #pragma unroll unroll-hint-value
3485
///  #pragma unroll '(' unroll-hint-value ')'
3486
///  #pragma nounroll
3487
///  #pragma unroll_and_jam
3488
///  #pragma unroll_and_jam unroll-hint-value
3489
///  #pragma unroll_and_jam '(' unroll-hint-value ')'
3490
///  #pragma nounroll_and_jam
3491
///
3492
///  unroll-hint-value:
3493
///    constant-expression
3494
///
3495
/// Loop unrolling hints can be specified with '#pragma unroll' or
3496
/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
3497
/// contained in parentheses. With no argument the directive instructs llvm to
3498
/// try to unroll the loop completely. A positive integer argument can be
3499
/// specified to indicate the number of times the loop should be unrolled.  To
3500
/// maximize compatibility with other compilers the unroll count argument can be
3501
/// specified with or without parentheses.  Specifying, '#pragma nounroll'
3502
/// disables unrolling of the loop.
3503
void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
3504
                                           PragmaIntroducer Introducer,
3505
100
                                           Token &Tok) {
3506
  // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
3507
  // "#pragma nounroll".
3508
100
  Token PragmaName = Tok;
3509
100
  PP.Lex(Tok);
3510
100
  auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3511
100
  if (Tok.is(tok::eod)) {
3512
    // nounroll or unroll pragma without an argument.
3513
38
    Info->PragmaName = PragmaName;
3514
38
    Info->Option.startToken();
3515
62
  } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
3516
62
             
PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam"61
) {
3517
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3518
2
        << PragmaName.getIdentifierInfo()->getName();
3519
2
    return;
3520
60
  } else {
3521
    // Unroll pragma with an argument: "#pragma unroll N" or
3522
    // "#pragma unroll(N)".
3523
    // Read '(' if it exists.
3524
60
    bool ValueInParens = Tok.is(tok::l_paren);
3525
60
    if (ValueInParens)
3526
37
      PP.Lex(Tok);
3527
3528
60
    Token Option;
3529
60
    Option.startToken();
3530
60
    if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
3531
3
      return;
3532
3533
    // In CUDA, the argument to '#pragma unroll' should not be contained in
3534
    // parentheses.
3535
57
    if (PP.getLangOpts().CUDA && 
ValueInParens2
)
3536
2
      PP.Diag(Info->Toks[0].getLocation(),
3537
2
              diag::warn_pragma_unroll_cuda_value_in_parens);
3538
3539
57
    if (Tok.isNot(tok::eod)) {
3540
0
      PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3541
0
          << "unroll";
3542
0
      return;
3543
0
    }
3544
57
  }
3545
3546
  // Generate the hint token.
3547
95
  auto TokenArray = std::make_unique<Token[]>(1);
3548
95
  TokenArray[0].startToken();
3549
95
  TokenArray[0].setKind(tok::annot_pragma_loop_hint);
3550
95
  TokenArray[0].setLocation(Introducer.Loc);
3551
95
  TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
3552
95
  TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3553
95
  PP.EnterTokenStream(std::move(TokenArray), 1,
3554
95
                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3555
95
}
3556
3557
/// Handle the Microsoft \#pragma intrinsic extension.
3558
///
3559
/// The syntax is:
3560
/// \code
3561
///  #pragma intrinsic(memset)
3562
///  #pragma intrinsic(strlen, memcpy)
3563
/// \endcode
3564
///
3565
/// Pragma intrisic tells the compiler to use a builtin version of the
3566
/// function. Clang does it anyway, so the pragma doesn't really do anything.
3567
/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3568
/// isn't an intrinsic in clang and suggest to include intrin.h.
3569
void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
3570
                                            PragmaIntroducer Introducer,
3571
19
                                            Token &Tok) {
3572
19
  PP.Lex(Tok);
3573
3574
19
  if (Tok.isNot(tok::l_paren)) {
3575
0
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
3576
0
        << "intrinsic";
3577
0
    return;
3578
0
  }
3579
19
  PP.Lex(Tok);
3580
3581
19
  bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3582
3583
21
  while (Tok.is(tok::identifier)) {
3584
18
    IdentifierInfo *II = Tok.getIdentifierInfo();
3585
18
    if (!II->getBuiltinID())
3586
8
      PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3587
8
          << II << SuggestIntrinH;
3588
3589
18
    PP.Lex(Tok);
3590
18
    if (Tok.isNot(tok::comma))
3591
16
      break;
3592
2
    PP.Lex(Tok);
3593
2
  }
3594
3595
19
  if (Tok.isNot(tok::r_paren)) {
3596
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
3597
2
        << "intrinsic";
3598
2
    return;
3599
2
  }
3600
17
  PP.Lex(Tok);
3601
3602
17
  if (Tok.isNot(tok::eod))
3603
1
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3604
1
        << "intrinsic";
3605
17
}
3606
3607
bool Parser::HandlePragmaMSFunction(StringRef PragmaName,
3608
15
                                    SourceLocation PragmaLocation) {
3609
15
  Token FirstTok = Tok;
3610
3611
15
  if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3612
15
                       PragmaName))
3613
0
    return false;
3614
3615
15
  bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3616
3617
15
  llvm::SmallVector<StringRef> NoBuiltins;
3618
18
  while (Tok.is(tok::identifier)) {
3619
15
    IdentifierInfo *II = Tok.getIdentifierInfo();
3620
15
    if (!II->getBuiltinID())
3621
4
      PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3622
4
          << II << SuggestIntrinH;
3623
11
    else
3624
11
      NoBuiltins.emplace_back(II->getName());
3625
3626
15
    PP.Lex(Tok);
3627
15
    if (Tok.isNot(tok::comma))
3628
12
      break;
3629
3
    PP.Lex(Tok); // ,
3630
3
  }
3631
3632
15
  if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3633
15
                       PragmaName) ||
3634
15
      ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3635
13
                       PragmaName))
3636
3
    return false;
3637
3638
12
  Actions.ActOnPragmaMSFunction(FirstTok.getLocation(), NoBuiltins);
3639
12
  return true;
3640
15
}
3641
3642
// #pragma optimize("gsty", on|off)
3643
bool Parser::HandlePragmaMSOptimize(StringRef PragmaName,
3644
12
                                    SourceLocation PragmaLocation) {
3645
12
  Token FirstTok = Tok;
3646
12
  if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3647
12
                       PragmaName))
3648
1
    return false;
3649
3650
11
  if (Tok.isNot(tok::string_literal)) {
3651
2
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_string) << PragmaName;
3652
2
    return false;
3653
2
  }
3654
9
  ExprResult StringResult = ParseStringLiteralExpression();
3655
9
  if (StringResult.isInvalid())
3656
0
    return false; // Already diagnosed.
3657
9
  StringLiteral *OptimizationList = cast<StringLiteral>(StringResult.get());
3658
9
  if (OptimizationList->getCharByteWidth() != 1) {
3659
0
    PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
3660
0
        << PragmaName;
3661
0
    return false;
3662
0
  }
3663
3664
9
  if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
3665
9
                       PragmaName))
3666
1
    return false;
3667
3668
8
  if (Tok.is(tok::eof) || 
Tok.is(tok::r_paren)7
) {
3669
1
    PP.Diag(PragmaLocation, diag::warn_pragma_missing_argument)
3670
1
        << PragmaName << /*Expected=*/true << "'on' or 'off'";
3671
1
    return false;
3672
1
  }
3673
7
  IdentifierInfo *II = Tok.getIdentifierInfo();
3674
7
  if (!II || (!II->isStr("on") && 
!II->isStr("off")2
)) {
3675
1
    PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
3676
1
        << PP.getSpelling(Tok) << PragmaName << /*Expected=*/true
3677
1
        << "'on' or 'off'";
3678
1
    return false;
3679
1
  }
3680
6
  bool IsOn = II->isStr("on");
3681
6
  PP.Lex(Tok);
3682
3683
6
  if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3684
6
                       PragmaName))
3685
0
    return false;
3686
3687
  // TODO: Add support for "sgty"
3688
6
  if (!OptimizationList->getString().empty()) {
3689
1
    PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
3690
1
        << OptimizationList->getString() << PragmaName << /*Expected=*/true
3691
1
        << "\"\"";
3692
1
    return false;
3693
1
  }
3694
3695
5
  if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3696
5
                       PragmaName))
3697
1
    return false;
3698
3699
4
  Actions.ActOnPragmaMSOptimize(FirstTok.getLocation(), IsOn);
3700
4
  return true;
3701
5
}
3702
3703
void PragmaForceCUDAHostDeviceHandler::HandlePragma(
3704
14
    Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
3705
14
  Token FirstTok = Tok;
3706
3707
14
  PP.Lex(Tok);
3708
14
  IdentifierInfo *Info = Tok.getIdentifierInfo();
3709
14
  if (!Info || 
(13
!Info->isStr("begin")13
&&
!Info->isStr("end")6
)) {
3710
2
    PP.Diag(FirstTok.getLocation(),
3711
2
            diag::warn_pragma_force_cuda_host_device_bad_arg);
3712
2
    return;
3713
2
  }
3714
3715
12
  if (Info->isStr("begin"))
3716
7
    Actions.PushForceCUDAHostDevice();
3717
5
  else if (!Actions.PopForceCUDAHostDevice())
3718
0
    PP.Diag(FirstTok.getLocation(),
3719
0
            diag::err_pragma_cannot_end_force_cuda_host_device);
3720
3721
12
  PP.Lex(Tok);
3722
12
  if (!Tok.is(tok::eod))
3723
1
    PP.Diag(FirstTok.getLocation(),
3724
1
            diag::warn_pragma_force_cuda_host_device_bad_arg);
3725
12
}
3726
3727
/// Handle the #pragma clang attribute directive.
3728
///
3729
/// The syntax is:
3730
/// \code
3731
///  #pragma clang attribute push (attribute, subject-set)
3732
///  #pragma clang attribute push
3733
///  #pragma clang attribute (attribute, subject-set)
3734
///  #pragma clang attribute pop
3735
/// \endcode
3736
///
3737
/// There are also 'namespace' variants of push and pop directives. The bare
3738
/// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
3739
/// namespace, since it always applies attributes to the most recently pushed
3740
/// group, regardless of namespace.
3741
/// \code
3742
///  #pragma clang attribute namespace.push (attribute, subject-set)
3743
///  #pragma clang attribute namespace.push
3744
///  #pragma clang attribute namespace.pop
3745
/// \endcode
3746
///
3747
/// The subject-set clause defines the set of declarations which receive the
3748
/// attribute. Its exact syntax is described in the LanguageExtensions document
3749
/// in Clang's documentation.
3750
///
3751
/// This directive instructs the compiler to begin/finish applying the specified
3752
/// attribute to the set of attribute-specific declarations in the active range
3753
/// of the pragma.
3754
void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
3755
                                          PragmaIntroducer Introducer,
3756
3.14k
                                          Token &FirstToken) {
3757
3.14k
  Token Tok;
3758
3.14k
  PP.Lex(Tok);
3759
3.14k
  auto *Info = new (PP.getPreprocessorAllocator())
3760
3.14k
      PragmaAttributeInfo(AttributesForPragmaAttribute);
3761
3762
  // Parse the optional namespace followed by a period.
3763
3.14k
  if (Tok.is(tok::identifier)) {
3764
2.25k
    IdentifierInfo *II = Tok.getIdentifierInfo();
3765
2.25k
    if (!II->isStr("push") && 
!II->isStr("pop")1.07k
) {
3766
16
      Info->Namespace = II;
3767
16
      PP.Lex(Tok);
3768
3769
16
      if (!Tok.is(tok::period)) {
3770
2
        PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
3771
2
            << II;
3772
2
        return;
3773
2
      }
3774
14
      PP.Lex(Tok);
3775
14
    }
3776
2.25k
  }
3777
3778
3.14k
  if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
3779
2
    PP.Diag(Tok.getLocation(),
3780
2
            diag::err_pragma_attribute_expected_push_pop_paren);
3781
2
    return;
3782
2
  }
3783
3784
  // Determine what action this pragma clang attribute represents.
3785
3.14k
  if (Tok.is(tok::l_paren)) {
3786
892
    if (Info->Namespace) {
3787
1
      PP.Diag(Tok.getLocation(),
3788
1
              diag::err_pragma_attribute_namespace_on_attribute);
3789
1
      PP.Diag(Tok.getLocation(),
3790
1
              diag::note_pragma_attribute_namespace_on_attribute);
3791
1
      return;
3792
1
    }
3793
891
    Info->Action = PragmaAttributeInfo::Attribute;
3794
2.24k
  } else {
3795
2.24k
    const IdentifierInfo *II = Tok.getIdentifierInfo();
3796
2.24k
    if (II->isStr("push"))
3797
1.18k
      Info->Action = PragmaAttributeInfo::Push;
3798
1.06k
    else if (II->isStr("pop"))
3799
1.06k
      Info->Action = PragmaAttributeInfo::Pop;
3800
0
    else {
3801
0
      PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
3802
0
          << PP.getSpelling(Tok);
3803
0
      return;
3804
0
    }
3805
3806
2.24k
    PP.Lex(Tok);
3807
2.24k
  }
3808
3809
  // Parse the actual attribute.
3810
3.14k
  if ((Info->Action == PragmaAttributeInfo::Push && 
Tok.isNot(tok::eod)1.18k
) ||
3811
3.14k
      
Info->Action == PragmaAttributeInfo::Attribute2.84k
) {
3812
1.18k
    if (Tok.isNot(tok::l_paren)) {
3813
0
      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3814
0
      return;
3815
0
    }
3816
1.18k
    PP.Lex(Tok);
3817
3818
    // Lex the attribute tokens.
3819
1.18k
    SmallVector<Token, 16> AttributeTokens;
3820
1.18k
    int OpenParens = 1;
3821
41.5k
    while (Tok.isNot(tok::eod)) {
3822
41.5k
      if (Tok.is(tok::l_paren))
3823
4.60k
        OpenParens++;
3824
36.9k
      else if (Tok.is(tok::r_paren)) {
3825
5.77k
        OpenParens--;
3826
5.77k
        if (OpenParens == 0)
3827
1.17k
          break;
3828
5.77k
      }
3829
3830
40.3k
      AttributeTokens.push_back(Tok);
3831
40.3k
      PP.Lex(Tok);
3832
40.3k
    }
3833
3834
1.18k
    if (AttributeTokens.empty()) {
3835
2
      PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
3836
2
      return;
3837
2
    }
3838
1.18k
    if (Tok.isNot(tok::r_paren)) {
3839
10
      PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3840
10
      return;
3841
10
    }
3842
1.17k
    SourceLocation EndLoc = Tok.getLocation();
3843
1.17k
    PP.Lex(Tok);
3844
3845
    // Terminate the attribute for parsing.
3846
1.17k
    Token EOFTok;
3847
1.17k
    EOFTok.startToken();
3848
1.17k
    EOFTok.setKind(tok::eof);
3849
1.17k
    EOFTok.setLocation(EndLoc);
3850
1.17k
    AttributeTokens.push_back(EOFTok);
3851
3852
1.17k
    markAsReinjectedForRelexing(AttributeTokens);
3853
1.17k
    Info->Tokens =
3854
1.17k
        llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
3855
1.17k
  }
3856
3857
3.12k
  if (Tok.isNot(tok::eod))
3858
2
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3859
2
        << "clang attribute";
3860
3861
  // Generate the annotated pragma token.
3862
3.12k
  auto TokenArray = std::make_unique<Token[]>(1);
3863
3.12k
  TokenArray[0].startToken();
3864
3.12k
  TokenArray[0].setKind(tok::annot_pragma_attribute);
3865
3.12k
  TokenArray[0].setLocation(FirstToken.getLocation());
3866
3.12k
  TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
3867
3.12k
  TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3868
3.12k
  PP.EnterTokenStream(std::move(TokenArray), 1,
3869
3.12k
                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3870
3.12k
}
3871
3872
// Handle '#pragma clang max_tokens 12345'.
3873
void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
3874
                                              PragmaIntroducer Introducer,
3875
12
                                              Token &Tok) {
3876
12
  PP.Lex(Tok);
3877
12
  if (Tok.is(tok::eod)) {
3878
3
    PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3879
3
        << "clang max_tokens_here" << /*Expected=*/true << "integer";
3880
3
    return;
3881
3
  }
3882
3883
9
  SourceLocation Loc = Tok.getLocation();
3884
9
  uint64_t MaxTokens;
3885
9
  if (Tok.isNot(tok::numeric_constant) ||
3886
9
      
!PP.parseSimpleIntegerLiteral(Tok, MaxTokens)6
) {
3887
3
    PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
3888
3
        << "clang max_tokens_here";
3889
3
    return;
3890
3
  }
3891
3892
6
  if (Tok.isNot(tok::eod)) {
3893
3
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3894
3
        << "clang max_tokens_here";
3895
3
    return;
3896
3
  }
3897
3898
3
  if (PP.getTokenCount() > MaxTokens) {
3899
3
    PP.Diag(Loc, diag::warn_max_tokens)
3900
3
        << PP.getTokenCount() << (unsigned)MaxTokens;
3901
3
  }
3902
3
}
3903
3904
// Handle '#pragma clang max_tokens_total 12345'.
3905
void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
3906
                                               PragmaIntroducer Introducer,
3907
10
                                               Token &Tok) {
3908
10
  PP.Lex(Tok);
3909
10
  if (Tok.is(tok::eod)) {
3910
3
    PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3911
3
        << "clang max_tokens_total" << /*Expected=*/true << "integer";
3912
3
    return;
3913
3
  }
3914
3915
7
  SourceLocation Loc = Tok.getLocation();
3916
7
  uint64_t MaxTokens;
3917
7
  if (Tok.isNot(tok::numeric_constant) ||
3918
7
      
!PP.parseSimpleIntegerLiteral(Tok, MaxTokens)4
) {
3919
3
    PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
3920
3
        << "clang max_tokens_total";
3921
3
    return;
3922
3
  }
3923
3924
4
  if (Tok.isNot(tok::eod)) {
3925
3
    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3926
3
        << "clang max_tokens_total";
3927
3
    return;
3928
3
  }
3929
3930
1
  PP.overrideMaxTokens(MaxTokens, Loc);
3931
1
}