Coverage Report

Created: 2022-05-17 06:19

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