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