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