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