Coverage Report

Created: 2023-11-11 10:31

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