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 if (Tok.isAnyIdentifier()) {
1245 auto *II = Tok.getIdentifierInfo();
1246 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
1247 .Case("compiler", "\".CRT$XCC\"")
1248 .Case("lib", "\".CRT$XCL\"")
1249 .Case("user", "\".CRT$XCU\"")
1250 .Default("");
1251
1252 if (!Section.empty()) {
1253 // Pretend the user wrote the appropriate string literal here.
1254 Token Toks[1];
1255 Toks[0] =
1256 Token::create(tok::string_literal, Tok.getLocation(), Section.size());
1257 Toks[0].setLiteralData(Section.data());
1258 SegmentName =
1259 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
1260 PP.Lex(Tok);
1261 }
1262 } else if (Tok.is(tok::string_literal)) {
1264 if (StringResult.isInvalid())
1265 return false;
1266 SegmentName = cast<StringLiteral>(StringResult.get());
1267 if (SegmentName->getCharByteWidth() != 1) {
1268 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1269 << PragmaName;
1270 return false;
1271 }
1272 // FIXME: Add support for the '[, func-name]' part of the pragma.
1273 }
1274
1275 if (!SegmentName) {
1276 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
1277 return false;
1278 }
1279
1280 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1281 PragmaName) ||
1282 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1283 PragmaName))
1284 return false;
1285
1286 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
1287 return true;
1288}
1289
1290bool Parser::HandlePragmaMSStrictGuardStackCheck(
1291 StringRef PragmaName, SourceLocation PragmaLocation) {
1292 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1293 PragmaName))
1294 return false;
1295
1297 if (Tok.is(tok::identifier)) {
1298 StringRef PushPop = Tok.getIdentifierInfo()->getName();
1299 if (PushPop == "push") {
1300 PP.Lex(Tok);
1301 Action = Sema::PSK_Push;
1302 if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_punc,
1303 PragmaName))
1304 return false;
1305 } else if (PushPop == "pop") {
1306 PP.Lex(Tok);
1307 Action = Sema::PSK_Pop;
1308 }
1309 }
1310
1311 bool Value = false;
1312 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
1313 const IdentifierInfo *II = Tok.getIdentifierInfo();
1314 if (II && II->isStr("off")) {
1315 PP.Lex(Tok);
1316 Value = false;
1317 } else if (II && II->isStr("on")) {
1318 PP.Lex(Tok);
1319 Value = true;
1320 } else {
1321 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1322 << PragmaName;
1323 return false;
1324 }
1325 }
1326
1327 // Finish the pragma: ')' $
1328 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1329 PragmaName))
1330 return false;
1331
1332 if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1333 PragmaName))
1334 return false;
1335
1336 Actions.ActOnPragmaMSStrictGuardStackCheck(PragmaLocation, Action, Value);
1337 return true;
1338}
1339
1340bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,
1341 SourceLocation PragmaLocation) {
1342 Token FirstTok = Tok;
1343 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1344 PragmaName))
1345 return false;
1346
1347 StringRef Section;
1348 if (Tok.is(tok::string_literal)) {
1350 if (StringResult.isInvalid())
1351 return false; // Already diagnosed.
1352 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
1353 if (SegmentName->getCharByteWidth() != 1) {
1354 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1355 << PragmaName;
1356 return false;
1357 }
1358 Section = SegmentName->getString();
1359 } else if (Tok.is(tok::identifier)) {
1360 Section = Tok.getIdentifierInfo()->getName();
1361 PP.Lex(Tok);
1362 } else {
1363 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
1364 << PragmaName;
1365 return false;
1366 }
1367
1368 if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
1369 PragmaName))
1370 return false;
1371
1372 SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> Functions;
1373 while (true) {
1374 if (Tok.isNot(tok::identifier)) {
1375 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1376 << PragmaName;
1377 return false;
1378 }
1379
1380 IdentifierInfo *II = Tok.getIdentifierInfo();
1381 Functions.emplace_back(II, Tok.getLocation());
1382
1383 PP.Lex(Tok);
1384 if (Tok.isNot(tok::comma))
1385 break;
1386 PP.Lex(Tok);
1387 }
1388
1389 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1390 PragmaName) ||
1391 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1392 PragmaName))
1393 return false;
1394
1395 Actions.ActOnPragmaMSAllocText(FirstTok.getLocation(), Section, Functions);
1396 return true;
1397}
1398
1399void Parser::zOSHandlePragmaHelper(tok::TokenKind PragmaKind) {
1400 assert(Tok.is(PragmaKind));
1401
1402 StringRef PragmaName = "export";
1403
1404 using namespace clang::charinfo;
1405 auto *TheTokens = static_cast<std::pair<std::unique_ptr<Token[]>, size_t> *>(
1406 Tok.getAnnotationValue());
1407 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
1408 /*IsReinject=*/true);
1409 Tok.setAnnotationValue(nullptr);
1410 ConsumeAnnotationToken();
1411
1412 llvm::scope_exit OnReturn([this]() {
1413 while (Tok.isNot(tok::eof))
1414 PP.Lex(Tok);
1415 PP.Lex(Tok);
1416 });
1417
1418 do {
1419 PP.Lex(Tok);
1420 if (Tok.isNot(tok::l_paren)) {
1421 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1422 << PragmaName;
1423 return;
1424 }
1425
1426 PP.Lex(Tok);
1427 if (Tok.isNot(tok::identifier)) {
1428 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1429 << PragmaName;
1430 return;
1431 }
1432
1433 IdentifierInfo *IdentName = Tok.getIdentifierInfo();
1434 SourceLocation IdentNameLoc = Tok.getLocation();
1435 PP.Lex(Tok);
1436
1437 if (Tok.isNot(tok::r_paren)) {
1438 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1439 << PragmaName;
1440 return;
1441 }
1442
1443 PP.Lex(Tok);
1444 Actions.ActOnPragmaExport(IdentName, IdentNameLoc, getCurScope());
1445
1446 // Because export is also a C++ keyword, we also check for that.
1447 if (Tok.is(tok::identifier) || Tok.is(tok::kw_export)) {
1448 PragmaName = Tok.getIdentifierInfo()->getName();
1449 if (PragmaName != "export")
1450 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1451 << PragmaName;
1452 } else if (Tok.isNot(tok::eof)) {
1453 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1454 << PragmaName;
1455 return;
1456 }
1457 } while (Tok.isNot(tok::eof));
1458 return;
1459}
1460
1461void Parser::HandlePragmaExport() {
1462 assert(Tok.is(tok::annot_pragma_export));
1463
1464 zOSHandlePragmaHelper(tok::annot_pragma_export);
1465}
1466
1467static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
1468 StringRef Str = PragmaName.getIdentifierInfo()->getName();
1469 std::string ClangLoopStr("clang loop ");
1470 if (Str == "loop" && Option.getIdentifierInfo())
1471 ClangLoopStr += Option.getIdentifierInfo()->getName();
1472 return std::string(llvm::StringSwitch<StringRef>(Str)
1473 .Case("loop", ClangLoopStr)
1474 .Case("unroll_and_jam", Str)
1475 .Case("unroll", Str)
1476 .Default(""));
1477}
1478
1479bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
1480 assert(Tok.is(tok::annot_pragma_loop_hint));
1481 PragmaLoopHintInfo *Info =
1482 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
1483
1484 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
1485 Hint.PragmaNameLoc = new (Actions.Context)
1486 IdentifierLoc(Info->PragmaName.getLocation(), PragmaNameInfo);
1487
1488 // It is possible that the loop hint has no option identifier, such as
1489 // #pragma unroll(4).
1490 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
1491 ? Info->Option.getIdentifierInfo()
1492 : nullptr;
1493 Hint.OptionLoc = new (Actions.Context)
1494 IdentifierLoc(Info->Option.getLocation(), OptionInfo);
1495
1496 llvm::ArrayRef<Token> Toks = Info->Toks;
1497
1498 // Return a valid hint if pragma unroll or nounroll were specified
1499 // without an argument.
1500 auto IsLoopHint =
1501 llvm::StringSwitch<bool>(PragmaNameInfo->getName())
1502 .Cases({"unroll", "nounroll", "unroll_and_jam", "nounroll_and_jam"},
1503 true)
1504 .Default(false);
1505
1506 if (Toks.empty() && IsLoopHint) {
1507 ConsumeAnnotationToken();
1508 Hint.Range = Info->PragmaName.getLocation();
1509 return true;
1510 }
1511
1512 // The constant expression is always followed by an eof token, which increases
1513 // the TokSize by 1.
1514 assert(!Toks.empty() &&
1515 "PragmaLoopHintInfo::Toks must contain at least one token.");
1516
1517 // If no option is specified the argument is assumed to be a constant expr.
1518 bool OptionUnroll = false;
1519 bool OptionUnrollAndJam = false;
1520 bool OptionDistribute = false;
1521 bool OptionPipelineDisabled = false;
1522 bool OptionLICMDisabled = false;
1523 bool StateOption = false;
1524 if (OptionInfo) { // Pragma Unroll does not specify an option.
1525 OptionUnroll = OptionInfo->isStr("unroll");
1526 OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
1527 OptionDistribute = OptionInfo->isStr("distribute");
1528 OptionPipelineDisabled = OptionInfo->isStr("pipeline");
1529 OptionLICMDisabled = OptionInfo->isStr("licm");
1530 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1531 .Case("vectorize", true)
1532 .Case("interleave", true)
1533 .Case("vectorize_predicate", true)
1534 .Default(false) ||
1535 OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
1536 OptionPipelineDisabled || OptionLICMDisabled;
1537 }
1538
1539 bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
1540 !OptionDistribute && !OptionPipelineDisabled &&
1541 !OptionLICMDisabled;
1542 // Verify loop hint has an argument.
1543 if (Toks[0].is(tok::eof)) {
1544 ConsumeAnnotationToken();
1545 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
1546 << /*StateArgument=*/StateOption
1547 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1548 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1549 return false;
1550 }
1551
1552 // Validate the argument.
1553 if (StateOption) {
1554 ConsumeAnnotationToken();
1555 SourceLocation StateLoc = Toks[0].getLocation();
1556 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1557
1558 bool Valid =
1559 StateInfo &&
1560 llvm::StringSwitch<bool>(StateInfo->getName())
1561 .Case("disable", true)
1562 .Case("enable", !OptionPipelineDisabled && !OptionLICMDisabled)
1563 .Case("full", OptionUnroll || OptionUnrollAndJam)
1564 .Case("assume_safety", AssumeSafetyArg)
1565 .Default(false);
1566 if (!Valid) {
1567 if (OptionPipelineDisabled || OptionLICMDisabled) {
1568 Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
1569 } else {
1570 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
1571 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1572 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1573 }
1574 return false;
1575 }
1576 if (Toks.size() > 2)
1577 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1578 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1579 Hint.StateLoc = new (Actions.Context) IdentifierLoc(StateLoc, StateInfo);
1580 } else if (OptionInfo && OptionInfo->getName() == "vectorize_width") {
1581 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1582 /*IsReinject=*/false);
1583 ConsumeAnnotationToken();
1584
1585 SourceLocation StateLoc = Toks[0].getLocation();
1586 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1587 StringRef IsScalableStr = StateInfo ? StateInfo->getName() : "";
1588
1589 // Look for vectorize_width(fixed|scalable)
1590 if (IsScalableStr == "scalable" || IsScalableStr == "fixed") {
1591 PP.Lex(Tok); // Identifier
1592
1593 if (Toks.size() > 2) {
1594 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1595 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1596 while (Tok.isNot(tok::eof))
1598 }
1599
1600 Hint.StateLoc = new (Actions.Context) IdentifierLoc(StateLoc, StateInfo);
1601
1602 ConsumeToken(); // Consume the constant expression eof terminator.
1603 } else {
1604 // Enter constant expression including eof terminator into token stream.
1606
1607 if (R.isInvalid() && !Tok.is(tok::comma))
1608 Diag(Toks[0].getLocation(),
1609 diag::note_pragma_loop_invalid_vectorize_option);
1610
1611 bool Arg2Error = false;
1612 if (Tok.is(tok::comma)) {
1613 PP.Lex(Tok); // ,
1614
1615 StateInfo = Tok.getIdentifierInfo();
1616 IsScalableStr = StateInfo ? StateInfo->getName() : "";
1617
1618 if (IsScalableStr != "scalable" && IsScalableStr != "fixed") {
1619 Diag(Tok.getLocation(),
1620 diag::err_pragma_loop_invalid_vectorize_option);
1621 Arg2Error = true;
1622 } else
1623 Hint.StateLoc =
1624 new (Actions.Context) IdentifierLoc(StateLoc, StateInfo);
1625
1626 PP.Lex(Tok); // Identifier
1627 }
1628
1629 // Tokens following an error in an ill-formed constant expression will
1630 // remain in the token stream and must be removed.
1631 if (Tok.isNot(tok::eof)) {
1632 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1633 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1634 while (Tok.isNot(tok::eof))
1636 }
1637
1638 ConsumeToken(); // Consume the constant expression eof terminator.
1639
1640 if (Arg2Error || R.isInvalid() ||
1641 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation(),
1642 /*AllowZero=*/false))
1643 return false;
1644
1645 // Argument is a constant expression with an integer type.
1646 Hint.ValueExpr = R.get();
1647 }
1648 } else {
1649 // Enter constant expression including eof terminator into token stream.
1650 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1651 /*IsReinject=*/false);
1652 ConsumeAnnotationToken();
1654
1655 // Tokens following an error in an ill-formed constant expression will
1656 // remain in the token stream and must be removed.
1657 if (Tok.isNot(tok::eof)) {
1658 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1659 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1660 while (Tok.isNot(tok::eof))
1662 }
1663
1664 ConsumeToken(); // Consume the constant expression eof terminator.
1665
1666 if (R.isInvalid() ||
1667 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation(),
1668 /*AllowZero=*/true))
1669 return false;
1670
1671 // Argument is a constant expression with an integer type.
1672 Hint.ValueExpr = R.get();
1673 }
1674
1675 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
1676 Info->Toks.back().getLocation());
1677 return true;
1678}
1679
1680namespace {
1681struct PragmaAttributeInfo {
1682 enum ActionType { Push, Pop, Attribute };
1683 ParsedAttributes &Attributes;
1684 ActionType Action;
1685 const IdentifierInfo *Namespace = nullptr;
1686 ArrayRef<Token> Tokens;
1687
1688 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1689};
1690
1691#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1692
1693} // end anonymous namespace
1694
1695static StringRef getIdentifier(const Token &Tok) {
1696 if (Tok.is(tok::identifier))
1697 return Tok.getIdentifierInfo()->getName();
1698 const char *S = tok::getKeywordSpelling(Tok.getKind());
1699 if (!S)
1700 return "";
1701 return S;
1702}
1703
1705 using namespace attr;
1706 switch (Rule) {
1707#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1708 case Value: \
1709 return IsAbstract;
1710#include "clang/Basic/AttrSubMatchRulesList.inc"
1711 }
1712 llvm_unreachable("Invalid attribute subject match rule");
1713 return false;
1714}
1715
1717 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1718 SourceLocation SubRuleLoc) {
1719 auto Diagnostic =
1720 PRef.Diag(SubRuleLoc,
1721 diag::err_pragma_attribute_expected_subject_sub_identifier)
1722 << PrimaryRuleName;
1723 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1724 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1725 else
1726 Diagnostic << /*SubRulesSupported=*/0;
1727}
1728
1730 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1731 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1732
1733 auto Diagnostic =
1734 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1735 << SubRuleName << PrimaryRuleName;
1736 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1737 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1738 else
1739 Diagnostic << /*SubRulesSupported=*/0;
1740}
1741
1742bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1743 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1744 SourceLocation &LastMatchRuleEndLoc) {
1745 bool IsAny = false;
1746 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1747 if (getIdentifier(Tok) == "any") {
1748 AnyLoc = ConsumeToken();
1749 IsAny = true;
1750 if (AnyParens.expectAndConsume())
1751 return true;
1752 }
1753
1754 do {
1755 // Parse the subject matcher rule.
1756 StringRef Name = getIdentifier(Tok);
1757 if (Name.empty()) {
1758 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1759 return true;
1760 }
1761 std::pair<std::optional<attr::SubjectMatchRule>,
1762 std::optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1763 Rule = isAttributeSubjectMatchRule(Name);
1764 if (!Rule.first) {
1765 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1766 return true;
1767 }
1768 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1769 SourceLocation RuleLoc = ConsumeToken();
1770
1771 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1772 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1773 if (Parens.expectAndConsume())
1774 return true;
1775 } else if (Parens.consumeOpen()) {
1776 if (!SubjectMatchRules
1777 .insert(
1778 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1779 .second)
1780 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1781 << Name
1782 << FixItHint::CreateRemoval(SourceRange(
1783 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1784 LastMatchRuleEndLoc = RuleLoc;
1785 continue;
1786 }
1787
1788 // Parse the sub-rules.
1789 StringRef SubRuleName = getIdentifier(Tok);
1790 if (SubRuleName.empty()) {
1791 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1792 Tok.getLocation());
1793 return true;
1794 }
1795 attr::SubjectMatchRule SubRule;
1796 if (SubRuleName == "unless") {
1797 SourceLocation SubRuleLoc = ConsumeToken();
1798 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1799 if (Parens.expectAndConsume())
1800 return true;
1801 SubRuleName = getIdentifier(Tok);
1802 if (SubRuleName.empty()) {
1803 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1804 SubRuleLoc);
1805 return true;
1806 }
1807 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1808 if (!SubRuleOrNone) {
1809 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1810 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1811 SubRuleUnlessName, SubRuleLoc);
1812 return true;
1813 }
1814 SubRule = *SubRuleOrNone;
1815 ConsumeToken();
1816 if (Parens.consumeClose())
1817 return true;
1818 } else {
1819 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1820 if (!SubRuleOrNone) {
1821 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1822 SubRuleName, Tok.getLocation());
1823 return true;
1824 }
1825 SubRule = *SubRuleOrNone;
1826 ConsumeToken();
1827 }
1828 SourceLocation RuleEndLoc = Tok.getLocation();
1829 LastMatchRuleEndLoc = RuleEndLoc;
1830 if (Parens.consumeClose())
1831 return true;
1832 if (!SubjectMatchRules
1833 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1834 .second) {
1835 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1837 << FixItHint::CreateRemoval(SourceRange(
1838 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1839 continue;
1840 }
1841 } while (IsAny && TryConsumeToken(tok::comma));
1842
1843 if (IsAny)
1844 if (AnyParens.consumeClose())
1845 return true;
1846
1847 return false;
1848}
1849
1850namespace {
1851
1852/// Describes the stage at which attribute subject rule parsing was interrupted.
1853enum class MissingAttributeSubjectRulesRecoveryPoint {
1854 Comma,
1855 ApplyTo,
1856 Equals,
1857 Any,
1858 None,
1859};
1860
1861MissingAttributeSubjectRulesRecoveryPoint
1862getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1863 if (const auto *II = Tok.getIdentifierInfo()) {
1864 if (II->isStr("apply_to"))
1865 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1866 if (II->isStr("any"))
1867 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1868 }
1869 if (Tok.is(tok::equal))
1870 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1871 return MissingAttributeSubjectRulesRecoveryPoint::None;
1872}
1873
1874/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1875/// suggests the possible attribute subject rules in a fix-it together with
1876/// any other missing tokens.
1877DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1878 unsigned DiagID, ParsedAttributes &Attrs,
1879 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1881 if (Loc.isInvalid())
1882 Loc = PRef.getCurToken().getLocation();
1883 auto Diagnostic = PRef.Diag(Loc, DiagID);
1884 std::string FixIt;
1885 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1886 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1887 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1888 FixIt = ", ";
1889 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1890 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1891 FixIt += "apply_to";
1892 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1893 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1894 FixIt += " = ";
1895 SourceRange FixItRange(Loc);
1896 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1897 // Gather the subject match rules that are supported by the attribute.
1898 // Add all the possible rules initially.
1899 llvm::BitVector IsMatchRuleAvailable(attr::SubjectMatchRule_Last + 1, true);
1900 // Remove the ones that are not supported by any of the attributes.
1901 for (const ParsedAttr &Attribute : Attrs) {
1903 Attribute.getMatchRules(PRef.getLangOpts(), MatchRules);
1904 llvm::BitVector IsSupported(attr::SubjectMatchRule_Last + 1);
1905 for (const auto &Rule : MatchRules) {
1906 // Ensure that the missing rule is reported in the fix-it only when it's
1907 // supported in the current language mode.
1908 if (!Rule.second)
1909 continue;
1910 IsSupported[Rule.first] = true;
1911 }
1912 IsMatchRuleAvailable &= IsSupported;
1913 }
1914 if (IsMatchRuleAvailable.count() == 0) {
1915 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1916 // placeholders will be supported by the fix-its.
1917 return Diagnostic;
1918 }
1919 FixIt += "any(";
1920 bool NeedsComma = false;
1921 for (unsigned I = 0; I <= attr::SubjectMatchRule_Last; I++) {
1922 if (!IsMatchRuleAvailable[I])
1923 continue;
1924 if (NeedsComma)
1925 FixIt += ", ";
1926 else
1927 NeedsComma = true;
1929 static_cast<attr::SubjectMatchRule>(I));
1930 }
1931 FixIt += ")";
1932 // Check if we need to remove the range
1933 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1934 FixItRange.setEnd(PRef.getCurToken().getLocation());
1935 }
1936 if (FixItRange.getBegin() == FixItRange.getEnd())
1937 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1938 else
1940 CharSourceRange::getCharRange(FixItRange), FixIt);
1941 return Diagnostic;
1942}
1943
1944} // end anonymous namespace
1945
1946void Parser::HandlePragmaAttribute() {
1947 assert(Tok.is(tok::annot_pragma_attribute) &&
1948 "Expected #pragma attribute annotation token");
1949 SourceLocation PragmaLoc = Tok.getLocation();
1950 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1951 if (Info->Action == PragmaAttributeInfo::Pop) {
1952 ConsumeAnnotationToken();
1953 Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
1954 return;
1955 }
1956 // Parse the actual attribute with its arguments.
1957 assert((Info->Action == PragmaAttributeInfo::Push ||
1958 Info->Action == PragmaAttributeInfo::Attribute) &&
1959 "Unexpected #pragma attribute command");
1960
1961 if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
1962 ConsumeAnnotationToken();
1963 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1964 return;
1965 }
1966
1967 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
1968 /*IsReinject=*/false);
1969 ConsumeAnnotationToken();
1970
1971 ParsedAttributes &Attrs = Info->Attributes;
1972 Attrs.clearListOnly();
1973
1974 auto SkipToEnd = [this]() {
1975 SkipUntil(tok::eof, StopBeforeMatch);
1976 ConsumeToken();
1977 };
1978
1979 if ((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||
1980 Tok.isRegularKeywordAttribute()) {
1981 // Parse the CXX11 style attribute.
1982 SourceLocation EndLoc = Tok.getLocation();
1983 ParseCXX11AttributeSpecifier(Attrs, &EndLoc);
1984 } else if (Tok.is(tok::kw___attribute)) {
1985 ConsumeToken();
1986 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1987 "attribute"))
1988 return SkipToEnd();
1989 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1990 return SkipToEnd();
1991
1992 // FIXME: The practical usefulness of completion here is limited because
1993 // we only get here if the line has balanced parens.
1994 if (Tok.is(tok::code_completion)) {
1995 cutOffParsing();
1996 // FIXME: suppress completion of unsupported attributes?
1997 Actions.CodeCompletion().CodeCompleteAttribute(
1999 return SkipToEnd();
2000 }
2001
2002 // Parse the comma-separated list of attributes.
2003 do {
2004 if (Tok.isNot(tok::identifier)) {
2005 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
2006 SkipToEnd();
2007 return;
2008 }
2009 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
2010 SourceLocation AttrNameLoc = ConsumeToken();
2011
2012 if (Tok.isNot(tok::l_paren))
2013 Attrs.addNew(AttrName, AttrNameLoc, AttributeScopeInfo(), nullptr, 0,
2014 ParsedAttr::Form::GNU());
2015 else
2016 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
2017 /*ScopeName=*/nullptr,
2018 /*ScopeLoc=*/SourceLocation(),
2019 ParsedAttr::Form::GNU(),
2020 /*Declarator=*/nullptr);
2021 } while (TryConsumeToken(tok::comma));
2022
2023 if (ExpectAndConsume(tok::r_paren))
2024 return SkipToEnd();
2025 if (ExpectAndConsume(tok::r_paren))
2026 return SkipToEnd();
2027 } else if (Tok.is(tok::kw___declspec)) {
2028 ParseMicrosoftDeclSpecs(Attrs);
2029 } else {
2030 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
2031 if (Tok.getIdentifierInfo()) {
2032 // If we suspect that this is an attribute suggest the use of
2033 // '__attribute__'.
2035 Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
2037 SourceLocation InsertStartLoc = Tok.getLocation();
2038 ConsumeToken();
2039 if (Tok.is(tok::l_paren)) {
2041 SkipUntil(tok::r_paren, StopBeforeMatch);
2042 if (Tok.isNot(tok::r_paren))
2043 return SkipToEnd();
2044 }
2045 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
2046 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
2047 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
2048 }
2049 }
2050 SkipToEnd();
2051 return;
2052 }
2053
2054 if (Attrs.empty() || Attrs.begin()->isInvalid()) {
2055 SkipToEnd();
2056 return;
2057 }
2058
2059 for (const ParsedAttr &Attribute : Attrs) {
2060 if (!Attribute.isSupportedByPragmaAttribute()) {
2061 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
2062 << Attribute;
2063 SkipToEnd();
2064 return;
2065 }
2066 }
2067
2068 // Parse the subject-list.
2069 if (!TryConsumeToken(tok::comma)) {
2070 createExpectedAttributeSubjectRulesTokenDiagnostic(
2071 diag::err_expected, Attrs,
2072 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
2073 << tok::comma;
2074 SkipToEnd();
2075 return;
2076 }
2077
2078 if (Tok.isNot(tok::identifier)) {
2079 createExpectedAttributeSubjectRulesTokenDiagnostic(
2080 diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
2081 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
2082 SkipToEnd();
2083 return;
2084 }
2085 const IdentifierInfo *II = Tok.getIdentifierInfo();
2086 if (!II->isStr("apply_to")) {
2087 createExpectedAttributeSubjectRulesTokenDiagnostic(
2088 diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
2089 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
2090 SkipToEnd();
2091 return;
2092 }
2093 ConsumeToken();
2094
2095 if (!TryConsumeToken(tok::equal)) {
2096 createExpectedAttributeSubjectRulesTokenDiagnostic(
2097 diag::err_expected, Attrs,
2098 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
2099 << tok::equal;
2100 SkipToEnd();
2101 return;
2102 }
2103
2104 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
2105 SourceLocation AnyLoc, LastMatchRuleEndLoc;
2106 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
2107 LastMatchRuleEndLoc)) {
2108 SkipToEnd();
2109 return;
2110 }
2111
2112 // Tokens following an ill-formed attribute will remain in the token stream
2113 // and must be removed.
2114 if (Tok.isNot(tok::eof)) {
2115 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
2116 SkipToEnd();
2117 return;
2118 }
2119
2120 // Consume the eof terminator token.
2121 ConsumeToken();
2122
2123 // Handle a mixed push/attribute by desurging to a push, then an attribute.
2124 if (Info->Action == PragmaAttributeInfo::Push)
2125 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
2126
2127 for (ParsedAttr &Attribute : Attrs) {
2128 Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
2129 SubjectMatchRules);
2130 }
2131}
2132
2133// #pragma GCC visibility comes in two variants:
2134// 'push' '(' [visibility] ')'
2135// 'pop'
2136void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
2137 PragmaIntroducer Introducer,
2138 Token &VisTok) {
2139 SourceLocation VisLoc = VisTok.getLocation();
2140
2141 Token Tok;
2143
2144 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
2145
2146 const IdentifierInfo *VisType;
2147 if (PushPop && PushPop->isStr("pop")) {
2148 VisType = nullptr;
2149 } else if (PushPop && PushPop->isStr("push")) {
2151 if (Tok.isNot(tok::l_paren)) {
2152 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
2153 << "visibility";
2154 return;
2155 }
2157 VisType = Tok.getIdentifierInfo();
2158 if (!VisType) {
2159 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2160 << "visibility";
2161 return;
2162 }
2164 if (Tok.isNot(tok::r_paren)) {
2165 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
2166 << "visibility";
2167 return;
2168 }
2169 } else {
2170 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2171 << "visibility";
2172 return;
2173 }
2174 SourceLocation EndLoc = Tok.getLocation();
2176 if (Tok.isNot(tok::eod)) {
2177 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2178 << "visibility";
2179 return;
2180 }
2181
2182 auto Toks = std::make_unique<Token[]>(1);
2183 Toks[0] = Token::createAnnotation(
2184 tok::annot_pragma_vis, SourceRange(VisLoc, EndLoc),
2185 const_cast<void *>(static_cast<const void *>(VisType)));
2186 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
2187 /*IsReinject=*/false);
2188}
2189
2190// #pragma pack(...) comes in the following delicious flavors:
2191// pack '(' [integer] ')'
2192// pack '(' 'show' ')'
2193// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
2194// pack '(' 'packed' | 'full' | 'twobyte' | 'reset' ')' with -fzos-extensions
2195void PragmaPackHandler::HandlePragma(Preprocessor &PP,
2196 PragmaIntroducer Introducer,
2197 Token &PackTok) {
2198 SourceLocation PackLoc = PackTok.getLocation();
2199
2200 Token Tok;
2201 PP.Lex(Tok);
2202 if (Tok.isNot(tok::l_paren)) {
2203 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
2204 return;
2205 }
2206
2208 StringRef SlotLabel;
2209 Token Alignment;
2210 Alignment.startToken();
2211 PP.Lex(Tok);
2212 if (Tok.is(tok::numeric_constant)) {
2213 Alignment = Tok;
2214
2215 PP.Lex(Tok);
2216
2217 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
2218 // the push/pop stack.
2219 // In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4)
2220 Action = (PP.getLangOpts().ApplePragmaPack || PP.getLangOpts().XLPragmaPack)
2222 : Sema::PSK_Set;
2223 } else if (Tok.is(tok::identifier)) {
2224 // Map pragma pack options to pack (integer).
2225 auto MapPack = [&](const char *Literal) {
2226 Action = Sema::PSK_Push_Set;
2227 Alignment = Tok;
2228 Alignment.setKind(tok::numeric_constant);
2229 Alignment.setLiteralData(Literal);
2230 Alignment.setLength(1);
2231 };
2232
2233 const IdentifierInfo *II = Tok.getIdentifierInfo();
2234 if (II->isStr("show")) {
2235 Action = Sema::PSK_Show;
2236 PP.Lex(Tok);
2237 } else if (II->isStr("packed") && PP.getLangOpts().ZOSExt) {
2238 // #pragma pack(packed) is the same as #pragma pack(1)
2239 MapPack("1");
2240 PP.Lex(Tok);
2241 } else if (II->isStr("full") && PP.getLangOpts().ZOSExt) {
2242 // #pragma pack(full) is the same as #pragma pack(4)
2243 MapPack("4");
2244 PP.Lex(Tok);
2245 } else if (II->isStr("twobyte") && PP.getLangOpts().ZOSExt) {
2246 // #pragma pack(twobyte) is the same as #pragma pack(2)
2247 MapPack("2");
2248 PP.Lex(Tok);
2249 } else if (II->isStr("reset") && PP.getLangOpts().ZOSExt) {
2250 // #pragma pack(reset) is the same as #pragma pack(pop) on XL
2251 Action = Sema::PSK_Pop;
2252 PP.Lex(Tok);
2253 } else {
2254 if (II->isStr("push")) {
2255 Action = Sema::PSK_Push;
2256 } else if (II->isStr("pop")) {
2257 Action = Sema::PSK_Pop;
2258 } else {
2259 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
2260 return;
2261 }
2262 PP.Lex(Tok);
2263
2264 if (Tok.is(tok::comma)) {
2265 PP.Lex(Tok);
2266
2267 if (Tok.is(tok::numeric_constant)) {
2268 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
2269 Alignment = Tok;
2270
2271 PP.Lex(Tok);
2272 } else if (Tok.is(tok::identifier)) {
2273 SlotLabel = Tok.getIdentifierInfo()->getName();
2274 PP.Lex(Tok);
2275
2276 if (Tok.is(tok::comma)) {
2277 PP.Lex(Tok);
2278
2279 if (Tok.isNot(tok::numeric_constant)) {
2280 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
2281 return;
2282 }
2283
2284 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
2285 Alignment = Tok;
2286
2287 PP.Lex(Tok);
2288 }
2289 } else {
2290 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
2291 return;
2292 }
2293 }
2294 }
2295 } else if (PP.getLangOpts().ApplePragmaPack ||
2296 PP.getLangOpts().XLPragmaPack) {
2297 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
2298 // the push/pop stack.
2299 // In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma
2300 // pack(pop).
2301 Action = Sema::PSK_Pop;
2302 }
2303
2304 if (Tok.isNot(tok::r_paren)) {
2305 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
2306 return;
2307 }
2308
2309 SourceLocation RParenLoc = Tok.getLocation();
2310 PP.Lex(Tok);
2311 if (Tok.isNot(tok::eod)) {
2312 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
2313 return;
2314 }
2315
2316 Sema::PragmaPackInfo *Info =
2318 Info->Action = Action;
2319 Info->SlotLabel = SlotLabel;
2320 Info->Alignment = Alignment;
2321
2323 1);
2324 Toks[0] = Token::createAnnotation(tok::annot_pragma_pack,
2325 SourceRange(PackLoc, RParenLoc),
2326 static_cast<void *>(Info));
2327 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2328 /*IsReinject=*/false);
2329}
2330
2331// #pragma ms_struct on
2332// #pragma ms_struct off
2333void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
2334 PragmaIntroducer Introducer,
2335 Token &MSStructTok) {
2337
2338 Token Tok;
2339 PP.Lex(Tok);
2340 if (Tok.isNot(tok::identifier)) {
2341 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
2342 return;
2343 }
2344 SourceLocation EndLoc = Tok.getLocation();
2345 const IdentifierInfo *II = Tok.getIdentifierInfo();
2346 if (II->isStr("on")) {
2347 Kind = PMSST_ON;
2348 PP.Lex(Tok);
2349 }
2350 else if (II->isStr("off") || II->isStr("reset"))
2351 PP.Lex(Tok);
2352 else {
2353 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
2354 return;
2355 }
2356
2357 if (Tok.isNot(tok::eod)) {
2358 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2359 << "ms_struct";
2360 return;
2361 }
2362
2364 1);
2365 Toks[0] = Token::createAnnotation(
2366 tok::annot_pragma_msstruct,
2367 SourceRange(MSStructTok.getLocation(), EndLoc),
2368 reinterpret_cast<void *>(static_cast<uintptr_t>(Kind)));
2369 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2370 /*IsReinject=*/false);
2371}
2372
2373// #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
2374void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
2375 PragmaIntroducer Introducer,
2376 Token &FirstToken) {
2377
2378 Token Tok;
2379 auto SecKind = PragmaClangSectionKind::Invalid;
2380
2381 PP.Lex(Tok); // eat 'section'
2382 while (Tok.isNot(tok::eod)) {
2383 if (Tok.isNot(tok::identifier)) {
2384 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
2385 return;
2386 }
2387
2388 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
2389 if (SecType->isStr("bss"))
2391 else if (SecType->isStr("data"))
2393 else if (SecType->isStr("rodata"))
2395 else if (SecType->isStr("relro"))
2397 else if (SecType->isStr("text"))
2399 else {
2400 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
2401 return;
2402 }
2403
2404 SourceLocation PragmaLocation = Tok.getLocation();
2405 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
2406 if (Tok.isNot(tok::equal)) {
2407 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal)
2408 << SecKind;
2409 return;
2410 }
2411
2412 std::string SecName;
2413 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
2414 return;
2415
2416 Actions.ActOnPragmaClangSection(PragmaLocation,
2417 (SecName.size()
2420 SecKind, SecName);
2421 }
2422}
2423
2424// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
2425// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
2426// #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'
2427static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
2428 bool IsOptions) {
2429 Token Tok;
2430
2431 if (IsOptions) {
2432 PP.Lex(Tok);
2433 if (Tok.isNot(tok::identifier) ||
2434 !Tok.getIdentifierInfo()->isStr("align")) {
2435 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
2436 return;
2437 }
2438 }
2439
2440 PP.Lex(Tok);
2441 if (PP.getLangOpts().XLPragmaPack) {
2442 if (Tok.isNot(tok::l_paren)) {
2443 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align";
2444 return;
2445 }
2446 } else if (Tok.isNot(tok::equal)) {
2447 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
2448 << IsOptions;
2449 return;
2450 }
2451
2452 PP.Lex(Tok);
2453 if (Tok.isNot(tok::identifier)) {
2454 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2455 << (IsOptions ? "options" : "align");
2456 return;
2457 }
2458
2460 const IdentifierInfo *II = Tok.getIdentifierInfo();
2461 if (II->isStr("native"))
2463 else if (II->isStr("natural"))
2465 else if (II->isStr("packed"))
2467 else if (II->isStr("power"))
2469 else if (II->isStr("mac68k"))
2471 else if (II->isStr("reset"))
2473 else {
2474 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
2475 << IsOptions;
2476 return;
2477 }
2478
2479 if (PP.getLangOpts().XLPragmaPack) {
2480 PP.Lex(Tok);
2481 if (Tok.isNot(tok::r_paren)) {
2482 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align";
2483 return;
2484 }
2485 }
2486
2487 SourceLocation EndLoc = Tok.getLocation();
2488 PP.Lex(Tok);
2489 if (Tok.isNot(tok::eod)) {
2490 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2491 << (IsOptions ? "options" : "align");
2492 return;
2493 }
2494
2496 1);
2497 Toks[0] = Token::createAnnotation(
2498 tok::annot_pragma_align, SourceRange(FirstTok.getLocation(), EndLoc),
2499 reinterpret_cast<void *>(static_cast<uintptr_t>(Kind)));
2500 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2501 /*IsReinject=*/false);
2502}
2503
2504void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
2505 PragmaIntroducer Introducer,
2506 Token &AlignTok) {
2507 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
2508}
2509
2510void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
2511 PragmaIntroducer Introducer,
2512 Token &OptionsTok) {
2513 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
2514}
2515
2516// #pragma unused(identifier)
2517void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
2518 PragmaIntroducer Introducer,
2519 Token &UnusedTok) {
2520 // FIXME: Should we be expanding macros here? My guess is no.
2521 SourceLocation UnusedLoc = UnusedTok.getLocation();
2522
2523 // Lex the left '('.
2524 Token Tok;
2525 PP.Lex(Tok);
2526 if (Tok.isNot(tok::l_paren)) {
2527 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
2528 return;
2529 }
2530
2531 // Lex the declaration reference(s).
2532 SmallVector<Token, 5> Identifiers;
2533 SourceLocation RParenLoc;
2534 bool LexID = true;
2535
2536 while (true) {
2537 PP.Lex(Tok);
2538
2539 if (LexID) {
2540 if (Tok.is(tok::identifier)) {
2541 Identifiers.push_back(Tok);
2542 LexID = false;
2543 continue;
2544 }
2545
2546 // Illegal token!
2547 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
2548 return;
2549 }
2550
2551 // We are execting a ')' or a ','.
2552 if (Tok.is(tok::comma)) {
2553 LexID = true;
2554 continue;
2555 }
2556
2557 if (Tok.is(tok::r_paren)) {
2558 RParenLoc = Tok.getLocation();
2559 break;
2560 }
2561
2562 // Illegal token!
2563 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
2564 return;
2565 }
2566
2567 PP.Lex(Tok);
2568 if (Tok.isNot(tok::eod)) {
2569 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2570 "unused";
2571 return;
2572 }
2573
2574 // Verify that we have a location for the right parenthesis.
2575 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
2576 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
2577
2578 // For each identifier token, insert into the token stream a
2579 // annot_pragma_unused token followed by the identifier token.
2580 // This allows us to cache a "#pragma unused" that occurs inside an inline
2581 // C++ member function.
2582
2584 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
2585 2 * Identifiers.size());
2586 for (unsigned i=0; i != Identifiers.size(); i++) {
2587 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
2588 pragmaUnusedTok =
2589 Token::createAnnotation(tok::annot_pragma_unused, UnusedLoc);
2590 idTok = Identifiers[i];
2591 }
2592 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2593 /*IsReinject=*/false);
2594}
2595
2596// #pragma weak identifier
2597// #pragma weak identifier '=' identifier
2598void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
2599 PragmaIntroducer Introducer,
2600 Token &WeakTok) {
2601 SourceLocation WeakLoc = WeakTok.getLocation();
2602
2603 Token Tok;
2604 PP.Lex(Tok);
2605 if (Tok.isNot(tok::identifier)) {
2606 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
2607 return;
2608 }
2609
2610 Token WeakName = Tok;
2611 bool HasAlias = false;
2612 Token AliasName;
2613
2614 PP.Lex(Tok);
2615 if (Tok.is(tok::equal)) {
2616 HasAlias = true;
2617 PP.Lex(Tok);
2618 if (Tok.isNot(tok::identifier)) {
2619 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2620 << "weak";
2621 return;
2622 }
2623 AliasName = Tok;
2624 PP.Lex(Tok);
2625 }
2626
2627 if (Tok.isNot(tok::eod)) {
2628 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
2629 return;
2630 }
2631
2632 if (HasAlias) {
2634 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
2635 Token &pragmaUnusedTok = Toks[0];
2636 pragmaUnusedTok =
2637 Token::createAnnotation(tok::annot_pragma_weakalias,
2638 SourceRange(WeakLoc, AliasName.getLocation()));
2639 Toks[1] = WeakName;
2640 Toks[2] = AliasName;
2641 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2642 /*IsReinject=*/false);
2643 } else {
2645 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
2646 Token &pragmaUnusedTok = Toks[0];
2647 pragmaUnusedTok = Token::createAnnotation(tok::annot_pragma_weak, WeakLoc);
2648 Toks[1] = WeakName;
2649 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2650 /*IsReinject=*/false);
2651 }
2652}
2653
2654// #pragma redefine_extname identifier identifier
2655void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
2656 PragmaIntroducer Introducer,
2657 Token &RedefToken) {
2658 SourceLocation RedefLoc = RedefToken.getLocation();
2659
2660 Token Tok;
2661 PP.Lex(Tok);
2662 if (Tok.isNot(tok::identifier)) {
2663 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2664 "redefine_extname";
2665 return;
2666 }
2667
2668 Token RedefName = Tok;
2669 PP.Lex(Tok);
2670
2671 if (Tok.isNot(tok::identifier)) {
2672 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2673 << "redefine_extname";
2674 return;
2675 }
2676
2677 Token AliasName = Tok;
2678 PP.Lex(Tok);
2679
2680 if (Tok.isNot(tok::eod)) {
2681 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2682 "redefine_extname";
2683 return;
2684 }
2685
2687 3);
2688 Token &pragmaRedefTok = Toks[0];
2689 pragmaRedefTok =
2690 Token::createAnnotation(tok::annot_pragma_redefine_extname,
2691 SourceRange(RedefLoc, AliasName.getLocation()));
2692 Toks[1] = RedefName;
2693 Toks[2] = AliasName;
2694 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2695 /*IsReinject=*/false);
2696}
2697
2698void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2699 PragmaIntroducer Introducer,
2700 Token &Tok) {
2701 tok::OnOffSwitch OOS;
2702 if (PP.LexOnOffSwitch(OOS))
2703 return;
2704
2706 1);
2707 Toks[0] = Token::createAnnotation(
2708 tok::annot_pragma_fp_contract, Tok.getLocation(),
2709 reinterpret_cast<void *>(static_cast<uintptr_t>(OOS)));
2710 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2711 /*IsReinject=*/false);
2712}
2713
2714void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2715 PragmaIntroducer Introducer,
2716 Token &Tok) {
2718 if (Tok.isNot(tok::identifier)) {
2719 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2720 "OPENCL";
2721 return;
2722 }
2724 SourceLocation NameLoc = Tok.getLocation();
2725
2726 PP.Lex(Tok);
2727 if (Tok.isNot(tok::colon)) {
2728 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
2729 return;
2730 }
2731
2732 PP.Lex(Tok);
2733 if (Tok.isNot(tok::identifier)) {
2734 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
2735 return;
2736 }
2738
2739 OpenCLExtState State;
2740 if (Pred->isStr("enable")) {
2741 State = Enable;
2742 } else if (Pred->isStr("disable")) {
2743 State = Disable;
2744 } else if (Pred->isStr("begin"))
2745 State = Begin;
2746 else if (Pred->isStr("end"))
2747 State = End;
2748 else {
2749 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2750 << Ext->isStr("all");
2751 return;
2752 }
2753 SourceLocation StateLoc = Tok.getLocation();
2754
2755 PP.Lex(Tok);
2756 if (Tok.isNot(tok::eod)) {
2757 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2758 "OPENCL EXTENSION";
2759 return;
2760 }
2761
2762 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2763 Info->first = Ext;
2764 Info->second = State;
2766 1);
2767 Toks[0] = Token::createAnnotation(tok::annot_pragma_opencl_extension,
2768 SourceRange(NameLoc, StateLoc),
2769 static_cast<void *>(Info));
2770 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2771 /*IsReinject=*/false);
2772
2773 if (PP.getPPCallbacks())
2774 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2775 StateLoc, State);
2776}
2777
2778/// Handle '#pragma omp ...' when OpenMP is disabled and '#pragma acc ...' when
2779/// OpenACC is disabled.
2780template <diag::kind IgnoredDiag>
2781void PragmaNoSupportHandler<IgnoredDiag>::HandlePragma(
2782 Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstTok) {
2783 if (!PP.getDiagnostics().isIgnored(IgnoredDiag, FirstTok.getLocation())) {
2784 PP.Diag(FirstTok, IgnoredDiag);
2786 SourceLocation());
2787 }
2789}
2790
2791/// Handle '#pragma omp ...' when OpenMP is enabled, and handle '#pragma acc...'
2792/// when OpenACC is enabled.
2793template <tok::TokenKind StartTok, tok::TokenKind EndTok,
2794 diag::kind UnexpectedDiag>
2795void PragmaSupportHandler<StartTok, EndTok, UnexpectedDiag>::HandlePragma(
2796 Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstTok) {
2798 Token Tok = Token::createAnnotation(StartTok, Introducer.Loc);
2799
2800 while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
2801 Pragma.push_back(Tok);
2802 PP.Lex(Tok);
2803 if (Tok.is(StartTok)) {
2804 PP.Diag(Tok, UnexpectedDiag) << 0;
2805 unsigned InnerPragmaCnt = 1;
2806 while (InnerPragmaCnt != 0) {
2807 PP.Lex(Tok);
2808 if (Tok.is(StartTok))
2809 ++InnerPragmaCnt;
2810 else if (Tok.is(EndTok))
2811 --InnerPragmaCnt;
2812 }
2813 PP.Lex(Tok);
2814 }
2815 }
2816 SourceLocation EodLoc = Tok.getLocation();
2817 Tok = Token::createAnnotation(EndTok, EodLoc);
2818 Pragma.push_back(Tok);
2819
2820 auto Toks = std::make_unique<Token[]>(Pragma.size());
2821 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2822 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2823 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2824}
2825
2826/// Handle '#pragma pointers_to_members'
2827// The grammar for this pragma is as follows:
2828//
2829// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2830//
2831// #pragma pointers_to_members '(' 'best_case' ')'
2832// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2833// #pragma pointers_to_members '(' inheritance-model ')'
2834void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2835 PragmaIntroducer Introducer,
2836 Token &Tok) {
2837 SourceLocation PointersToMembersLoc = Tok.getLocation();
2838 PP.Lex(Tok);
2839 if (Tok.isNot(tok::l_paren)) {
2840 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2841 << "pointers_to_members";
2842 return;
2843 }
2844 PP.Lex(Tok);
2845 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2846 if (!Arg) {
2847 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2848 << "pointers_to_members";
2849 return;
2850 }
2851 PP.Lex(Tok);
2852
2853 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
2854 if (Arg->isStr("best_case")) {
2855 RepresentationMethod = LangOptions::PPTMK_BestCase;
2856 } else {
2857 if (Arg->isStr("full_generality")) {
2858 if (Tok.is(tok::comma)) {
2859 PP.Lex(Tok);
2860
2861 Arg = Tok.getIdentifierInfo();
2862 if (!Arg) {
2863 PP.Diag(Tok.getLocation(),
2864 diag::err_pragma_pointers_to_members_unknown_kind)
2865 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2866 return;
2867 }
2868 PP.Lex(Tok);
2869 } else if (Tok.is(tok::r_paren)) {
2870 // #pragma pointers_to_members(full_generality) implicitly specifies
2871 // virtual_inheritance.
2872 Arg = nullptr;
2874 } else {
2875 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2876 << "full_generality";
2877 return;
2878 }
2879 }
2880
2881 if (Arg) {
2882 if (Arg->isStr("single_inheritance")) {
2883 RepresentationMethod =
2885 } else if (Arg->isStr("multiple_inheritance")) {
2886 RepresentationMethod =
2888 } else if (Arg->isStr("virtual_inheritance")) {
2889 RepresentationMethod =
2891 } else {
2892 PP.Diag(Tok.getLocation(),
2893 diag::err_pragma_pointers_to_members_unknown_kind)
2894 << Arg << /*HasPointerDeclaration*/ 1;
2895 return;
2896 }
2897 }
2898 }
2899
2900 if (Tok.isNot(tok::r_paren)) {
2901 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2902 << (Arg ? Arg->getName() : "full_generality");
2903 return;
2904 }
2905
2906 SourceLocation EndLoc = Tok.getLocation();
2907 PP.Lex(Tok);
2908 if (Tok.isNot(tok::eod)) {
2909 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2910 << "pointers_to_members";
2911 return;
2912 }
2913
2914 Token AnnotTok = Token::createAnnotation(
2915 tok::annot_pragma_ms_pointers_to_members,
2916 SourceRange(PointersToMembersLoc, EndLoc),
2917 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2918 PP.EnterToken(AnnotTok, /*IsReinject=*/true);
2919}
2920
2921/// Handle '#pragma vtordisp'
2922// The grammar for this pragma is as follows:
2923//
2924// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2925//
2926// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2927// #pragma vtordisp '(' 'pop' ')'
2928// #pragma vtordisp '(' ')'
2929void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2930 PragmaIntroducer Introducer, Token &Tok) {
2931 SourceLocation VtorDispLoc = Tok.getLocation();
2932 PP.Lex(Tok);
2933 if (Tok.isNot(tok::l_paren)) {
2934 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2935 return;
2936 }
2937 PP.Lex(Tok);
2938
2940 const IdentifierInfo *II = Tok.getIdentifierInfo();
2941 if (II) {
2942 if (II->isStr("push")) {
2943 // #pragma vtordisp(push, mode)
2944 PP.Lex(Tok);
2945 if (Tok.isNot(tok::comma)) {
2946 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2947 return;
2948 }
2949 PP.Lex(Tok);
2950 Action = Sema::PSK_Push_Set;
2951 // not push, could be on/off
2952 } else if (II->isStr("pop")) {
2953 // #pragma vtordisp(pop)
2954 PP.Lex(Tok);
2955 Action = Sema::PSK_Pop;
2956 }
2957 // not push or pop, could be on/off
2958 } else {
2959 if (Tok.is(tok::r_paren)) {
2960 // #pragma vtordisp()
2961 Action = Sema::PSK_Reset;
2962 }
2963 }
2964
2965
2966 uint64_t Value = 0;
2967 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
2968 const IdentifierInfo *II = Tok.getIdentifierInfo();
2969 if (II && II->isStr("off")) {
2970 PP.Lex(Tok);
2971 Value = 0;
2972 } else if (II && II->isStr("on")) {
2973 PP.Lex(Tok);
2974 Value = 1;
2975 } else if (Tok.is(tok::numeric_constant) &&
2977 if (Value > 2) {
2978 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2979 << 0 << 2 << "vtordisp";
2980 return;
2981 }
2982 } else {
2983 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2984 << "vtordisp";
2985 return;
2986 }
2987 }
2988
2989 // Finish the pragma: ')' $
2990 if (Tok.isNot(tok::r_paren)) {
2991 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2992 return;
2993 }
2994 SourceLocation EndLoc = Tok.getLocation();
2995 PP.Lex(Tok);
2996 if (Tok.isNot(tok::eod)) {
2997 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2998 << "vtordisp";
2999 return;
3000 }
3001
3002 // Enter the annotation.
3003 Token AnnotTok = Token::createAnnotation(
3004 tok::annot_pragma_ms_vtordisp, SourceRange(VtorDispLoc, EndLoc),
3005 reinterpret_cast<void *>(
3006 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
3007 PP.EnterToken(AnnotTok, /*IsReinject=*/false);
3008}
3009
3010/// Handle all MS pragmas. Simply forwards the tokens after inserting
3011/// an annotation token.
3012void PragmaMSPragma::HandlePragma(Preprocessor &PP,
3013 PragmaIntroducer Introducer, Token &Tok) {
3014 Token EoF = Token::createEof();
3015 Token AnnotTok =
3016 Token::createAnnotation(tok::annot_pragma_ms_pragma, Tok.getLocation());
3017 SmallVector<Token, 8> TokenVector;
3018 // Suck up all of the tokens before the eod.
3019 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
3020 TokenVector.push_back(Tok);
3022 }
3023 // Add a sentinel EoF token to the end of the list.
3024 TokenVector.push_back(EoF);
3025 // We must allocate this array with new because EnterTokenStream is going to
3026 // delete it later.
3027 markAsReinjectedForRelexing(TokenVector);
3028 auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
3029 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
3030 auto Value = new (PP.getPreprocessorAllocator())
3031 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
3032 TokenVector.size());
3033 AnnotTok.setAnnotationValue(Value);
3034 PP.EnterToken(AnnotTok, /*IsReinject*/ false);
3035}
3036
3037/// Handle the \#pragma float_control extension.
3038///
3039/// The syntax is:
3040/// \code
3041/// #pragma float_control(keyword[, setting] [,push])
3042/// \endcode
3043/// Where 'keyword' and 'setting' are identifiers.
3044// 'keyword' can be: precise, except, push, pop
3045// 'setting' can be: on, off
3046/// The optional arguments 'setting' and 'push' are supported only
3047/// when the keyword is 'precise' or 'except'.
3048void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
3049 PragmaIntroducer Introducer,
3050 Token &Tok) {
3052 SourceLocation FloatControlLoc = Tok.getLocation();
3053 Token PragmaName = Tok;
3054 if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
3055 PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
3056 << PragmaName.getIdentifierInfo()->getName();
3057 return;
3058 }
3059 PP.Lex(Tok);
3060 if (Tok.isNot(tok::l_paren)) {
3061 PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
3062 return;
3063 }
3064
3065 // Read the identifier.
3066 PP.Lex(Tok);
3067 if (Tok.isNot(tok::identifier)) {
3068 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3069 return;
3070 }
3071
3072 // Verify that this is one of the float control options.
3075 llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
3076 .Case("precise", PFC_Precise)
3077 .Case("except", PFC_Except)
3078 .Case("push", PFC_Push)
3079 .Case("pop", PFC_Pop)
3080 .Default(PFC_Unknown);
3081 PP.Lex(Tok); // the identifier
3082 if (Kind == PFC_Unknown) {
3083 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3084 return;
3085 } else if (Kind == PFC_Push || Kind == PFC_Pop) {
3086 if (Tok.isNot(tok::r_paren)) {
3087 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3088 return;
3089 }
3090 PP.Lex(Tok); // Eat the r_paren
3091 Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push;
3092 } else {
3093 if (Tok.is(tok::r_paren))
3094 // Selecting Precise or Except
3095 PP.Lex(Tok); // the r_paren
3096 else if (Tok.isNot(tok::comma)) {
3097 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3098 return;
3099 } else {
3100 PP.Lex(Tok); // ,
3101 if (!Tok.isAnyIdentifier()) {
3102 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3103 return;
3104 }
3105 StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
3106 if (PushOnOff == "on")
3107 // Kind is set correctly
3108 ;
3109 else if (PushOnOff == "off") {
3110 if (Kind == PFC_Precise)
3112 if (Kind == PFC_Except)
3114 } else if (PushOnOff == "push") {
3115 Action = Sema::PSK_Push_Set;
3116 } else {
3117 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3118 return;
3119 }
3120 PP.Lex(Tok); // the identifier
3121 if (Tok.is(tok::comma)) {
3122 PP.Lex(Tok); // ,
3123 if (!Tok.isAnyIdentifier()) {
3124 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3125 return;
3126 }
3127 StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
3128 if (ExpectedPush == "push") {
3129 Action = Sema::PSK_Push_Set;
3130 } else {
3131 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3132 return;
3133 }
3134 PP.Lex(Tok); // the push identifier
3135 }
3136 if (Tok.isNot(tok::r_paren)) {
3137 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3138 return;
3139 }
3140 PP.Lex(Tok); // the r_paren
3141 }
3142 }
3143 SourceLocation EndLoc = Tok.getLocation();
3144 if (Tok.isNot(tok::eod)) {
3145 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3146 << "float_control";
3147 return;
3148 }
3149
3150 // Note: there is no accomodation for PP callback for this pragma.
3151
3152 // Enter the annotation.
3153 auto TokenArray = std::make_unique<Token[]>(1);
3154 // Create an encoding of Action and Value by shifting the Action into
3155 // the high 16 bits then union with the Kind.
3156 TokenArray[0] = Token::createAnnotation(
3157 tok::annot_pragma_float_control, SourceRange(FloatControlLoc, EndLoc),
3158 reinterpret_cast<void *>(
3159 static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
3160 PP.EnterTokenStream(std::move(TokenArray), 1,
3161 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3162}
3163
3164/// Handle the Microsoft \#pragma detect_mismatch extension.
3165///
3166/// The syntax is:
3167/// \code
3168/// #pragma detect_mismatch("name", "value")
3169/// \endcode
3170/// Where 'name' and 'value' are quoted strings. The values are embedded in
3171/// the object file and passed along to the linker. If the linker detects a
3172/// mismatch in the object file's values for the given name, a LNK2038 error
3173/// is emitted. See MSDN for more details.
3174void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
3175 PragmaIntroducer Introducer,
3176 Token &Tok) {
3177 SourceLocation DetectMismatchLoc = Tok.getLocation();
3178 PP.Lex(Tok);
3179 if (Tok.isNot(tok::l_paren)) {
3180 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
3181 return;
3182 }
3183
3184 // Read the name to embed, which must be a string literal.
3185 std::string NameString;
3186 if (!PP.LexStringLiteral(Tok, NameString,
3187 "pragma detect_mismatch",
3188 /*AllowMacroExpansion=*/true))
3189 return;
3190
3191 // Read the comma followed by a second string literal.
3192 std::string ValueString;
3193 if (Tok.isNot(tok::comma)) {
3194 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
3195 return;
3196 }
3197
3198 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
3199 /*AllowMacroExpansion=*/true))
3200 return;
3201
3202 if (Tok.isNot(tok::r_paren)) {
3203 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3204 return;
3205 }
3206 PP.Lex(Tok); // Eat the r_paren.
3207
3208 if (Tok.isNot(tok::eod)) {
3209 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
3210 return;
3211 }
3212
3213 // If the pragma is lexically sound, notify any interested PPCallbacks.
3214 if (PP.getPPCallbacks())
3215 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
3216 ValueString);
3217
3218 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
3219}
3220
3221/// Handle the microsoft \#pragma comment extension.
3222///
3223/// The syntax is:
3224/// \code
3225/// #pragma comment(linker, "foo")
3226/// \endcode
3227/// 'linker' is one of six identifiers: compiler, copyright, exestr, lib,
3228/// linker, user.
3229///
3230/// "foo" is a string, which is fully macro expanded, and permits string
3231/// concatenation, embedded escape characters etc. See MSDN for more details.
3232void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
3233 PragmaIntroducer Introducer,
3234 Token &Tok) {
3235 SourceLocation CommentLoc = Tok.getLocation();
3236 PP.Lex(Tok);
3237 if (Tok.isNot(tok::l_paren)) {
3238 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
3239 return;
3240 }
3241
3242 // Read the identifier.
3243 PP.Lex(Tok);
3244 if (Tok.isNot(tok::identifier)) {
3245 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
3246 return;
3247 }
3248
3249 // Verify that this is one of the 6 explicitly listed options.
3252 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
3253 .Case("linker", PCK_Linker)
3254 .Case("lib", PCK_Lib)
3255 .Case("compiler", PCK_Compiler)
3256 .Case("exestr", PCK_ExeStr)
3257 .Case("user", PCK_User)
3258 .Case("copyright", PCK_Copyright)
3259 .Default(PCK_Unknown);
3260 if (Kind == PCK_Unknown) {
3261 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
3262 return;
3263 }
3264
3265 if (PP.getTargetInfo().getTriple().isOSAIX() && Kind != PCK_Copyright) {
3266 // Currently, pragma comment kinds aside from "copyright" are not fully
3267 // implemented by Clang for AIX targets.
3268 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
3269 << II->getName();
3270 return;
3271 }
3272
3273 if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
3274 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
3275 << II->getName();
3276 return;
3277 }
3278
3279 // Handle pragma comment copyright kind.
3280 if (Kind == PCK_Copyright) {
3281 if (SeenCopyrightInTU) {
3282 // pragma comment copyright can each appear only once in a TU.
3283 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_once)
3284 << II->getName();
3285 return;
3286 }
3287 SeenCopyrightInTU = true;
3288 }
3289
3290 // Read the optional string if present.
3291 PP.Lex(Tok);
3292 std::string ArgumentString;
3293 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
3294 "pragma comment",
3295 /*AllowMacroExpansion=*/true))
3296 return;
3297
3298 // FIXME: warn that 'exestr' is deprecated.
3299 // FIXME: If the kind is "compiler" warn if the string is present (it is
3300 // ignored).
3301 // The MSDN docs say that "lib" and "linker" require a string and have a short
3302 // list of linker options they support, but in practice MSVC doesn't
3303 // issue a diagnostic. Therefore neither does clang.
3304
3305 if (Tok.isNot(tok::r_paren)) {
3306 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
3307 return;
3308 }
3309 PP.Lex(Tok); // eat the r_paren.
3310
3311 if (Tok.isNot(tok::eod)) {
3312 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
3313 return;
3314 }
3315
3316 // Skip further processing for well-formed copyright with an empty string.
3317 if (Kind == PCK_Copyright && ArgumentString.empty())
3318 return;
3319
3320 // If the pragma is lexically sound, notify any interested PPCallbacks.
3321 if (PP.getPPCallbacks())
3322 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
3323
3324 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
3325}
3326
3327// #pragma clang optimize off
3328// #pragma clang optimize on
3329void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
3330 PragmaIntroducer Introducer,
3331 Token &FirstToken) {
3332 Token Tok;
3333 PP.Lex(Tok);
3334 if (Tok.is(tok::eod)) {
3335 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3336 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
3337 return;
3338 }
3339 if (Tok.isNot(tok::identifier)) {
3340 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
3341 << PP.getSpelling(Tok);
3342 return;
3343 }
3344 const IdentifierInfo *II = Tok.getIdentifierInfo();
3345 // The only accepted values are 'on' or 'off'.
3346 bool IsOn = false;
3347 if (II->isStr("on")) {
3348 IsOn = true;
3349 } else if (!II->isStr("off")) {
3350 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
3351 << PP.getSpelling(Tok);
3352 return;
3353 }
3354 PP.Lex(Tok);
3355
3356 if (Tok.isNot(tok::eod)) {
3357 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
3358 << PP.getSpelling(Tok);
3359 return;
3360 }
3361
3362 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
3363}
3364
3365namespace {
3366/// Used as the annotation value for tok::annot_pragma_fp.
3367struct TokFPAnnotValue {
3368 enum FlagValues { On, Off, Fast };
3369
3370 std::optional<LangOptions::FPModeKind> ContractValue;
3371 std::optional<LangOptions::FPModeKind> ReassociateValue;
3372 std::optional<LangOptions::FPModeKind> ReciprocalValue;
3373 std::optional<LangOptions::FPExceptionModeKind> ExceptionsValue;
3374 std::optional<LangOptions::FPEvalMethodKind> EvalMethodValue;
3375};
3376} // end anonymous namespace
3377
3378void PragmaFPHandler::HandlePragma(Preprocessor &PP,
3379 PragmaIntroducer Introducer, Token &Tok) {
3380 // fp
3381 Token PragmaName = Tok;
3382 SmallVector<Token, 1> TokenList;
3383
3384 PP.Lex(Tok);
3385 if (Tok.isNot(tok::identifier)) {
3386 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
3387 << /*MissingOption=*/true << "";
3388 return;
3389 }
3390
3391 auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue;
3392 while (Tok.is(tok::identifier)) {
3393 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3394
3395 auto FlagKind =
3396 llvm::StringSwitch<std::optional<PragmaFPKind>>(OptionInfo->getName())
3397 .Case("contract", PFK_Contract)
3398 .Case("reassociate", PFK_Reassociate)
3399 .Case("exceptions", PFK_Exceptions)
3400 .Case("eval_method", PFK_EvalMethod)
3401 .Case("reciprocal", PFK_Reciprocal)
3402 .Default(std::nullopt);
3403 if (!FlagKind) {
3404 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
3405 << /*MissingOption=*/false << OptionInfo;
3406 return;
3407 }
3408 PP.Lex(Tok);
3409
3410 // Read '('
3411 if (Tok.isNot(tok::l_paren)) {
3412 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3413 return;
3414 }
3415 PP.Lex(Tok);
3416 bool isEvalMethodDouble =
3417 Tok.is(tok::kw_double) && FlagKind == PFK_EvalMethod;
3418
3419 // Don't diagnose if we have an eval_metod pragma with "double" kind.
3420 if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) {
3421 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3422 << PP.getSpelling(Tok) << OptionInfo->getName()
3423 << static_cast<int>(*FlagKind);
3424 return;
3425 }
3426 const IdentifierInfo *II = Tok.getIdentifierInfo();
3427
3428 if (FlagKind == PFK_Contract) {
3429 AnnotValue->ContractValue =
3430 llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
3431 II->getName())
3435 .Default(std::nullopt);
3436 if (!AnnotValue->ContractValue) {
3437 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3438 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3439 return;
3440 }
3441 } else if (FlagKind == PFK_Reassociate || FlagKind == PFK_Reciprocal) {
3442 auto &Value = FlagKind == PFK_Reassociate ? AnnotValue->ReassociateValue
3443 : AnnotValue->ReciprocalValue;
3444 Value = llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
3445 II->getName())
3448 .Default(std::nullopt);
3449 if (!Value) {
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_Exceptions) {
3455 AnnotValue->ExceptionsValue =
3456 llvm::StringSwitch<std::optional<LangOptions::FPExceptionModeKind>>(
3457 II->getName())
3458 .Case("ignore", LangOptions::FPE_Ignore)
3459 .Case("maytrap", LangOptions::FPE_MayTrap)
3460 .Case("strict", LangOptions::FPE_Strict)
3461 .Default(std::nullopt);
3462 if (!AnnotValue->ExceptionsValue) {
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_EvalMethod) {
3468 AnnotValue->EvalMethodValue =
3469 llvm::StringSwitch<std::optional<LangOptions::FPEvalMethodKind>>(
3470 II->getName())
3474 .Default(std::nullopt);
3475 if (!AnnotValue->EvalMethodValue) {
3476 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3477 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3478 return;
3479 }
3480 }
3481 PP.Lex(Tok);
3482
3483 // Read ')'
3484 if (Tok.isNot(tok::r_paren)) {
3485 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3486 return;
3487 }
3488 PP.Lex(Tok);
3489 }
3490
3491 if (Tok.isNot(tok::eod)) {
3492 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3493 << "clang fp";
3494 return;
3495 }
3496
3497 Token FPTok =
3498 Token::createAnnotation(tok::annot_pragma_fp, PragmaName.getLocation(),
3499 reinterpret_cast<void *>(AnnotValue));
3500 TokenList.push_back(FPTok);
3501
3502 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3503 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3504
3505 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3506 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3507}
3508
3509void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,
3510 PragmaIntroducer Introducer,
3511 Token &Tok) {
3512 Token PragmaName = Tok;
3513 if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
3514 PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
3515 << PragmaName.getIdentifierInfo()->getName();
3516 return;
3517 }
3518
3519 PP.Lex(Tok);
3520 if (Tok.isNot(tok::identifier)) {
3521 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
3522 << PragmaName.getIdentifierInfo()->getName();
3523 return;
3524 }
3526
3527 auto RM =
3528 llvm::StringSwitch<llvm::RoundingMode>(II->getName())
3529 .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero)
3530 .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven)
3531 .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive)
3532 .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative)
3533 .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway)
3534 .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic)
3535 .Default(llvm::RoundingMode::Invalid);
3536 if (RM == llvm::RoundingMode::Invalid) {
3537 PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode);
3538 return;
3539 }
3540 PP.Lex(Tok);
3541
3542 if (Tok.isNot(tok::eod)) {
3543 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3544 << "STDC FENV_ROUND";
3545 return;
3546 }
3547
3548 // Until the pragma is fully implemented, issue a warning.
3549 PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);
3550
3552 1);
3553 Toks[0] = Token::createAnnotation(
3554 tok::annot_pragma_fenv_round, Tok.getLocation(),
3555 reinterpret_cast<void *>(static_cast<uintptr_t>(RM)));
3556 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
3557 /*IsReinject=*/false);
3558}
3559
3560void Parser::HandlePragmaFP() {
3561 assert(Tok.is(tok::annot_pragma_fp));
3562 auto *AnnotValue =
3563 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
3564
3565 if (AnnotValue->ReassociateValue)
3566 Actions.ActOnPragmaFPValueChangingOption(
3567 Tok.getLocation(), PFK_Reassociate,
3568 *AnnotValue->ReassociateValue == LangOptions::FPModeKind::FPM_On);
3569
3570 if (AnnotValue->ReciprocalValue)
3571 Actions.ActOnPragmaFPValueChangingOption(
3572 Tok.getLocation(), PFK_Reciprocal,
3573 *AnnotValue->ReciprocalValue == LangOptions::FPModeKind::FPM_On);
3574
3575 if (AnnotValue->ContractValue)
3576 Actions.ActOnPragmaFPContract(Tok.getLocation(),
3577 *AnnotValue->ContractValue);
3578 if (AnnotValue->ExceptionsValue)
3579 Actions.ActOnPragmaFPExceptions(Tok.getLocation(),
3580 *AnnotValue->ExceptionsValue);
3581 if (AnnotValue->EvalMethodValue)
3582 Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(),
3583 *AnnotValue->EvalMethodValue);
3584 ConsumeAnnotationToken();
3585}
3586
3587/// Parses loop or unroll pragma hint value and fills in Info.
3588static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
3589 Token Option, bool ValueInParens,
3590 PragmaLoopHintInfo &Info) {
3592 int OpenParens = ValueInParens ? 1 : 0;
3593 // Read constant expression.
3594 while (Tok.isNot(tok::eod)) {
3595 if (Tok.is(tok::l_paren))
3596 OpenParens++;
3597 else if (Tok.is(tok::r_paren)) {
3598 OpenParens--;
3599 if (OpenParens == 0 && ValueInParens)
3600 break;
3601 }
3602
3603 ValueList.push_back(Tok);
3604 PP.Lex(Tok);
3605 }
3606
3607 if (ValueInParens) {
3608 // Read ')'
3609 if (Tok.isNot(tok::r_paren)) {
3610 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3611 return true;
3612 }
3613 PP.Lex(Tok);
3614 }
3615
3616 Token EOFTok = Token::createEof(Tok.getLocation());
3617 ValueList.push_back(EOFTok); // Terminates expression for parsing.
3618
3619 markAsReinjectedForRelexing(ValueList);
3621
3622 Info.PragmaName = PragmaName;
3623 Info.Option = Option;
3624 return false;
3625}
3626
3627/// Handle the \#pragma clang loop directive.
3628/// #pragma clang 'loop' loop-hints
3629///
3630/// loop-hints:
3631/// loop-hint loop-hints[opt]
3632///
3633/// loop-hint:
3634/// 'vectorize' '(' loop-hint-keyword ')'
3635/// 'interleave' '(' loop-hint-keyword ')'
3636/// 'unroll' '(' unroll-hint-keyword ')'
3637/// 'vectorize_predicate' '(' loop-hint-keyword ')'
3638/// 'vectorize_width' '(' loop-hint-value ')'
3639/// 'interleave_count' '(' loop-hint-value ')'
3640/// 'unroll_count' '(' loop-hint-value ')'
3641/// 'pipeline' '(' disable ')'
3642/// 'pipeline_initiation_interval' '(' loop-hint-value ')'
3643///
3644/// loop-hint-keyword:
3645/// 'enable'
3646/// 'disable'
3647/// 'assume_safety'
3648///
3649/// unroll-hint-keyword:
3650/// 'enable'
3651/// 'disable'
3652/// 'full'
3653///
3654/// loop-hint-value:
3655/// constant-expression
3656///
3657/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
3658/// try vectorizing the instructions of the loop it precedes. Specifying
3659/// interleave(enable) or interleave_count(_value_) instructs llvm to try
3660/// interleaving multiple iterations of the loop it precedes. The width of the
3661/// vector instructions is specified by vectorize_width() and the number of
3662/// interleaved loop iterations is specified by interleave_count(). Specifying a
3663/// value of 1 effectively disables vectorization/interleaving, even if it is
3664/// possible and profitable, and 0 is invalid. The loop vectorizer currently
3665/// only works on inner loops.
3666///
3667/// The unroll and unroll_count directives control the concatenation
3668/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
3669/// completely if the trip count is known at compile time and unroll partially
3670/// if the trip count is not known. Specifying unroll(full) is similar to
3671/// unroll(enable) but will unroll the loop only if the trip count is known at
3672/// compile time. Specifying unroll(disable) disables unrolling for the
3673/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
3674/// loop the number of times indicated by the value.
3675void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
3676 PragmaIntroducer Introducer,
3677 Token &Tok) {
3678 // Incoming token is "loop" from "#pragma clang loop".
3679 Token PragmaName = Tok;
3680 SmallVector<Token, 1> TokenList;
3681
3682 // Lex the optimization option and verify it is an identifier.
3683 PP.Lex(Tok);
3684 if (Tok.isNot(tok::identifier)) {
3685 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3686 << /*MissingOption=*/true << "";
3687 return;
3688 }
3689
3690 while (Tok.is(tok::identifier)) {
3691 Token Option = Tok;
3692 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3693
3694 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
3695 .Case("vectorize", true)
3696 .Case("interleave", true)
3697 .Case("unroll", true)
3698 .Case("distribute", true)
3699 .Case("vectorize_predicate", true)
3700 .Case("vectorize_width", true)
3701 .Case("interleave_count", true)
3702 .Case("unroll_count", true)
3703 .Case("pipeline", true)
3704 .Case("pipeline_initiation_interval", true)
3705 .Case("licm", true)
3706 .Default(false);
3707 if (!OptionValid) {
3708 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3709 << /*MissingOption=*/false << OptionInfo;
3710 return;
3711 }
3712 PP.Lex(Tok);
3713
3714 // Read '('
3715 if (Tok.isNot(tok::l_paren)) {
3716 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3717 return;
3718 }
3719 PP.Lex(Tok);
3720
3721 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3722 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
3723 *Info))
3724 return;
3725
3726 // Generate the loop hint token.
3727 Token LoopHintTok = Token::createAnnotation(
3728 tok::annot_pragma_loop_hint,
3729 SourceRange(Introducer.Loc, PragmaName.getLocation()),
3730 static_cast<void *>(Info));
3731 TokenList.push_back(LoopHintTok);
3732 }
3733
3734 if (Tok.isNot(tok::eod)) {
3735 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3736 << "clang loop";
3737 return;
3738 }
3739
3740 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3741 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3742
3743 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3744 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3745}
3746
3747/// Handle the loop unroll optimization pragmas.
3748/// #pragma unroll
3749/// #pragma unroll unroll-hint-value
3750/// #pragma unroll '(' unroll-hint-value ')'
3751/// #pragma nounroll
3752/// #pragma unroll_and_jam
3753/// #pragma unroll_and_jam unroll-hint-value
3754/// #pragma unroll_and_jam '(' unroll-hint-value ')'
3755/// #pragma nounroll_and_jam
3756///
3757/// unroll-hint-value:
3758/// constant-expression
3759///
3760/// Loop unrolling hints can be specified with '#pragma unroll' or
3761/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
3762/// contained in parentheses. With no argument the directive instructs llvm to
3763/// try to unroll the loop completely. A positive integer argument can be
3764/// specified to indicate the number of times the loop should be unrolled. To
3765/// maximize compatibility with other compilers the unroll count argument can be
3766/// specified with or without parentheses. Specifying, '#pragma nounroll'
3767/// disables unrolling of the loop.
3768void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
3769 PragmaIntroducer Introducer,
3770 Token &Tok) {
3771 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
3772 // "#pragma nounroll".
3773 Token PragmaName = Tok;
3774 PP.Lex(Tok);
3775 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3776 if (Tok.is(tok::eod)) {
3777 // nounroll or unroll pragma without an argument.
3778 Info->PragmaName = PragmaName;
3779 Info->Option.startToken();
3780 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
3781 PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
3782 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3783 << PragmaName.getIdentifierInfo()->getName();
3784 return;
3785 } else {
3786 // Unroll pragma with an argument: "#pragma unroll N" or
3787 // "#pragma unroll(N)".
3788 // Read '(' if it exists.
3789 bool ValueInParens = Tok.is(tok::l_paren);
3790 if (ValueInParens)
3791 PP.Lex(Tok);
3792
3793 Token Option;
3794 Option.startToken();
3795 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
3796 return;
3797
3798 // In CUDA, the argument to '#pragma unroll' should not be contained in
3799 // parentheses.
3800 if (PP.getLangOpts().CUDA && ValueInParens)
3801 PP.Diag(Info->Toks[0].getLocation(),
3802 diag::warn_pragma_unroll_cuda_value_in_parens);
3803
3804 if (Tok.isNot(tok::eod)) {
3805 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3806 << "unroll";
3807 return;
3808 }
3809 }
3810
3811 // Generate the hint token.
3812 auto TokenArray = std::make_unique<Token[]>(1);
3813 TokenArray[0] = Token::createAnnotation(
3814 tok::annot_pragma_loop_hint,
3815 SourceRange(Introducer.Loc, PragmaName.getLocation()),
3816 static_cast<void *>(Info));
3817 PP.EnterTokenStream(std::move(TokenArray), 1,
3818 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3819}
3820
3821bool Parser::HandlePragmaMSFunction(StringRef PragmaName,
3822 SourceLocation PragmaLocation) {
3823 Token FirstTok = Tok;
3824
3825 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3826 PragmaName))
3827 return false;
3828
3829 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3830
3831 llvm::SmallVector<StringRef> NoBuiltins;
3832 while (Tok.is(tok::identifier)) {
3833 IdentifierInfo *II = Tok.getIdentifierInfo();
3834 if (!II->getBuiltinID())
3835 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3836 << II << SuggestIntrinH;
3837 else
3838 NoBuiltins.emplace_back(II->getName());
3839
3840 PP.Lex(Tok);
3841 if (Tok.isNot(tok::comma))
3842 break;
3843 PP.Lex(Tok); // ,
3844 }
3845
3846 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3847 PragmaName) ||
3848 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3849 PragmaName))
3850 return false;
3851
3852 Actions.ActOnPragmaMSFunction(FirstTok.getLocation(), NoBuiltins);
3853 return true;
3854}
3855
3856bool Parser::HandlePragmaMSOptimize(StringRef PragmaName,
3857 SourceLocation PragmaLocation) {
3858 Token FirstTok = Tok;
3859 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3860 PragmaName))
3861 return false;
3862
3863 if (Tok.isNot(tok::string_literal)) {
3864 PP.Diag(PragmaLocation, diag::warn_pragma_expected_string) << PragmaName;
3865 return false;
3866 }
3868 if (StringResult.isInvalid())
3869 return false; // Already diagnosed.
3870 StringLiteral *OptimizationList = cast<StringLiteral>(StringResult.get());
3871 if (OptimizationList->getCharByteWidth() != 1) {
3872 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
3873 << PragmaName;
3874 return false;
3875 }
3876
3877 if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
3878 PragmaName))
3879 return false;
3880
3881 if (Tok.is(tok::eof) || Tok.is(tok::r_paren)) {
3882 PP.Diag(PragmaLocation, diag::warn_pragma_missing_argument)
3883 << PragmaName << /*Expected=*/true << "'on' or 'off'";
3884 return false;
3885 }
3886 IdentifierInfo *II = Tok.getIdentifierInfo();
3887 if (!II || (!II->isStr("on") && !II->isStr("off"))) {
3888 PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
3889 << PP.getSpelling(Tok) << PragmaName << /*Expected=*/true
3890 << "'on' or 'off'";
3891 return false;
3892 }
3893 bool IsOn = II->isStr("on");
3894 PP.Lex(Tok);
3895
3896 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3897 PragmaName))
3898 return false;
3899
3900 // TODO: Add support for "sgty"
3901 if (!OptimizationList->getString().empty()) {
3902 PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
3903 << OptimizationList->getString() << PragmaName << /*Expected=*/true
3904 << "\"\"";
3905 return false;
3906 }
3907
3908 if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3909 PragmaName))
3910 return false;
3911
3912 Actions.ActOnPragmaMSOptimize(FirstTok.getLocation(), IsOn);
3913 return true;
3914}
3915
3916/// Handle the Microsoft \#pragma intrinsic extension.
3917///
3918/// The syntax is:
3919/// \code
3920/// #pragma intrinsic(memset)
3921/// #pragma intrinsic(strlen, memcpy)
3922/// \endcode
3923///
3924/// Pragma intrisic tells the compiler to use a builtin version of the
3925/// function. Clang does it anyway, so the pragma doesn't really do anything.
3926/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3927/// isn't an intrinsic in clang and suggest to include intrin.h, as well as
3928/// declare the builtin if it has not been declared.
3929bool Parser::HandlePragmaMSIntrinsic(StringRef PragmaName,
3930 SourceLocation PragmaLocation) {
3931 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3932 PragmaName))
3933 return false;
3934
3935 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3936
3937 while (Tok.is(tok::identifier)) {
3938 IdentifierInfo *II = Tok.getIdentifierInfo();
3939 if (!II->getBuiltinID())
3940 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3941 << II << SuggestIntrinH;
3942 // If the builtin hasn't already been declared, declare it now.
3943 DeclarationNameInfo NameInfo(II, Tok.getLocation());
3944 LookupResult Previous(Actions, NameInfo, Sema::LookupOrdinaryName,
3946 Actions.LookupName(Previous, Actions.getCurScope(),
3947 /*CreateBuiltins*/ false);
3948 if (Previous.empty())
3949 Actions.LazilyCreateBuiltin(II, II->getBuiltinID(), Actions.getCurScope(),
3950 /*ForRedeclaration*/ true, Tok.getLocation());
3951 PP.Lex(Tok);
3952 if (Tok.isNot(tok::comma))
3953 break;
3954 PP.Lex(Tok);
3955 }
3956 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3957 PragmaName))
3958 return false;
3959
3960 if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3961 PragmaName))
3962 return false;
3963 return true;
3964}
3965
3966void PragmaForceCUDAHostDeviceHandler::HandlePragma(
3967 Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
3968 Token FirstTok = Tok;
3969
3970 PP.Lex(Tok);
3972 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
3973 PP.Diag(FirstTok.getLocation(),
3974 diag::warn_pragma_force_cuda_host_device_bad_arg);
3975 return;
3976 }
3977
3978 if (Info->isStr("begin"))
3979 Actions.CUDA().PushForceHostDevice();
3980 else if (!Actions.CUDA().PopForceHostDevice())
3981 PP.Diag(FirstTok.getLocation(),
3982 diag::err_pragma_cannot_end_force_cuda_host_device);
3983
3984 PP.Lex(Tok);
3985 if (!Tok.is(tok::eod))
3986 PP.Diag(FirstTok.getLocation(),
3987 diag::warn_pragma_force_cuda_host_device_bad_arg);
3988}
3989
3990/// Handle the #pragma clang attribute directive.
3991///
3992/// The syntax is:
3993/// \code
3994/// #pragma clang attribute push (attribute, subject-set)
3995/// #pragma clang attribute push
3996/// #pragma clang attribute (attribute, subject-set)
3997/// #pragma clang attribute pop
3998/// \endcode
3999///
4000/// There are also 'namespace' variants of push and pop directives. The bare
4001/// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
4002/// namespace, since it always applies attributes to the most recently pushed
4003/// group, regardless of namespace.
4004/// \code
4005/// #pragma clang attribute namespace.push (attribute, subject-set)
4006/// #pragma clang attribute namespace.push
4007/// #pragma clang attribute namespace.pop
4008/// \endcode
4009///
4010/// The subject-set clause defines the set of declarations which receive the
4011/// attribute. Its exact syntax is described in the LanguageExtensions document
4012/// in Clang's documentation.
4013///
4014/// This directive instructs the compiler to begin/finish applying the specified
4015/// attribute to the set of attribute-specific declarations in the active range
4016/// of the pragma.
4017void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
4018 PragmaIntroducer Introducer,
4019 Token &FirstToken) {
4020 Token Tok;
4021 PP.Lex(Tok);
4022 auto *Info = new (PP.getPreprocessorAllocator())
4023 PragmaAttributeInfo(AttributesForPragmaAttribute);
4024
4025 // Parse the optional namespace followed by a period.
4026 if (Tok.is(tok::identifier)) {
4028 if (!II->isStr("push") && !II->isStr("pop")) {
4029 Info->Namespace = II;
4030 PP.Lex(Tok);
4031
4032 if (!Tok.is(tok::period)) {
4033 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
4034 << II;
4035 return;
4036 }
4037 PP.Lex(Tok);
4038 }
4039 }
4040
4041 if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
4042 PP.Diag(Tok.getLocation(),
4043 diag::err_pragma_attribute_expected_push_pop_paren);
4044 return;
4045 }
4046
4047 // Determine what action this pragma clang attribute represents.
4048 if (Tok.is(tok::l_paren)) {
4049 if (Info->Namespace) {
4050 PP.Diag(Tok.getLocation(),
4051 diag::err_pragma_attribute_namespace_on_attribute);
4052 PP.Diag(Tok.getLocation(),
4053 diag::note_pragma_attribute_namespace_on_attribute);
4054 return;
4055 }
4056 Info->Action = PragmaAttributeInfo::Attribute;
4057 } else {
4058 const IdentifierInfo *II = Tok.getIdentifierInfo();
4059 if (II->isStr("push"))
4060 Info->Action = PragmaAttributeInfo::Push;
4061 else if (II->isStr("pop"))
4062 Info->Action = PragmaAttributeInfo::Pop;
4063 else {
4064 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
4065 << PP.getSpelling(Tok);
4066 return;
4067 }
4068
4069 PP.Lex(Tok);
4070 }
4071
4072 // Parse the actual attribute.
4073 if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
4074 Info->Action == PragmaAttributeInfo::Attribute) {
4075 if (Tok.isNot(tok::l_paren)) {
4076 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
4077 return;
4078 }
4079 PP.Lex(Tok);
4080
4081 // Lex the attribute tokens.
4082 SmallVector<Token, 16> AttributeTokens;
4083 int OpenParens = 1;
4084 while (Tok.isNot(tok::eod)) {
4085 if (Tok.is(tok::l_paren))
4086 OpenParens++;
4087 else if (Tok.is(tok::r_paren)) {
4088 OpenParens--;
4089 if (OpenParens == 0)
4090 break;
4091 }
4092
4093 AttributeTokens.push_back(Tok);
4094 PP.Lex(Tok);
4095 }
4096
4097 if (AttributeTokens.empty()) {
4098 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
4099 return;
4100 }
4101 if (Tok.isNot(tok::r_paren)) {
4102 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
4103 return;
4104 }
4105 SourceLocation EndLoc = Tok.getLocation();
4106 PP.Lex(Tok);
4107
4108 // Terminate the attribute for parsing.
4109 Token EOFTok = Token::createEof(EndLoc);
4110 AttributeTokens.push_back(EOFTok);
4111
4112 markAsReinjectedForRelexing(AttributeTokens);
4113 Info->Tokens =
4114 llvm::ArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
4115 }
4116
4117 if (Tok.isNot(tok::eod))
4118 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4119 << "clang attribute";
4120
4121 // Generate the annotated pragma token.
4122 auto TokenArray = std::make_unique<Token[]>(1);
4123 TokenArray[0] = Token::createAnnotation(tok::annot_pragma_attribute,
4124 FirstToken.getLocation(),
4125 static_cast<void *>(Info));
4126 PP.EnterTokenStream(std::move(TokenArray), 1,
4127 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
4128}
4129
4130// Handle '#pragma clang max_tokens 12345'.
4131void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
4132 PragmaIntroducer Introducer,
4133 Token &Tok) {
4134 PP.Lex(Tok);
4135 if (Tok.is(tok::eod)) {
4136 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
4137 << "clang max_tokens_here" << /*Expected=*/true << "integer";
4138 return;
4139 }
4140
4142 uint64_t MaxTokens;
4143 if (Tok.isNot(tok::numeric_constant) ||
4144 !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
4145 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
4146 << "clang max_tokens_here";
4147 return;
4148 }
4149
4150 if (Tok.isNot(tok::eod)) {
4151 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4152 << "clang max_tokens_here";
4153 return;
4154 }
4155
4156 if (PP.getTokenCount() > MaxTokens) {
4157 PP.Diag(Loc, diag::warn_max_tokens)
4158 << PP.getTokenCount() << (unsigned)MaxTokens;
4159 }
4160}
4161
4162// Handle '#pragma clang max_tokens_total 12345'.
4163void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
4164 PragmaIntroducer Introducer,
4165 Token &Tok) {
4166 PP.Lex(Tok);
4167 if (Tok.is(tok::eod)) {
4168 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
4169 << "clang max_tokens_total" << /*Expected=*/true << "integer";
4170 return;
4171 }
4172
4174 uint64_t MaxTokens;
4175 if (Tok.isNot(tok::numeric_constant) ||
4176 !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
4177 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
4178 << "clang max_tokens_total";
4179 return;
4180 }
4181
4182 if (Tok.isNot(tok::eod)) {
4183 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4184 << "clang max_tokens_total";
4185 return;
4186 }
4187
4188 PP.overrideMaxTokens(MaxTokens, Loc);
4189}
4190
4192 tok::TokenKind TokKind) {
4193 Token AnnotTok = Token::createAnnotation(TokKind, Tok.getLocation());
4194 SmallVector<Token, 8> TokenVector;
4195 // Suck up all of the tokens before the eod.
4196 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
4197 TokenVector.push_back(Tok);
4198 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
4199 }
4200 // Add a sentinel EoF token to the end of the list.
4201 Token EoF = Token::createEof(Tok.getLocation());
4202 TokenVector.push_back(EoF);
4203 // We must allocate this array with new because EnterTokenStream is going to
4204 // delete it later.
4205 markAsReinjectedForRelexing(TokenVector);
4206 auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
4207 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
4208 auto Value = new (PP.getPreprocessorAllocator())
4209 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
4210 TokenVector.size());
4211 AnnotTok.setAnnotationValue(Value);
4212 PP.EnterToken(AnnotTok, /*IsReinject*/ false);
4213}
4214
4215/// Handle #pragma export.
4216void PragmaExportHandler::HandlePragma(Preprocessor &PP,
4217 PragmaIntroducer Introducer,
4218 Token &FirstToken) {
4219 zOSPragmaHandlerHelper(PP, FirstToken, tok::annot_pragma_export);
4220}
4221
4222// Handle '#pragma clang riscv intrinsic vector'.
4223// '#pragma clang riscv intrinsic sifive_vector'.
4224// '#pragma clang riscv intrinsic andes_vector'.
4225void PragmaRISCVHandler::HandlePragma(Preprocessor &PP,
4226 PragmaIntroducer Introducer,
4227 Token &FirstToken) {
4228 Token Tok;
4229 PP.Lex(Tok);
4231
4232 if (!II || !II->isStr("intrinsic")) {
4233 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
4234 << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'intrinsic'";
4235 return;
4236 }
4237
4238 PP.Lex(Tok);
4239 II = Tok.getIdentifierInfo();
4240 if (!II || !(II->isStr("vector") || II->isStr("sifive_vector") ||
4241 II->isStr("andes_vector"))) {
4242 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
4243 << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true
4244 << "'vector', 'sifive_vector' or 'andes_vector'";
4245 return;
4246 }
4247
4248 PP.Lex(Tok);
4249 if (Tok.isNot(tok::eod)) {
4250 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4251 << "clang riscv intrinsic";
4252 return;
4253 }
4254
4255 if (II->isStr("vector"))
4256 Actions.RISCV().DeclareRVVBuiltins = true;
4257 else if (II->isStr("sifive_vector"))
4258 Actions.RISCV().DeclareSiFiveVectorBuiltins = true;
4259 else if (II->isStr("andes_vector"))
4260 Actions.RISCV().DeclareAndesVectorBuiltins = true;
4261}
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:950
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:991
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:1857
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:863
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9504
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6856
PragmaMsStackAction
Definition Sema.h:1879
@ PSK_Push_Set
Definition Sema.h:1885
@ PSK_Reset
Definition Sema.h:1880
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:1560
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:472
@ 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
unsigned long uint64_t
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
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:1890