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