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