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