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