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