1 //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the language specific #pragma handlers.
11 //===----------------------------------------------------------------------===//
13 #include "clang/AST/ASTContext.h"
14 #include "clang/Basic/PragmaKinds.h"
15 #include "clang/Basic/TargetInfo.h"
16 #include "clang/Lex/Preprocessor.h"
17 #include "clang/Lex/Token.h"
18 #include "clang/Parse/LoopHint.h"
19 #include "clang/Parse/ParseDiagnostic.h"
20 #include "clang/Parse/Parser.h"
21 #include "clang/Parse/RAIIObjectsForParser.h"
22 #include "clang/Sema/EnterExpressionEvaluationContext.h"
23 #include "clang/Sema/Scope.h"
24 #include "llvm/ADT/ArrayRef.h"
25 #include "llvm/ADT/StringSwitch.h"
27 using namespace clang
;
31 struct PragmaAlignHandler
: public PragmaHandler
{
32 explicit PragmaAlignHandler() : PragmaHandler("align") {}
33 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
34 Token
&FirstToken
) override
;
37 struct PragmaGCCVisibilityHandler
: public PragmaHandler
{
38 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
39 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
40 Token
&FirstToken
) override
;
43 struct PragmaOptionsHandler
: public PragmaHandler
{
44 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
45 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
46 Token
&FirstToken
) override
;
49 struct PragmaPackHandler
: public PragmaHandler
{
50 explicit PragmaPackHandler() : PragmaHandler("pack") {}
51 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
52 Token
&FirstToken
) override
;
55 struct PragmaClangSectionHandler
: public PragmaHandler
{
56 explicit PragmaClangSectionHandler(Sema
&S
)
57 : PragmaHandler("section"), Actions(S
) {}
58 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
59 Token
&FirstToken
) override
;
65 struct PragmaMSStructHandler
: public PragmaHandler
{
66 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
67 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
68 Token
&FirstToken
) override
;
71 struct PragmaUnusedHandler
: public PragmaHandler
{
72 PragmaUnusedHandler() : PragmaHandler("unused") {}
73 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
74 Token
&FirstToken
) override
;
77 struct PragmaWeakHandler
: public PragmaHandler
{
78 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
79 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
80 Token
&FirstToken
) override
;
83 struct PragmaRedefineExtnameHandler
: public PragmaHandler
{
84 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
85 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
86 Token
&FirstToken
) override
;
89 struct PragmaOpenCLExtensionHandler
: public PragmaHandler
{
90 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
91 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
92 Token
&FirstToken
) override
;
96 struct PragmaFPContractHandler
: public PragmaHandler
{
97 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
98 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
99 Token
&FirstToken
) override
;
102 // Pragma STDC implementations.
104 /// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
105 struct PragmaSTDC_FENV_ACCESSHandler
: public PragmaHandler
{
106 PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
108 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
109 Token
&Tok
) override
{
110 Token PragmaName
= Tok
;
111 if (!PP
.getTargetInfo().hasStrictFP() && !PP
.getLangOpts().ExpStrictFP
) {
112 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_fp_ignored
)
113 << PragmaName
.getIdentifierInfo()->getName();
116 tok::OnOffSwitch OOS
;
117 if (PP
.LexOnOffSwitch(OOS
))
120 MutableArrayRef
<Token
> Toks(PP
.getPreprocessorAllocator().Allocate
<Token
>(1),
122 Toks
[0].startToken();
123 Toks
[0].setKind(tok::annot_pragma_fenv_access
);
124 Toks
[0].setLocation(Tok
.getLocation());
125 Toks
[0].setAnnotationEndLoc(Tok
.getLocation());
126 Toks
[0].setAnnotationValue(reinterpret_cast<void*>(
127 static_cast<uintptr_t>(OOS
)));
128 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
129 /*IsReinject=*/false);
133 /// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
134 struct PragmaSTDC_CX_LIMITED_RANGEHandler
: public PragmaHandler
{
135 PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
137 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
138 Token
&Tok
) override
{
139 tok::OnOffSwitch OOS
;
140 PP
.LexOnOffSwitch(OOS
);
144 /// Handler for "\#pragma STDC FENV_ROUND ...".
145 struct PragmaSTDC_FENV_ROUNDHandler
: public PragmaHandler
{
146 PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {}
148 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
149 Token
&Tok
) override
;
152 /// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
153 struct PragmaSTDC_UnknownHandler
: public PragmaHandler
{
154 PragmaSTDC_UnknownHandler() = default;
156 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
157 Token
&UnknownTok
) override
{
158 // C99 6.10.6p2, unknown forms are not allowed.
159 PP
.Diag(UnknownTok
, diag::ext_stdc_pragma_ignored
);
163 struct PragmaFPHandler
: public PragmaHandler
{
164 PragmaFPHandler() : PragmaHandler("fp") {}
165 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
166 Token
&FirstToken
) override
;
169 struct PragmaNoOpenMPHandler
: public PragmaHandler
{
170 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
171 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
172 Token
&FirstToken
) override
;
175 struct PragmaOpenMPHandler
: public PragmaHandler
{
176 PragmaOpenMPHandler() : PragmaHandler("omp") { }
177 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
178 Token
&FirstToken
) override
;
181 /// PragmaCommentHandler - "\#pragma comment ...".
182 struct PragmaCommentHandler
: public PragmaHandler
{
183 PragmaCommentHandler(Sema
&Actions
)
184 : PragmaHandler("comment"), Actions(Actions
) {}
185 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
186 Token
&FirstToken
) override
;
192 struct PragmaDetectMismatchHandler
: public PragmaHandler
{
193 PragmaDetectMismatchHandler(Sema
&Actions
)
194 : PragmaHandler("detect_mismatch"), Actions(Actions
) {}
195 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
196 Token
&FirstToken
) override
;
202 struct PragmaFloatControlHandler
: public PragmaHandler
{
203 PragmaFloatControlHandler(Sema
&Actions
)
204 : PragmaHandler("float_control") {}
205 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
206 Token
&FirstToken
) override
;
209 struct PragmaMSPointersToMembers
: public PragmaHandler
{
210 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
211 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
212 Token
&FirstToken
) override
;
215 struct PragmaMSVtorDisp
: public PragmaHandler
{
216 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
217 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
218 Token
&FirstToken
) override
;
221 struct PragmaMSPragma
: public PragmaHandler
{
222 explicit PragmaMSPragma(const char *name
) : PragmaHandler(name
) {}
223 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
224 Token
&FirstToken
) override
;
227 /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
228 struct PragmaOptimizeHandler
: public PragmaHandler
{
229 PragmaOptimizeHandler(Sema
&S
)
230 : PragmaHandler("optimize"), Actions(S
) {}
231 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
232 Token
&FirstToken
) override
;
238 struct PragmaLoopHintHandler
: public PragmaHandler
{
239 PragmaLoopHintHandler() : PragmaHandler("loop") {}
240 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
241 Token
&FirstToken
) override
;
244 struct PragmaUnrollHintHandler
: public PragmaHandler
{
245 PragmaUnrollHintHandler(const char *name
) : PragmaHandler(name
) {}
246 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
247 Token
&FirstToken
) override
;
250 struct PragmaMSRuntimeChecksHandler
: public EmptyPragmaHandler
{
251 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
254 struct PragmaMSIntrinsicHandler
: public PragmaHandler
{
255 PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
256 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
257 Token
&FirstToken
) override
;
260 // "\#pragma fenv_access (on)".
261 struct PragmaMSFenvAccessHandler
: public PragmaHandler
{
262 PragmaMSFenvAccessHandler() : PragmaHandler("fenv_access") {}
263 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
264 Token
&FirstToken
) override
{
265 StringRef PragmaName
= FirstToken
.getIdentifierInfo()->getName();
266 if (!PP
.getTargetInfo().hasStrictFP() && !PP
.getLangOpts().ExpStrictFP
) {
267 PP
.Diag(FirstToken
.getLocation(), diag::warn_pragma_fp_ignored
)
274 if (Tok
.isNot(tok::l_paren
)) {
275 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_lparen
)
279 PP
.Lex(Tok
); // Consume the l_paren.
280 if (Tok
.isNot(tok::identifier
)) {
281 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_ms_fenv_access
);
284 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
285 tok::OnOffSwitch OOS
;
286 if (II
->isStr("on")) {
289 } else if (II
->isStr("off")) {
293 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_ms_fenv_access
);
296 if (Tok
.isNot(tok::r_paren
)) {
297 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_rparen
)
301 PP
.Lex(Tok
); // Consume the r_paren.
303 if (Tok
.isNot(tok::eod
)) {
304 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
309 MutableArrayRef
<Token
> Toks(
310 PP
.getPreprocessorAllocator().Allocate
<Token
>(1), 1);
311 Toks
[0].startToken();
312 Toks
[0].setKind(tok::annot_pragma_fenv_access_ms
);
313 Toks
[0].setLocation(FirstToken
.getLocation());
314 Toks
[0].setAnnotationEndLoc(Tok
.getLocation());
315 Toks
[0].setAnnotationValue(
316 reinterpret_cast<void*>(static_cast<uintptr_t>(OOS
)));
317 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
318 /*IsReinject=*/false);
322 struct PragmaForceCUDAHostDeviceHandler
: public PragmaHandler
{
323 PragmaForceCUDAHostDeviceHandler(Sema
&Actions
)
324 : PragmaHandler("force_cuda_host_device"), Actions(Actions
) {}
325 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
326 Token
&FirstToken
) override
;
332 /// PragmaAttributeHandler - "\#pragma clang attribute ...".
333 struct PragmaAttributeHandler
: public PragmaHandler
{
334 PragmaAttributeHandler(AttributeFactory
&AttrFactory
)
335 : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory
) {}
336 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
337 Token
&FirstToken
) override
;
339 /// A pool of attributes that were parsed in \#pragma clang attribute.
340 ParsedAttributes AttributesForPragmaAttribute
;
343 struct PragmaMaxTokensHereHandler
: public PragmaHandler
{
344 PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
345 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
346 Token
&FirstToken
) override
;
349 struct PragmaMaxTokensTotalHandler
: public PragmaHandler
{
350 PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
351 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
352 Token
&FirstToken
) override
;
355 struct PragmaRISCVHandler
: public PragmaHandler
{
356 PragmaRISCVHandler(Sema
&Actions
)
357 : PragmaHandler("riscv"), Actions(Actions
) {}
358 void HandlePragma(Preprocessor
&PP
, PragmaIntroducer Introducer
,
359 Token
&FirstToken
) override
;
365 void markAsReinjectedForRelexing(llvm::MutableArrayRef
<clang::Token
> Toks
) {
367 T
.setFlag(clang::Token::IsReinjected
);
371 void Parser::initializePragmaHandlers() {
372 AlignHandler
= std::make_unique
<PragmaAlignHandler
>();
373 PP
.AddPragmaHandler(AlignHandler
.get());
375 GCCVisibilityHandler
= std::make_unique
<PragmaGCCVisibilityHandler
>();
376 PP
.AddPragmaHandler("GCC", GCCVisibilityHandler
.get());
378 OptionsHandler
= std::make_unique
<PragmaOptionsHandler
>();
379 PP
.AddPragmaHandler(OptionsHandler
.get());
381 PackHandler
= std::make_unique
<PragmaPackHandler
>();
382 PP
.AddPragmaHandler(PackHandler
.get());
384 MSStructHandler
= std::make_unique
<PragmaMSStructHandler
>();
385 PP
.AddPragmaHandler(MSStructHandler
.get());
387 UnusedHandler
= std::make_unique
<PragmaUnusedHandler
>();
388 PP
.AddPragmaHandler(UnusedHandler
.get());
390 WeakHandler
= std::make_unique
<PragmaWeakHandler
>();
391 PP
.AddPragmaHandler(WeakHandler
.get());
393 RedefineExtnameHandler
= std::make_unique
<PragmaRedefineExtnameHandler
>();
394 PP
.AddPragmaHandler(RedefineExtnameHandler
.get());
396 FPContractHandler
= std::make_unique
<PragmaFPContractHandler
>();
397 PP
.AddPragmaHandler("STDC", FPContractHandler
.get());
399 STDCFenvAccessHandler
= std::make_unique
<PragmaSTDC_FENV_ACCESSHandler
>();
400 PP
.AddPragmaHandler("STDC", STDCFenvAccessHandler
.get());
402 STDCFenvRoundHandler
= std::make_unique
<PragmaSTDC_FENV_ROUNDHandler
>();
403 PP
.AddPragmaHandler("STDC", STDCFenvRoundHandler
.get());
405 STDCCXLIMITHandler
= std::make_unique
<PragmaSTDC_CX_LIMITED_RANGEHandler
>();
406 PP
.AddPragmaHandler("STDC", STDCCXLIMITHandler
.get());
408 STDCUnknownHandler
= std::make_unique
<PragmaSTDC_UnknownHandler
>();
409 PP
.AddPragmaHandler("STDC", STDCUnknownHandler
.get());
411 PCSectionHandler
= std::make_unique
<PragmaClangSectionHandler
>(Actions
);
412 PP
.AddPragmaHandler("clang", PCSectionHandler
.get());
414 if (getLangOpts().OpenCL
) {
415 OpenCLExtensionHandler
= std::make_unique
<PragmaOpenCLExtensionHandler
>();
416 PP
.AddPragmaHandler("OPENCL", OpenCLExtensionHandler
.get());
418 PP
.AddPragmaHandler("OPENCL", FPContractHandler
.get());
420 if (getLangOpts().OpenMP
)
421 OpenMPHandler
= std::make_unique
<PragmaOpenMPHandler
>();
423 OpenMPHandler
= std::make_unique
<PragmaNoOpenMPHandler
>();
424 PP
.AddPragmaHandler(OpenMPHandler
.get());
426 if (getLangOpts().MicrosoftExt
||
427 getTargetInfo().getTriple().isOSBinFormatELF()) {
428 MSCommentHandler
= std::make_unique
<PragmaCommentHandler
>(Actions
);
429 PP
.AddPragmaHandler(MSCommentHandler
.get());
432 FloatControlHandler
= std::make_unique
<PragmaFloatControlHandler
>(Actions
);
433 PP
.AddPragmaHandler(FloatControlHandler
.get());
434 if (getLangOpts().MicrosoftExt
) {
435 MSDetectMismatchHandler
=
436 std::make_unique
<PragmaDetectMismatchHandler
>(Actions
);
437 PP
.AddPragmaHandler(MSDetectMismatchHandler
.get());
438 MSPointersToMembers
= std::make_unique
<PragmaMSPointersToMembers
>();
439 PP
.AddPragmaHandler(MSPointersToMembers
.get());
440 MSVtorDisp
= std::make_unique
<PragmaMSVtorDisp
>();
441 PP
.AddPragmaHandler(MSVtorDisp
.get());
442 MSInitSeg
= std::make_unique
<PragmaMSPragma
>("init_seg");
443 PP
.AddPragmaHandler(MSInitSeg
.get());
444 MSDataSeg
= std::make_unique
<PragmaMSPragma
>("data_seg");
445 PP
.AddPragmaHandler(MSDataSeg
.get());
446 MSBSSSeg
= std::make_unique
<PragmaMSPragma
>("bss_seg");
447 PP
.AddPragmaHandler(MSBSSSeg
.get());
448 MSConstSeg
= std::make_unique
<PragmaMSPragma
>("const_seg");
449 PP
.AddPragmaHandler(MSConstSeg
.get());
450 MSCodeSeg
= std::make_unique
<PragmaMSPragma
>("code_seg");
451 PP
.AddPragmaHandler(MSCodeSeg
.get());
452 MSSection
= std::make_unique
<PragmaMSPragma
>("section");
453 PP
.AddPragmaHandler(MSSection
.get());
454 MSStrictGuardStackCheck
=
455 std::make_unique
<PragmaMSPragma
>("strict_gs_check");
456 PP
.AddPragmaHandler(MSStrictGuardStackCheck
.get());
457 MSFunction
= std::make_unique
<PragmaMSPragma
>("function");
458 PP
.AddPragmaHandler(MSFunction
.get());
459 MSAllocText
= std::make_unique
<PragmaMSPragma
>("alloc_text");
460 PP
.AddPragmaHandler(MSAllocText
.get());
461 MSOptimize
= std::make_unique
<PragmaMSPragma
>("optimize");
462 PP
.AddPragmaHandler(MSOptimize
.get());
463 MSRuntimeChecks
= std::make_unique
<PragmaMSRuntimeChecksHandler
>();
464 PP
.AddPragmaHandler(MSRuntimeChecks
.get());
465 MSIntrinsic
= std::make_unique
<PragmaMSIntrinsicHandler
>();
466 PP
.AddPragmaHandler(MSIntrinsic
.get());
467 MSFenvAccess
= std::make_unique
<PragmaMSFenvAccessHandler
>();
468 PP
.AddPragmaHandler(MSFenvAccess
.get());
471 if (getLangOpts().CUDA
) {
472 CUDAForceHostDeviceHandler
=
473 std::make_unique
<PragmaForceCUDAHostDeviceHandler
>(Actions
);
474 PP
.AddPragmaHandler("clang", CUDAForceHostDeviceHandler
.get());
477 OptimizeHandler
= std::make_unique
<PragmaOptimizeHandler
>(Actions
);
478 PP
.AddPragmaHandler("clang", OptimizeHandler
.get());
480 LoopHintHandler
= std::make_unique
<PragmaLoopHintHandler
>();
481 PP
.AddPragmaHandler("clang", LoopHintHandler
.get());
483 UnrollHintHandler
= std::make_unique
<PragmaUnrollHintHandler
>("unroll");
484 PP
.AddPragmaHandler(UnrollHintHandler
.get());
485 PP
.AddPragmaHandler("GCC", UnrollHintHandler
.get());
487 NoUnrollHintHandler
= std::make_unique
<PragmaUnrollHintHandler
>("nounroll");
488 PP
.AddPragmaHandler(NoUnrollHintHandler
.get());
489 PP
.AddPragmaHandler("GCC", NoUnrollHintHandler
.get());
491 UnrollAndJamHintHandler
=
492 std::make_unique
<PragmaUnrollHintHandler
>("unroll_and_jam");
493 PP
.AddPragmaHandler(UnrollAndJamHintHandler
.get());
495 NoUnrollAndJamHintHandler
=
496 std::make_unique
<PragmaUnrollHintHandler
>("nounroll_and_jam");
497 PP
.AddPragmaHandler(NoUnrollAndJamHintHandler
.get());
499 FPHandler
= std::make_unique
<PragmaFPHandler
>();
500 PP
.AddPragmaHandler("clang", FPHandler
.get());
502 AttributePragmaHandler
=
503 std::make_unique
<PragmaAttributeHandler
>(AttrFactory
);
504 PP
.AddPragmaHandler("clang", AttributePragmaHandler
.get());
506 MaxTokensHerePragmaHandler
= std::make_unique
<PragmaMaxTokensHereHandler
>();
507 PP
.AddPragmaHandler("clang", MaxTokensHerePragmaHandler
.get());
509 MaxTokensTotalPragmaHandler
= std::make_unique
<PragmaMaxTokensTotalHandler
>();
510 PP
.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler
.get());
512 if (getTargetInfo().getTriple().isRISCV()) {
513 RISCVPragmaHandler
= std::make_unique
<PragmaRISCVHandler
>(Actions
);
514 PP
.AddPragmaHandler("clang", RISCVPragmaHandler
.get());
518 void Parser::resetPragmaHandlers() {
519 // Remove the pragma handlers we installed.
520 PP
.RemovePragmaHandler(AlignHandler
.get());
521 AlignHandler
.reset();
522 PP
.RemovePragmaHandler("GCC", GCCVisibilityHandler
.get());
523 GCCVisibilityHandler
.reset();
524 PP
.RemovePragmaHandler(OptionsHandler
.get());
525 OptionsHandler
.reset();
526 PP
.RemovePragmaHandler(PackHandler
.get());
528 PP
.RemovePragmaHandler(MSStructHandler
.get());
529 MSStructHandler
.reset();
530 PP
.RemovePragmaHandler(UnusedHandler
.get());
531 UnusedHandler
.reset();
532 PP
.RemovePragmaHandler(WeakHandler
.get());
534 PP
.RemovePragmaHandler(RedefineExtnameHandler
.get());
535 RedefineExtnameHandler
.reset();
537 if (getLangOpts().OpenCL
) {
538 PP
.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler
.get());
539 OpenCLExtensionHandler
.reset();
540 PP
.RemovePragmaHandler("OPENCL", FPContractHandler
.get());
542 PP
.RemovePragmaHandler(OpenMPHandler
.get());
543 OpenMPHandler
.reset();
545 if (getLangOpts().MicrosoftExt
||
546 getTargetInfo().getTriple().isOSBinFormatELF()) {
547 PP
.RemovePragmaHandler(MSCommentHandler
.get());
548 MSCommentHandler
.reset();
551 PP
.RemovePragmaHandler("clang", PCSectionHandler
.get());
552 PCSectionHandler
.reset();
554 PP
.RemovePragmaHandler(FloatControlHandler
.get());
555 FloatControlHandler
.reset();
556 if (getLangOpts().MicrosoftExt
) {
557 PP
.RemovePragmaHandler(MSDetectMismatchHandler
.get());
558 MSDetectMismatchHandler
.reset();
559 PP
.RemovePragmaHandler(MSPointersToMembers
.get());
560 MSPointersToMembers
.reset();
561 PP
.RemovePragmaHandler(MSVtorDisp
.get());
563 PP
.RemovePragmaHandler(MSInitSeg
.get());
565 PP
.RemovePragmaHandler(MSDataSeg
.get());
567 PP
.RemovePragmaHandler(MSBSSSeg
.get());
569 PP
.RemovePragmaHandler(MSConstSeg
.get());
571 PP
.RemovePragmaHandler(MSCodeSeg
.get());
573 PP
.RemovePragmaHandler(MSSection
.get());
575 PP
.RemovePragmaHandler(MSStrictGuardStackCheck
.get());
576 MSStrictGuardStackCheck
.reset();
577 PP
.RemovePragmaHandler(MSFunction
.get());
579 PP
.RemovePragmaHandler(MSAllocText
.get());
581 PP
.RemovePragmaHandler(MSRuntimeChecks
.get());
582 MSRuntimeChecks
.reset();
583 PP
.RemovePragmaHandler(MSIntrinsic
.get());
585 PP
.RemovePragmaHandler(MSOptimize
.get());
587 PP
.RemovePragmaHandler(MSFenvAccess
.get());
588 MSFenvAccess
.reset();
591 if (getLangOpts().CUDA
) {
592 PP
.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler
.get());
593 CUDAForceHostDeviceHandler
.reset();
596 PP
.RemovePragmaHandler("STDC", FPContractHandler
.get());
597 FPContractHandler
.reset();
599 PP
.RemovePragmaHandler("STDC", STDCFenvAccessHandler
.get());
600 STDCFenvAccessHandler
.reset();
602 PP
.RemovePragmaHandler("STDC", STDCFenvRoundHandler
.get());
603 STDCFenvRoundHandler
.reset();
605 PP
.RemovePragmaHandler("STDC", STDCCXLIMITHandler
.get());
606 STDCCXLIMITHandler
.reset();
608 PP
.RemovePragmaHandler("STDC", STDCUnknownHandler
.get());
609 STDCUnknownHandler
.reset();
611 PP
.RemovePragmaHandler("clang", OptimizeHandler
.get());
612 OptimizeHandler
.reset();
614 PP
.RemovePragmaHandler("clang", LoopHintHandler
.get());
615 LoopHintHandler
.reset();
617 PP
.RemovePragmaHandler(UnrollHintHandler
.get());
618 PP
.RemovePragmaHandler("GCC", UnrollHintHandler
.get());
619 UnrollHintHandler
.reset();
621 PP
.RemovePragmaHandler(NoUnrollHintHandler
.get());
622 PP
.RemovePragmaHandler("GCC", NoUnrollHintHandler
.get());
623 NoUnrollHintHandler
.reset();
625 PP
.RemovePragmaHandler(UnrollAndJamHintHandler
.get());
626 UnrollAndJamHintHandler
.reset();
628 PP
.RemovePragmaHandler(NoUnrollAndJamHintHandler
.get());
629 NoUnrollAndJamHintHandler
.reset();
631 PP
.RemovePragmaHandler("clang", FPHandler
.get());
634 PP
.RemovePragmaHandler("clang", AttributePragmaHandler
.get());
635 AttributePragmaHandler
.reset();
637 PP
.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler
.get());
638 MaxTokensHerePragmaHandler
.reset();
640 PP
.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler
.get());
641 MaxTokensTotalPragmaHandler
.reset();
643 if (getTargetInfo().getTriple().isRISCV()) {
644 PP
.RemovePragmaHandler("clang", RISCVPragmaHandler
.get());
645 RISCVPragmaHandler
.reset();
649 /// Handle the annotation token produced for #pragma unused(...)
651 /// Each annot_pragma_unused is followed by the argument token so e.g.
652 /// "#pragma unused(x,y)" becomes:
653 /// annot_pragma_unused 'x' annot_pragma_unused 'y'
654 void Parser::HandlePragmaUnused() {
655 assert(Tok
.is(tok::annot_pragma_unused
));
656 SourceLocation UnusedLoc
= ConsumeAnnotationToken();
657 Actions
.ActOnPragmaUnused(Tok
, getCurScope(), UnusedLoc
);
658 ConsumeToken(); // The argument token.
661 void Parser::HandlePragmaVisibility() {
662 assert(Tok
.is(tok::annot_pragma_vis
));
663 const IdentifierInfo
*VisType
=
664 static_cast<IdentifierInfo
*>(Tok
.getAnnotationValue());
665 SourceLocation VisLoc
= ConsumeAnnotationToken();
666 Actions
.ActOnPragmaVisibility(VisType
, VisLoc
);
669 void Parser::HandlePragmaPack() {
670 assert(Tok
.is(tok::annot_pragma_pack
));
671 Sema::PragmaPackInfo
*Info
=
672 static_cast<Sema::PragmaPackInfo
*>(Tok
.getAnnotationValue());
673 SourceLocation PragmaLoc
= Tok
.getLocation();
674 ExprResult Alignment
;
675 if (Info
->Alignment
.is(tok::numeric_constant
)) {
676 Alignment
= Actions
.ActOnNumericConstant(Info
->Alignment
);
677 if (Alignment
.isInvalid()) {
678 ConsumeAnnotationToken();
682 Actions
.ActOnPragmaPack(PragmaLoc
, Info
->Action
, Info
->SlotLabel
,
684 // Consume the token after processing the pragma to enable pragma-specific
685 // #include warnings.
686 ConsumeAnnotationToken();
689 void Parser::HandlePragmaMSStruct() {
690 assert(Tok
.is(tok::annot_pragma_msstruct
));
691 PragmaMSStructKind Kind
= static_cast<PragmaMSStructKind
>(
692 reinterpret_cast<uintptr_t>(Tok
.getAnnotationValue()));
693 Actions
.ActOnPragmaMSStruct(Kind
);
694 ConsumeAnnotationToken();
697 void Parser::HandlePragmaAlign() {
698 assert(Tok
.is(tok::annot_pragma_align
));
699 Sema::PragmaOptionsAlignKind Kind
=
700 static_cast<Sema::PragmaOptionsAlignKind
>(
701 reinterpret_cast<uintptr_t>(Tok
.getAnnotationValue()));
702 Actions
.ActOnPragmaOptionsAlign(Kind
, Tok
.getLocation());
703 // Consume the token after processing the pragma to enable pragma-specific
704 // #include warnings.
705 ConsumeAnnotationToken();
708 void Parser::HandlePragmaDump() {
709 assert(Tok
.is(tok::annot_pragma_dump
));
710 ConsumeAnnotationToken();
711 if (Tok
.is(tok::eod
)) {
712 PP
.Diag(Tok
, diag::warn_pragma_debug_missing_argument
) << "dump";
713 } else if (NextToken().is(tok::eod
)) {
714 if (Tok
.isNot(tok::identifier
)) {
715 PP
.Diag(Tok
, diag::warn_pragma_debug_unexpected_argument
);
717 ExpectAndConsume(tok::eod
);
720 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
721 Actions
.ActOnPragmaDump(getCurScope(), Tok
.getLocation(), II
);
724 SourceLocation StartLoc
= Tok
.getLocation();
725 EnterExpressionEvaluationContext
Ctx(
726 Actions
, Sema::ExpressionEvaluationContext::Unevaluated
);
727 ExprResult E
= ParseExpression();
728 if (!E
.isUsable() || E
.get()->containsErrors()) {
729 // Diagnostics were emitted during parsing. No action needed.
730 } else if (E
.get()->getDependence() != ExprDependence::None
) {
731 PP
.Diag(StartLoc
, diag::warn_pragma_debug_dependent_argument
)
732 << E
.get()->isTypeDependent()
733 << SourceRange(StartLoc
, Tok
.getLocation());
735 Actions
.ActOnPragmaDump(E
.get());
737 SkipUntil(tok::eod
, StopBeforeMatch
);
739 ExpectAndConsume(tok::eod
);
742 void Parser::HandlePragmaWeak() {
743 assert(Tok
.is(tok::annot_pragma_weak
));
744 SourceLocation PragmaLoc
= ConsumeAnnotationToken();
745 Actions
.ActOnPragmaWeakID(Tok
.getIdentifierInfo(), PragmaLoc
,
747 ConsumeToken(); // The weak name.
750 void Parser::HandlePragmaWeakAlias() {
751 assert(Tok
.is(tok::annot_pragma_weakalias
));
752 SourceLocation PragmaLoc
= ConsumeAnnotationToken();
753 IdentifierInfo
*WeakName
= Tok
.getIdentifierInfo();
754 SourceLocation WeakNameLoc
= Tok
.getLocation();
756 IdentifierInfo
*AliasName
= Tok
.getIdentifierInfo();
757 SourceLocation AliasNameLoc
= Tok
.getLocation();
759 Actions
.ActOnPragmaWeakAlias(WeakName
, AliasName
, PragmaLoc
,
760 WeakNameLoc
, AliasNameLoc
);
764 void Parser::HandlePragmaRedefineExtname() {
765 assert(Tok
.is(tok::annot_pragma_redefine_extname
));
766 SourceLocation RedefLoc
= ConsumeAnnotationToken();
767 IdentifierInfo
*RedefName
= Tok
.getIdentifierInfo();
768 SourceLocation RedefNameLoc
= Tok
.getLocation();
770 IdentifierInfo
*AliasName
= Tok
.getIdentifierInfo();
771 SourceLocation AliasNameLoc
= Tok
.getLocation();
773 Actions
.ActOnPragmaRedefineExtname(RedefName
, AliasName
, RedefLoc
,
774 RedefNameLoc
, AliasNameLoc
);
777 void Parser::HandlePragmaFPContract() {
778 assert(Tok
.is(tok::annot_pragma_fp_contract
));
779 tok::OnOffSwitch OOS
=
780 static_cast<tok::OnOffSwitch
>(
781 reinterpret_cast<uintptr_t>(Tok
.getAnnotationValue()));
783 LangOptions::FPModeKind FPC
;
786 FPC
= LangOptions::FPM_On
;
789 FPC
= LangOptions::FPM_Off
;
791 case tok::OOS_DEFAULT
:
792 FPC
= getLangOpts().getDefaultFPContractMode();
796 SourceLocation PragmaLoc
= ConsumeAnnotationToken();
797 Actions
.ActOnPragmaFPContract(PragmaLoc
, FPC
);
800 void Parser::HandlePragmaFloatControl() {
801 assert(Tok
.is(tok::annot_pragma_float_control
));
803 // The value that is held on the PragmaFloatControlStack encodes
804 // the PragmaFloatControl kind and the MSStackAction kind
805 // into a single 32-bit word. The MsStackAction is the high 16 bits
806 // and the FloatControl is the lower 16 bits. Use shift and bit-and
807 // to decode the parts.
808 uintptr_t Value
= reinterpret_cast<uintptr_t>(Tok
.getAnnotationValue());
809 Sema::PragmaMsStackAction Action
=
810 static_cast<Sema::PragmaMsStackAction
>((Value
>> 16) & 0xFFFF);
811 PragmaFloatControlKind Kind
= PragmaFloatControlKind(Value
& 0xFFFF);
812 SourceLocation PragmaLoc
= ConsumeAnnotationToken();
813 Actions
.ActOnPragmaFloatControl(PragmaLoc
, Action
, Kind
);
816 void Parser::HandlePragmaFEnvAccess() {
817 assert(Tok
.is(tok::annot_pragma_fenv_access
) ||
818 Tok
.is(tok::annot_pragma_fenv_access_ms
));
819 tok::OnOffSwitch OOS
=
820 static_cast<tok::OnOffSwitch
>(
821 reinterpret_cast<uintptr_t>(Tok
.getAnnotationValue()));
831 case tok::OOS_DEFAULT
: // FIXME: Add this cli option when it makes sense.
836 SourceLocation PragmaLoc
= ConsumeAnnotationToken();
837 Actions
.ActOnPragmaFEnvAccess(PragmaLoc
, IsEnabled
);
840 void Parser::HandlePragmaFEnvRound() {
841 assert(Tok
.is(tok::annot_pragma_fenv_round
));
842 auto RM
= static_cast<llvm::RoundingMode
>(
843 reinterpret_cast<uintptr_t>(Tok
.getAnnotationValue()));
845 SourceLocation PragmaLoc
= ConsumeAnnotationToken();
846 Actions
.ActOnPragmaFEnvRound(PragmaLoc
, RM
);
849 StmtResult
Parser::HandlePragmaCaptured()
851 assert(Tok
.is(tok::annot_pragma_captured
));
852 ConsumeAnnotationToken();
854 if (Tok
.isNot(tok::l_brace
)) {
855 PP
.Diag(Tok
, diag::err_expected
) << tok::l_brace
;
859 SourceLocation Loc
= Tok
.getLocation();
861 ParseScope
CapturedRegionScope(this, Scope::FnScope
| Scope::DeclScope
|
862 Scope::CompoundStmtScope
);
863 Actions
.ActOnCapturedRegionStart(Loc
, getCurScope(), CR_Default
,
866 StmtResult R
= ParseCompoundStatement();
867 CapturedRegionScope
.Exit();
870 Actions
.ActOnCapturedRegionError();
874 return Actions
.ActOnCapturedRegionEnd(R
.get());
878 enum OpenCLExtState
: char {
879 Disable
, Enable
, Begin
, End
881 typedef std::pair
<const IdentifierInfo
*, OpenCLExtState
> OpenCLExtData
;
884 void Parser::HandlePragmaOpenCLExtension() {
885 assert(Tok
.is(tok::annot_pragma_opencl_extension
));
886 OpenCLExtData
*Data
= static_cast<OpenCLExtData
*>(Tok
.getAnnotationValue());
887 auto State
= Data
->second
;
888 auto Ident
= Data
->first
;
889 SourceLocation NameLoc
= Tok
.getLocation();
890 ConsumeAnnotationToken();
892 auto &Opt
= Actions
.getOpenCLOptions();
893 auto Name
= Ident
->getName();
894 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
895 // overriding all previously issued extension directives, but only if the
896 // behavior is set to disable."
898 if (State
== Disable
)
901 PP
.Diag(NameLoc
, diag::warn_pragma_expected_predicate
) << 1;
902 } else if (State
== Begin
) {
903 if (!Opt
.isKnown(Name
) || !Opt
.isSupported(Name
, getLangOpts())) {
905 // FIXME: Default behavior of the extension pragma is not defined.
906 // Therefore, it should never be added by default.
907 Opt
.acceptsPragma(Name
);
909 } else if (State
== End
) {
910 // There is no behavior for this directive. We only accept this for
911 // backward compatibility.
912 } else if (!Opt
.isKnown(Name
) || !Opt
.isWithPragma(Name
))
913 PP
.Diag(NameLoc
, diag::warn_pragma_unknown_extension
) << Ident
;
914 else if (Opt
.isSupportedExtension(Name
, getLangOpts()))
915 Opt
.enable(Name
, State
== Enable
);
916 else if (Opt
.isSupportedCoreOrOptionalCore(Name
, getLangOpts()))
917 PP
.Diag(NameLoc
, diag::warn_pragma_extension_is_core
) << Ident
;
919 PP
.Diag(NameLoc
, diag::warn_pragma_unsupported_extension
) << Ident
;
922 void Parser::HandlePragmaMSPointersToMembers() {
923 assert(Tok
.is(tok::annot_pragma_ms_pointers_to_members
));
924 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod
=
925 static_cast<LangOptions::PragmaMSPointersToMembersKind
>(
926 reinterpret_cast<uintptr_t>(Tok
.getAnnotationValue()));
927 SourceLocation PragmaLoc
= ConsumeAnnotationToken();
928 Actions
.ActOnPragmaMSPointersToMembers(RepresentationMethod
, PragmaLoc
);
931 void Parser::HandlePragmaMSVtorDisp() {
932 assert(Tok
.is(tok::annot_pragma_ms_vtordisp
));
933 uintptr_t Value
= reinterpret_cast<uintptr_t>(Tok
.getAnnotationValue());
934 Sema::PragmaMsStackAction Action
=
935 static_cast<Sema::PragmaMsStackAction
>((Value
>> 16) & 0xFFFF);
936 MSVtorDispMode Mode
= MSVtorDispMode(Value
& 0xFFFF);
937 SourceLocation PragmaLoc
= ConsumeAnnotationToken();
938 Actions
.ActOnPragmaMSVtorDisp(Action
, PragmaLoc
, Mode
);
941 void Parser::HandlePragmaMSPragma() {
942 assert(Tok
.is(tok::annot_pragma_ms_pragma
));
943 // Grab the tokens out of the annotation and enter them into the stream.
945 (std::pair
<std::unique_ptr
<Token
[]>, size_t> *)Tok
.getAnnotationValue();
946 PP
.EnterTokenStream(std::move(TheTokens
->first
), TheTokens
->second
, true,
947 /*IsReinject=*/true);
948 SourceLocation PragmaLocation
= ConsumeAnnotationToken();
949 assert(Tok
.isAnyIdentifier());
950 StringRef PragmaName
= Tok
.getIdentifierInfo()->getName();
951 PP
.Lex(Tok
); // pragma kind
953 // Figure out which #pragma we're dealing with. The switch has no default
954 // because lex shouldn't emit the annotation token for unrecognized pragmas.
955 typedef bool (Parser::*PragmaHandler
)(StringRef
, SourceLocation
);
956 PragmaHandler Handler
=
957 llvm::StringSwitch
<PragmaHandler
>(PragmaName
)
958 .Case("data_seg", &Parser::HandlePragmaMSSegment
)
959 .Case("bss_seg", &Parser::HandlePragmaMSSegment
)
960 .Case("const_seg", &Parser::HandlePragmaMSSegment
)
961 .Case("code_seg", &Parser::HandlePragmaMSSegment
)
962 .Case("section", &Parser::HandlePragmaMSSection
)
963 .Case("init_seg", &Parser::HandlePragmaMSInitSeg
)
964 .Case("strict_gs_check", &Parser::HandlePragmaMSStrictGuardStackCheck
)
965 .Case("function", &Parser::HandlePragmaMSFunction
)
966 .Case("alloc_text", &Parser::HandlePragmaMSAllocText
)
967 .Case("optimize", &Parser::HandlePragmaMSOptimize
);
969 if (!(this->*Handler
)(PragmaName
, PragmaLocation
)) {
970 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
971 // until eof (really end of line) to prevent follow-on errors.
972 while (Tok
.isNot(tok::eof
))
978 bool Parser::HandlePragmaMSSection(StringRef PragmaName
,
979 SourceLocation PragmaLocation
) {
980 if (Tok
.isNot(tok::l_paren
)) {
981 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_lparen
) << PragmaName
;
985 // Parsing code for pragma section
986 if (Tok
.isNot(tok::string_literal
)) {
987 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_section_name
)
991 ExprResult StringResult
= ParseStringLiteralExpression();
992 if (StringResult
.isInvalid())
993 return false; // Already diagnosed.
994 StringLiteral
*SegmentName
= cast
<StringLiteral
>(StringResult
.get());
995 if (SegmentName
->getCharByteWidth() != 1) {
996 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_non_wide_string
)
1000 int SectionFlags
= ASTContext::PSF_Read
;
1001 bool SectionFlagsAreDefault
= true;
1002 while (Tok
.is(tok::comma
)) {
1004 // Ignore "long" and "short".
1005 // They are undocumented, but widely used, section attributes which appear
1007 if (Tok
.is(tok::kw_long
) || Tok
.is(tok::kw_short
)) {
1008 PP
.Lex(Tok
); // long/short
1012 if (!Tok
.isAnyIdentifier()) {
1013 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_action_or_r_paren
)
1017 ASTContext::PragmaSectionFlag Flag
=
1018 llvm::StringSwitch
<ASTContext::PragmaSectionFlag
>(
1019 Tok
.getIdentifierInfo()->getName())
1020 .Case("read", ASTContext::PSF_Read
)
1021 .Case("write", ASTContext::PSF_Write
)
1022 .Case("execute", ASTContext::PSF_Execute
)
1023 .Case("shared", ASTContext::PSF_Invalid
)
1024 .Case("nopage", ASTContext::PSF_Invalid
)
1025 .Case("nocache", ASTContext::PSF_Invalid
)
1026 .Case("discard", ASTContext::PSF_Invalid
)
1027 .Case("remove", ASTContext::PSF_Invalid
)
1028 .Default(ASTContext::PSF_None
);
1029 if (Flag
== ASTContext::PSF_None
|| Flag
== ASTContext::PSF_Invalid
) {
1030 PP
.Diag(PragmaLocation
, Flag
== ASTContext::PSF_None
1031 ? diag::warn_pragma_invalid_specific_action
1032 : diag::warn_pragma_unsupported_action
)
1033 << PragmaName
<< Tok
.getIdentifierInfo()->getName();
1036 SectionFlags
|= Flag
;
1037 SectionFlagsAreDefault
= false;
1038 PP
.Lex(Tok
); // Identifier
1040 // If no section attributes are specified, the section will be marked as
1042 if (SectionFlagsAreDefault
)
1043 SectionFlags
|= ASTContext::PSF_Write
;
1044 if (Tok
.isNot(tok::r_paren
)) {
1045 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_rparen
) << PragmaName
;
1049 if (Tok
.isNot(tok::eof
)) {
1050 PP
.Diag(PragmaLocation
, diag::warn_pragma_extra_tokens_at_eol
)
1055 Actions
.ActOnPragmaMSSection(PragmaLocation
, SectionFlags
, SegmentName
);
1059 bool Parser::HandlePragmaMSSegment(StringRef PragmaName
,
1060 SourceLocation PragmaLocation
) {
1061 if (Tok
.isNot(tok::l_paren
)) {
1062 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_lparen
) << PragmaName
;
1066 Sema::PragmaMsStackAction Action
= Sema::PSK_Reset
;
1067 StringRef SlotLabel
;
1068 if (Tok
.isAnyIdentifier()) {
1069 StringRef PushPop
= Tok
.getIdentifierInfo()->getName();
1070 if (PushPop
== "push")
1071 Action
= Sema::PSK_Push
;
1072 else if (PushPop
== "pop")
1073 Action
= Sema::PSK_Pop
;
1075 PP
.Diag(PragmaLocation
,
1076 diag::warn_pragma_expected_section_push_pop_or_name
)
1080 if (Action
!= Sema::PSK_Reset
) {
1081 PP
.Lex(Tok
); // push | pop
1082 if (Tok
.is(tok::comma
)) {
1084 // If we've got a comma, we either need a label or a string.
1085 if (Tok
.isAnyIdentifier()) {
1086 SlotLabel
= Tok
.getIdentifierInfo()->getName();
1087 PP
.Lex(Tok
); // identifier
1088 if (Tok
.is(tok::comma
))
1090 else if (Tok
.isNot(tok::r_paren
)) {
1091 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_punc
)
1096 } else if (Tok
.isNot(tok::r_paren
)) {
1097 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_punc
) << PragmaName
;
1102 // Grab the string literal for our section name.
1103 StringLiteral
*SegmentName
= nullptr;
1104 if (Tok
.isNot(tok::r_paren
)) {
1105 if (Tok
.isNot(tok::string_literal
)) {
1106 unsigned DiagID
= Action
!= Sema::PSK_Reset
? !SlotLabel
.empty() ?
1107 diag::warn_pragma_expected_section_name
:
1108 diag::warn_pragma_expected_section_label_or_name
:
1109 diag::warn_pragma_expected_section_push_pop_or_name
;
1110 PP
.Diag(PragmaLocation
, DiagID
) << PragmaName
;
1113 ExprResult StringResult
= ParseStringLiteralExpression();
1114 if (StringResult
.isInvalid())
1115 return false; // Already diagnosed.
1116 SegmentName
= cast
<StringLiteral
>(StringResult
.get());
1117 if (SegmentName
->getCharByteWidth() != 1) {
1118 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_non_wide_string
)
1122 // Setting section "" has no effect
1123 if (SegmentName
->getLength())
1124 Action
= (Sema::PragmaMsStackAction
)(Action
| Sema::PSK_Set
);
1126 if (Tok
.isNot(tok::r_paren
)) {
1127 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_rparen
) << PragmaName
;
1131 if (Tok
.isNot(tok::eof
)) {
1132 PP
.Diag(PragmaLocation
, diag::warn_pragma_extra_tokens_at_eol
)
1137 Actions
.ActOnPragmaMSSeg(PragmaLocation
, Action
, SlotLabel
,
1138 SegmentName
, PragmaName
);
1142 // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
1143 bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName
,
1144 SourceLocation PragmaLocation
) {
1145 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC
) {
1146 PP
.Diag(PragmaLocation
, diag::warn_pragma_init_seg_unsupported_target
);
1150 if (ExpectAndConsume(tok::l_paren
, diag::warn_pragma_expected_lparen
,
1154 // Parse either the known section names or the string section name.
1155 StringLiteral
*SegmentName
= nullptr;
1156 if (Tok
.isAnyIdentifier()) {
1157 auto *II
= Tok
.getIdentifierInfo();
1158 StringRef Section
= llvm::StringSwitch
<StringRef
>(II
->getName())
1159 .Case("compiler", "\".CRT$XCC\"")
1160 .Case("lib", "\".CRT$XCL\"")
1161 .Case("user", "\".CRT$XCU\"")
1164 if (!Section
.empty()) {
1165 // Pretend the user wrote the appropriate string literal here.
1167 Toks
[0].startToken();
1168 Toks
[0].setKind(tok::string_literal
);
1169 Toks
[0].setLocation(Tok
.getLocation());
1170 Toks
[0].setLiteralData(Section
.data());
1171 Toks
[0].setLength(Section
.size());
1173 cast
<StringLiteral
>(Actions
.ActOnStringLiteral(Toks
, nullptr).get());
1176 } else if (Tok
.is(tok::string_literal
)) {
1177 ExprResult StringResult
= ParseStringLiteralExpression();
1178 if (StringResult
.isInvalid())
1180 SegmentName
= cast
<StringLiteral
>(StringResult
.get());
1181 if (SegmentName
->getCharByteWidth() != 1) {
1182 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_non_wide_string
)
1186 // FIXME: Add support for the '[, func-name]' part of the pragma.
1190 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_init_seg
) << PragmaName
;
1194 if (ExpectAndConsume(tok::r_paren
, diag::warn_pragma_expected_rparen
,
1196 ExpectAndConsume(tok::eof
, diag::warn_pragma_extra_tokens_at_eol
,
1200 Actions
.ActOnPragmaMSInitSeg(PragmaLocation
, SegmentName
);
1204 // #pragma strict_gs_check(pop)
1205 // #pragma strict_gs_check(push, "on" | "off")
1206 // #pragma strict_gs_check("on" | "off")
1207 bool Parser::HandlePragmaMSStrictGuardStackCheck(
1208 StringRef PragmaName
, SourceLocation PragmaLocation
) {
1209 if (ExpectAndConsume(tok::l_paren
, diag::warn_pragma_expected_lparen
,
1213 Sema::PragmaMsStackAction Action
= Sema::PSK_Set
;
1214 if (Tok
.is(tok::identifier
)) {
1215 StringRef PushPop
= Tok
.getIdentifierInfo()->getName();
1216 if (PushPop
== "push") {
1218 Action
= Sema::PSK_Push
;
1219 if (ExpectAndConsume(tok::comma
, diag::warn_pragma_expected_punc
,
1222 } else if (PushPop
== "pop") {
1224 Action
= Sema::PSK_Pop
;
1229 if (Action
& Sema::PSK_Push
|| Action
& Sema::PSK_Set
) {
1230 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
1231 if (II
&& II
->isStr("off")) {
1234 } else if (II
&& II
->isStr("on")) {
1238 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_invalid_action
)
1244 // Finish the pragma: ')' $
1245 if (ExpectAndConsume(tok::r_paren
, diag::warn_pragma_expected_rparen
,
1249 if (ExpectAndConsume(tok::eof
, diag::warn_pragma_extra_tokens_at_eol
,
1253 Actions
.ActOnPragmaMSStrictGuardStackCheck(PragmaLocation
, Action
, Value
);
1257 bool Parser::HandlePragmaMSAllocText(StringRef PragmaName
,
1258 SourceLocation PragmaLocation
) {
1259 Token FirstTok
= Tok
;
1260 if (ExpectAndConsume(tok::l_paren
, diag::warn_pragma_expected_lparen
,
1265 if (Tok
.is(tok::string_literal
)) {
1266 ExprResult StringResult
= ParseStringLiteralExpression();
1267 if (StringResult
.isInvalid())
1268 return false; // Already diagnosed.
1269 StringLiteral
*SegmentName
= cast
<StringLiteral
>(StringResult
.get());
1270 if (SegmentName
->getCharByteWidth() != 1) {
1271 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_non_wide_string
)
1275 Section
= SegmentName
->getString();
1276 } else if (Tok
.is(tok::identifier
)) {
1277 Section
= Tok
.getIdentifierInfo()->getName();
1280 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_section_name
)
1285 if (ExpectAndConsume(tok::comma
, diag::warn_pragma_expected_comma
,
1289 SmallVector
<std::tuple
<IdentifierInfo
*, SourceLocation
>> Functions
;
1291 if (Tok
.isNot(tok::identifier
)) {
1292 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_identifier
)
1297 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
1298 Functions
.emplace_back(II
, Tok
.getLocation());
1301 if (Tok
.isNot(tok::comma
))
1306 if (ExpectAndConsume(tok::r_paren
, diag::warn_pragma_expected_rparen
,
1308 ExpectAndConsume(tok::eof
, diag::warn_pragma_extra_tokens_at_eol
,
1312 Actions
.ActOnPragmaMSAllocText(FirstTok
.getLocation(), Section
, Functions
);
1316 static std::string
PragmaLoopHintString(Token PragmaName
, Token Option
) {
1317 StringRef Str
= PragmaName
.getIdentifierInfo()->getName();
1318 std::string
ClangLoopStr("clang loop ");
1319 if (Str
== "loop" && Option
.getIdentifierInfo())
1320 ClangLoopStr
+= Option
.getIdentifierInfo()->getName();
1321 return std::string(llvm::StringSwitch
<StringRef
>(Str
)
1322 .Case("loop", ClangLoopStr
)
1323 .Case("unroll_and_jam", Str
)
1324 .Case("unroll", Str
)
1328 bool Parser::HandlePragmaLoopHint(LoopHint
&Hint
) {
1329 assert(Tok
.is(tok::annot_pragma_loop_hint
));
1330 PragmaLoopHintInfo
*Info
=
1331 static_cast<PragmaLoopHintInfo
*>(Tok
.getAnnotationValue());
1333 IdentifierInfo
*PragmaNameInfo
= Info
->PragmaName
.getIdentifierInfo();
1334 Hint
.PragmaNameLoc
= IdentifierLoc::create(
1335 Actions
.Context
, Info
->PragmaName
.getLocation(), PragmaNameInfo
);
1337 // It is possible that the loop hint has no option identifier, such as
1338 // #pragma unroll(4).
1339 IdentifierInfo
*OptionInfo
= Info
->Option
.is(tok::identifier
)
1340 ? Info
->Option
.getIdentifierInfo()
1342 Hint
.OptionLoc
= IdentifierLoc::create(
1343 Actions
.Context
, Info
->Option
.getLocation(), OptionInfo
);
1345 llvm::ArrayRef
<Token
> Toks
= Info
->Toks
;
1347 // Return a valid hint if pragma unroll or nounroll were specified
1348 // without an argument.
1349 auto IsLoopHint
= llvm::StringSwitch
<bool>(PragmaNameInfo
->getName())
1350 .Cases("unroll", "nounroll", "unroll_and_jam",
1351 "nounroll_and_jam", true)
1354 if (Toks
.empty() && IsLoopHint
) {
1355 ConsumeAnnotationToken();
1356 Hint
.Range
= Info
->PragmaName
.getLocation();
1360 // The constant expression is always followed by an eof token, which increases
1361 // the TokSize by 1.
1362 assert(!Toks
.empty() &&
1363 "PragmaLoopHintInfo::Toks must contain at least one token.");
1365 // If no option is specified the argument is assumed to be a constant expr.
1366 bool OptionUnroll
= false;
1367 bool OptionUnrollAndJam
= false;
1368 bool OptionDistribute
= false;
1369 bool OptionPipelineDisabled
= false;
1370 bool StateOption
= false;
1371 if (OptionInfo
) { // Pragma Unroll does not specify an option.
1372 OptionUnroll
= OptionInfo
->isStr("unroll");
1373 OptionUnrollAndJam
= OptionInfo
->isStr("unroll_and_jam");
1374 OptionDistribute
= OptionInfo
->isStr("distribute");
1375 OptionPipelineDisabled
= OptionInfo
->isStr("pipeline");
1376 StateOption
= llvm::StringSwitch
<bool>(OptionInfo
->getName())
1377 .Case("vectorize", true)
1378 .Case("interleave", true)
1379 .Case("vectorize_predicate", true)
1381 OptionUnroll
|| OptionUnrollAndJam
|| OptionDistribute
||
1382 OptionPipelineDisabled
;
1385 bool AssumeSafetyArg
= !OptionUnroll
&& !OptionUnrollAndJam
&&
1386 !OptionDistribute
&& !OptionPipelineDisabled
;
1387 // Verify loop hint has an argument.
1388 if (Toks
[0].is(tok::eof
)) {
1389 ConsumeAnnotationToken();
1390 Diag(Toks
[0].getLocation(), diag::err_pragma_loop_missing_argument
)
1391 << /*StateArgument=*/StateOption
1392 << /*FullKeyword=*/(OptionUnroll
|| OptionUnrollAndJam
)
1393 << /*AssumeSafetyKeyword=*/AssumeSafetyArg
;
1397 // Validate the argument.
1399 ConsumeAnnotationToken();
1400 SourceLocation StateLoc
= Toks
[0].getLocation();
1401 IdentifierInfo
*StateInfo
= Toks
[0].getIdentifierInfo();
1403 bool Valid
= StateInfo
&&
1404 llvm::StringSwitch
<bool>(StateInfo
->getName())
1405 .Case("disable", true)
1406 .Case("enable", !OptionPipelineDisabled
)
1407 .Case("full", OptionUnroll
|| OptionUnrollAndJam
)
1408 .Case("assume_safety", AssumeSafetyArg
)
1411 if (OptionPipelineDisabled
) {
1412 Diag(Toks
[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword
);
1414 Diag(Toks
[0].getLocation(), diag::err_pragma_invalid_keyword
)
1415 << /*FullKeyword=*/(OptionUnroll
|| OptionUnrollAndJam
)
1416 << /*AssumeSafetyKeyword=*/AssumeSafetyArg
;
1420 if (Toks
.size() > 2)
1421 Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
1422 << PragmaLoopHintString(Info
->PragmaName
, Info
->Option
);
1423 Hint
.StateLoc
= IdentifierLoc::create(Actions
.Context
, StateLoc
, StateInfo
);
1424 } else if (OptionInfo
&& OptionInfo
->getName() == "vectorize_width") {
1425 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/false,
1426 /*IsReinject=*/false);
1427 ConsumeAnnotationToken();
1429 SourceLocation StateLoc
= Toks
[0].getLocation();
1430 IdentifierInfo
*StateInfo
= Toks
[0].getIdentifierInfo();
1431 StringRef IsScalableStr
= StateInfo
? StateInfo
->getName() : "";
1433 // Look for vectorize_width(fixed|scalable)
1434 if (IsScalableStr
== "scalable" || IsScalableStr
== "fixed") {
1435 PP
.Lex(Tok
); // Identifier
1437 if (Toks
.size() > 2) {
1438 Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
1439 << PragmaLoopHintString(Info
->PragmaName
, Info
->Option
);
1440 while (Tok
.isNot(tok::eof
))
1445 IdentifierLoc::create(Actions
.Context
, StateLoc
, StateInfo
);
1447 ConsumeToken(); // Consume the constant expression eof terminator.
1449 // Enter constant expression including eof terminator into token stream.
1450 ExprResult R
= ParseConstantExpression();
1452 if (R
.isInvalid() && !Tok
.is(tok::comma
))
1453 Diag(Toks
[0].getLocation(),
1454 diag::note_pragma_loop_invalid_vectorize_option
);
1456 bool Arg2Error
= false;
1457 if (Tok
.is(tok::comma
)) {
1460 StateInfo
= Tok
.getIdentifierInfo();
1461 IsScalableStr
= StateInfo
->getName();
1463 if (IsScalableStr
!= "scalable" && IsScalableStr
!= "fixed") {
1464 Diag(Tok
.getLocation(),
1465 diag::err_pragma_loop_invalid_vectorize_option
);
1469 IdentifierLoc::create(Actions
.Context
, StateLoc
, StateInfo
);
1471 PP
.Lex(Tok
); // Identifier
1474 // Tokens following an error in an ill-formed constant expression will
1475 // remain in the token stream and must be removed.
1476 if (Tok
.isNot(tok::eof
)) {
1477 Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
1478 << PragmaLoopHintString(Info
->PragmaName
, Info
->Option
);
1479 while (Tok
.isNot(tok::eof
))
1483 ConsumeToken(); // Consume the constant expression eof terminator.
1485 if (Arg2Error
|| R
.isInvalid() ||
1486 Actions
.CheckLoopHintExpr(R
.get(), Toks
[0].getLocation()))
1489 // Argument is a constant expression with an integer type.
1490 Hint
.ValueExpr
= R
.get();
1493 // Enter constant expression including eof terminator into token stream.
1494 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/false,
1495 /*IsReinject=*/false);
1496 ConsumeAnnotationToken();
1497 ExprResult R
= ParseConstantExpression();
1499 // Tokens following an error in an ill-formed constant expression will
1500 // remain in the token stream and must be removed.
1501 if (Tok
.isNot(tok::eof
)) {
1502 Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
1503 << PragmaLoopHintString(Info
->PragmaName
, Info
->Option
);
1504 while (Tok
.isNot(tok::eof
))
1508 ConsumeToken(); // Consume the constant expression eof terminator.
1510 if (R
.isInvalid() ||
1511 Actions
.CheckLoopHintExpr(R
.get(), Toks
[0].getLocation()))
1514 // Argument is a constant expression with an integer type.
1515 Hint
.ValueExpr
= R
.get();
1518 Hint
.Range
= SourceRange(Info
->PragmaName
.getLocation(),
1519 Info
->Toks
.back().getLocation());
1524 struct PragmaAttributeInfo
{
1525 enum ActionType
{ Push
, Pop
, Attribute
};
1526 ParsedAttributes
&Attributes
;
1528 const IdentifierInfo
*Namespace
= nullptr;
1529 ArrayRef
<Token
> Tokens
;
1531 PragmaAttributeInfo(ParsedAttributes
&Attributes
) : Attributes(Attributes
) {}
1534 #include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1536 } // end anonymous namespace
1538 static StringRef
getIdentifier(const Token
&Tok
) {
1539 if (Tok
.is(tok::identifier
))
1540 return Tok
.getIdentifierInfo()->getName();
1541 const char *S
= tok::getKeywordSpelling(Tok
.getKind());
1547 static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule
) {
1548 using namespace attr
;
1550 #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1553 #include "clang/Basic/AttrSubMatchRulesList.inc"
1555 llvm_unreachable("Invalid attribute subject match rule");
1559 static void diagnoseExpectedAttributeSubjectSubRule(
1560 Parser
&PRef
, attr::SubjectMatchRule PrimaryRule
, StringRef PrimaryRuleName
,
1561 SourceLocation SubRuleLoc
) {
1563 PRef
.Diag(SubRuleLoc
,
1564 diag::err_pragma_attribute_expected_subject_sub_identifier
)
1566 if (const char *SubRules
= validAttributeSubjectMatchSubRules(PrimaryRule
))
1567 Diagnostic
<< /*SubRulesSupported=*/1 << SubRules
;
1569 Diagnostic
<< /*SubRulesSupported=*/0;
1572 static void diagnoseUnknownAttributeSubjectSubRule(
1573 Parser
&PRef
, attr::SubjectMatchRule PrimaryRule
, StringRef PrimaryRuleName
,
1574 StringRef SubRuleName
, SourceLocation SubRuleLoc
) {
1577 PRef
.Diag(SubRuleLoc
, diag::err_pragma_attribute_unknown_subject_sub_rule
)
1578 << SubRuleName
<< PrimaryRuleName
;
1579 if (const char *SubRules
= validAttributeSubjectMatchSubRules(PrimaryRule
))
1580 Diagnostic
<< /*SubRulesSupported=*/1 << SubRules
;
1582 Diagnostic
<< /*SubRulesSupported=*/0;
1585 bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1586 attr::ParsedSubjectMatchRuleSet
&SubjectMatchRules
, SourceLocation
&AnyLoc
,
1587 SourceLocation
&LastMatchRuleEndLoc
) {
1589 BalancedDelimiterTracker
AnyParens(*this, tok::l_paren
);
1590 if (getIdentifier(Tok
) == "any") {
1591 AnyLoc
= ConsumeToken();
1593 if (AnyParens
.expectAndConsume())
1598 // Parse the subject matcher rule.
1599 StringRef Name
= getIdentifier(Tok
);
1601 Diag(Tok
, diag::err_pragma_attribute_expected_subject_identifier
);
1604 std::pair
<std::optional
<attr::SubjectMatchRule
>,
1605 std::optional
<attr::SubjectMatchRule
> (*)(StringRef
, bool)>
1606 Rule
= isAttributeSubjectMatchRule(Name
);
1608 Diag(Tok
, diag::err_pragma_attribute_unknown_subject_rule
) << Name
;
1611 attr::SubjectMatchRule PrimaryRule
= *Rule
.first
;
1612 SourceLocation RuleLoc
= ConsumeToken();
1614 BalancedDelimiterTracker
Parens(*this, tok::l_paren
);
1615 if (isAbstractAttrMatcherRule(PrimaryRule
)) {
1616 if (Parens
.expectAndConsume())
1618 } else if (Parens
.consumeOpen()) {
1619 if (!SubjectMatchRules
1621 std::make_pair(PrimaryRule
, SourceRange(RuleLoc
, RuleLoc
)))
1623 Diag(RuleLoc
, diag::err_pragma_attribute_duplicate_subject
)
1625 << FixItHint::CreateRemoval(SourceRange(
1626 RuleLoc
, Tok
.is(tok::comma
) ? Tok
.getLocation() : RuleLoc
));
1627 LastMatchRuleEndLoc
= RuleLoc
;
1631 // Parse the sub-rules.
1632 StringRef SubRuleName
= getIdentifier(Tok
);
1633 if (SubRuleName
.empty()) {
1634 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule
, Name
,
1638 attr::SubjectMatchRule SubRule
;
1639 if (SubRuleName
== "unless") {
1640 SourceLocation SubRuleLoc
= ConsumeToken();
1641 BalancedDelimiterTracker
Parens(*this, tok::l_paren
);
1642 if (Parens
.expectAndConsume())
1644 SubRuleName
= getIdentifier(Tok
);
1645 if (SubRuleName
.empty()) {
1646 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule
, Name
,
1650 auto SubRuleOrNone
= Rule
.second(SubRuleName
, /*IsUnless=*/true);
1651 if (!SubRuleOrNone
) {
1652 std::string SubRuleUnlessName
= "unless(" + SubRuleName
.str() + ")";
1653 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule
, Name
,
1654 SubRuleUnlessName
, SubRuleLoc
);
1657 SubRule
= *SubRuleOrNone
;
1659 if (Parens
.consumeClose())
1662 auto SubRuleOrNone
= Rule
.second(SubRuleName
, /*IsUnless=*/false);
1663 if (!SubRuleOrNone
) {
1664 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule
, Name
,
1665 SubRuleName
, Tok
.getLocation());
1668 SubRule
= *SubRuleOrNone
;
1671 SourceLocation RuleEndLoc
= Tok
.getLocation();
1672 LastMatchRuleEndLoc
= RuleEndLoc
;
1673 if (Parens
.consumeClose())
1675 if (!SubjectMatchRules
1676 .insert(std::make_pair(SubRule
, SourceRange(RuleLoc
, RuleEndLoc
)))
1678 Diag(RuleLoc
, diag::err_pragma_attribute_duplicate_subject
)
1679 << attr::getSubjectMatchRuleSpelling(SubRule
)
1680 << FixItHint::CreateRemoval(SourceRange(
1681 RuleLoc
, Tok
.is(tok::comma
) ? Tok
.getLocation() : RuleEndLoc
));
1684 } while (IsAny
&& TryConsumeToken(tok::comma
));
1687 if (AnyParens
.consumeClose())
1695 /// Describes the stage at which attribute subject rule parsing was interrupted.
1696 enum class MissingAttributeSubjectRulesRecoveryPoint
{
1704 MissingAttributeSubjectRulesRecoveryPoint
1705 getAttributeSubjectRulesRecoveryPointForToken(const Token
&Tok
) {
1706 if (const auto *II
= Tok
.getIdentifierInfo()) {
1707 if (II
->isStr("apply_to"))
1708 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo
;
1709 if (II
->isStr("any"))
1710 return MissingAttributeSubjectRulesRecoveryPoint::Any
;
1712 if (Tok
.is(tok::equal
))
1713 return MissingAttributeSubjectRulesRecoveryPoint::Equals
;
1714 return MissingAttributeSubjectRulesRecoveryPoint::None
;
1717 /// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1718 /// suggests the possible attribute subject rules in a fix-it together with
1719 /// any other missing tokens.
1720 DiagnosticBuilder
createExpectedAttributeSubjectRulesTokenDiagnostic(
1721 unsigned DiagID
, ParsedAttributes
&Attrs
,
1722 MissingAttributeSubjectRulesRecoveryPoint Point
, Parser
&PRef
) {
1723 SourceLocation Loc
= PRef
.getEndOfPreviousToken();
1724 if (Loc
.isInvalid())
1725 Loc
= PRef
.getCurToken().getLocation();
1726 auto Diagnostic
= PRef
.Diag(Loc
, DiagID
);
1728 MissingAttributeSubjectRulesRecoveryPoint EndPoint
=
1729 getAttributeSubjectRulesRecoveryPointForToken(PRef
.getCurToken());
1730 if (Point
== MissingAttributeSubjectRulesRecoveryPoint::Comma
)
1732 if (Point
<= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo
&&
1733 EndPoint
> MissingAttributeSubjectRulesRecoveryPoint::ApplyTo
)
1734 FixIt
+= "apply_to";
1735 if (Point
<= MissingAttributeSubjectRulesRecoveryPoint::Equals
&&
1736 EndPoint
> MissingAttributeSubjectRulesRecoveryPoint::Equals
)
1738 SourceRange
FixItRange(Loc
);
1739 if (EndPoint
== MissingAttributeSubjectRulesRecoveryPoint::None
) {
1740 // Gather the subject match rules that are supported by the attribute.
1741 // Add all the possible rules initially.
1742 llvm::BitVector
IsMatchRuleAvailable(attr::SubjectMatchRule_Last
+ 1, true);
1743 // Remove the ones that are not supported by any of the attributes.
1744 for (const ParsedAttr
&Attribute
: Attrs
) {
1745 SmallVector
<std::pair
<attr::SubjectMatchRule
, bool>, 4> MatchRules
;
1746 Attribute
.getMatchRules(PRef
.getLangOpts(), MatchRules
);
1747 llvm::BitVector
IsSupported(attr::SubjectMatchRule_Last
+ 1);
1748 for (const auto &Rule
: MatchRules
) {
1749 // Ensure that the missing rule is reported in the fix-it only when it's
1750 // supported in the current language mode.
1753 IsSupported
[Rule
.first
] = true;
1755 IsMatchRuleAvailable
&= IsSupported
;
1757 if (IsMatchRuleAvailable
.count() == 0) {
1758 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1759 // placeholders will be supported by the fix-its.
1763 bool NeedsComma
= false;
1764 for (unsigned I
= 0; I
<= attr::SubjectMatchRule_Last
; I
++) {
1765 if (!IsMatchRuleAvailable
[I
])
1771 FixIt
+= attr::getSubjectMatchRuleSpelling(
1772 static_cast<attr::SubjectMatchRule
>(I
));
1775 // Check if we need to remove the range
1776 PRef
.SkipUntil(tok::eof
, Parser::StopBeforeMatch
);
1777 FixItRange
.setEnd(PRef
.getCurToken().getLocation());
1779 if (FixItRange
.getBegin() == FixItRange
.getEnd())
1780 Diagnostic
<< FixItHint::CreateInsertion(FixItRange
.getBegin(), FixIt
);
1782 Diagnostic
<< FixItHint::CreateReplacement(
1783 CharSourceRange::getCharRange(FixItRange
), FixIt
);
1787 } // end anonymous namespace
1789 void Parser::HandlePragmaAttribute() {
1790 assert(Tok
.is(tok::annot_pragma_attribute
) &&
1791 "Expected #pragma attribute annotation token");
1792 SourceLocation PragmaLoc
= Tok
.getLocation();
1793 auto *Info
= static_cast<PragmaAttributeInfo
*>(Tok
.getAnnotationValue());
1794 if (Info
->Action
== PragmaAttributeInfo::Pop
) {
1795 ConsumeAnnotationToken();
1796 Actions
.ActOnPragmaAttributePop(PragmaLoc
, Info
->Namespace
);
1799 // Parse the actual attribute with its arguments.
1800 assert((Info
->Action
== PragmaAttributeInfo::Push
||
1801 Info
->Action
== PragmaAttributeInfo::Attribute
) &&
1802 "Unexpected #pragma attribute command");
1804 if (Info
->Action
== PragmaAttributeInfo::Push
&& Info
->Tokens
.empty()) {
1805 ConsumeAnnotationToken();
1806 Actions
.ActOnPragmaAttributeEmptyPush(PragmaLoc
, Info
->Namespace
);
1810 PP
.EnterTokenStream(Info
->Tokens
, /*DisableMacroExpansion=*/false,
1811 /*IsReinject=*/false);
1812 ConsumeAnnotationToken();
1814 ParsedAttributes
&Attrs
= Info
->Attributes
;
1815 Attrs
.clearListOnly();
1817 auto SkipToEnd
= [this]() {
1818 SkipUntil(tok::eof
, StopBeforeMatch
);
1822 if ((Tok
.is(tok::l_square
) && NextToken().is(tok::l_square
)) ||
1823 Tok
.isRegularKeywordAttribute()) {
1824 // Parse the CXX11 style attribute.
1825 ParseCXX11AttributeSpecifier(Attrs
);
1826 } else if (Tok
.is(tok::kw___attribute
)) {
1828 if (ExpectAndConsume(tok::l_paren
, diag::err_expected_lparen_after
,
1831 if (ExpectAndConsume(tok::l_paren
, diag::err_expected_lparen_after
, "("))
1834 // FIXME: The practical usefulness of completion here is limited because
1835 // we only get here if the line has balanced parens.
1836 if (Tok
.is(tok::code_completion
)) {
1838 // FIXME: suppress completion of unsupported attributes?
1839 Actions
.CodeCompleteAttribute(AttributeCommonInfo::Syntax::AS_GNU
);
1843 // Parse the comma-separated list of attributes.
1845 if (Tok
.isNot(tok::identifier
)) {
1846 Diag(Tok
, diag::err_pragma_attribute_expected_attribute_name
);
1850 IdentifierInfo
*AttrName
= Tok
.getIdentifierInfo();
1851 SourceLocation AttrNameLoc
= ConsumeToken();
1853 if (Tok
.isNot(tok::l_paren
))
1854 Attrs
.addNew(AttrName
, AttrNameLoc
, nullptr, AttrNameLoc
, nullptr, 0,
1855 ParsedAttr::Form::GNU());
1857 ParseGNUAttributeArgs(AttrName
, AttrNameLoc
, Attrs
, /*EndLoc=*/nullptr,
1858 /*ScopeName=*/nullptr,
1859 /*ScopeLoc=*/SourceLocation(),
1860 ParsedAttr::Form::GNU(),
1861 /*Declarator=*/nullptr);
1862 } while (TryConsumeToken(tok::comma
));
1864 if (ExpectAndConsume(tok::r_paren
))
1866 if (ExpectAndConsume(tok::r_paren
))
1868 } else if (Tok
.is(tok::kw___declspec
)) {
1869 ParseMicrosoftDeclSpecs(Attrs
);
1871 Diag(Tok
, diag::err_pragma_attribute_expected_attribute_syntax
);
1872 if (Tok
.getIdentifierInfo()) {
1873 // If we suspect that this is an attribute suggest the use of
1875 if (ParsedAttr::getParsedKind(
1876 Tok
.getIdentifierInfo(), /*ScopeName=*/nullptr,
1877 ParsedAttr::AS_GNU
) != ParsedAttr::UnknownAttribute
) {
1878 SourceLocation InsertStartLoc
= Tok
.getLocation();
1880 if (Tok
.is(tok::l_paren
)) {
1882 SkipUntil(tok::r_paren
, StopBeforeMatch
);
1883 if (Tok
.isNot(tok::r_paren
))
1886 Diag(Tok
, diag::note_pragma_attribute_use_attribute_kw
)
1887 << FixItHint::CreateInsertion(InsertStartLoc
, "__attribute__((")
1888 << FixItHint::CreateInsertion(Tok
.getEndLoc(), "))");
1895 if (Attrs
.empty() || Attrs
.begin()->isInvalid()) {
1900 for (const ParsedAttr
&Attribute
: Attrs
) {
1901 if (!Attribute
.isSupportedByPragmaAttribute()) {
1902 Diag(PragmaLoc
, diag::err_pragma_attribute_unsupported_attribute
)
1909 // Parse the subject-list.
1910 if (!TryConsumeToken(tok::comma
)) {
1911 createExpectedAttributeSubjectRulesTokenDiagnostic(
1912 diag::err_expected
, Attrs
,
1913 MissingAttributeSubjectRulesRecoveryPoint::Comma
, *this)
1919 if (Tok
.isNot(tok::identifier
)) {
1920 createExpectedAttributeSubjectRulesTokenDiagnostic(
1921 diag::err_pragma_attribute_invalid_subject_set_specifier
, Attrs
,
1922 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo
, *this);
1926 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
1927 if (!II
->isStr("apply_to")) {
1928 createExpectedAttributeSubjectRulesTokenDiagnostic(
1929 diag::err_pragma_attribute_invalid_subject_set_specifier
, Attrs
,
1930 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo
, *this);
1936 if (!TryConsumeToken(tok::equal
)) {
1937 createExpectedAttributeSubjectRulesTokenDiagnostic(
1938 diag::err_expected
, Attrs
,
1939 MissingAttributeSubjectRulesRecoveryPoint::Equals
, *this)
1945 attr::ParsedSubjectMatchRuleSet SubjectMatchRules
;
1946 SourceLocation AnyLoc
, LastMatchRuleEndLoc
;
1947 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules
, AnyLoc
,
1948 LastMatchRuleEndLoc
)) {
1953 // Tokens following an ill-formed attribute will remain in the token stream
1954 // and must be removed.
1955 if (Tok
.isNot(tok::eof
)) {
1956 Diag(Tok
, diag::err_pragma_attribute_extra_tokens_after_attribute
);
1961 // Consume the eof terminator token.
1964 // Handle a mixed push/attribute by desurging to a push, then an attribute.
1965 if (Info
->Action
== PragmaAttributeInfo::Push
)
1966 Actions
.ActOnPragmaAttributeEmptyPush(PragmaLoc
, Info
->Namespace
);
1968 for (ParsedAttr
&Attribute
: Attrs
) {
1969 Actions
.ActOnPragmaAttributeAttribute(Attribute
, PragmaLoc
,
1974 // #pragma GCC visibility comes in two variants:
1975 // 'push' '(' [visibility] ')'
1977 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor
&PP
,
1978 PragmaIntroducer Introducer
,
1980 SourceLocation VisLoc
= VisTok
.getLocation();
1983 PP
.LexUnexpandedToken(Tok
);
1985 const IdentifierInfo
*PushPop
= Tok
.getIdentifierInfo();
1987 const IdentifierInfo
*VisType
;
1988 if (PushPop
&& PushPop
->isStr("pop")) {
1990 } else if (PushPop
&& PushPop
->isStr("push")) {
1991 PP
.LexUnexpandedToken(Tok
);
1992 if (Tok
.isNot(tok::l_paren
)) {
1993 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_lparen
)
1997 PP
.LexUnexpandedToken(Tok
);
1998 VisType
= Tok
.getIdentifierInfo();
2000 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_identifier
)
2004 PP
.LexUnexpandedToken(Tok
);
2005 if (Tok
.isNot(tok::r_paren
)) {
2006 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_rparen
)
2011 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_identifier
)
2015 SourceLocation EndLoc
= Tok
.getLocation();
2016 PP
.LexUnexpandedToken(Tok
);
2017 if (Tok
.isNot(tok::eod
)) {
2018 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
2023 auto Toks
= std::make_unique
<Token
[]>(1);
2024 Toks
[0].startToken();
2025 Toks
[0].setKind(tok::annot_pragma_vis
);
2026 Toks
[0].setLocation(VisLoc
);
2027 Toks
[0].setAnnotationEndLoc(EndLoc
);
2028 Toks
[0].setAnnotationValue(
2029 const_cast<void *>(static_cast<const void *>(VisType
)));
2030 PP
.EnterTokenStream(std::move(Toks
), 1, /*DisableMacroExpansion=*/true,
2031 /*IsReinject=*/false);
2034 // #pragma pack(...) comes in the following delicious flavors:
2035 // pack '(' [integer] ')'
2036 // pack '(' 'show' ')'
2037 // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
2038 void PragmaPackHandler::HandlePragma(Preprocessor
&PP
,
2039 PragmaIntroducer Introducer
,
2041 SourceLocation PackLoc
= PackTok
.getLocation();
2045 if (Tok
.isNot(tok::l_paren
)) {
2046 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_lparen
) << "pack";
2050 Sema::PragmaMsStackAction Action
= Sema::PSK_Reset
;
2051 StringRef SlotLabel
;
2053 Alignment
.startToken();
2055 if (Tok
.is(tok::numeric_constant
)) {
2060 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
2061 // the push/pop stack.
2062 // In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4)
2063 Action
= (PP
.getLangOpts().ApplePragmaPack
|| PP
.getLangOpts().XLPragmaPack
)
2064 ? Sema::PSK_Push_Set
2066 } else if (Tok
.is(tok::identifier
)) {
2067 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
2068 if (II
->isStr("show")) {
2069 Action
= Sema::PSK_Show
;
2072 if (II
->isStr("push")) {
2073 Action
= Sema::PSK_Push
;
2074 } else if (II
->isStr("pop")) {
2075 Action
= Sema::PSK_Pop
;
2077 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_invalid_action
) << "pack";
2082 if (Tok
.is(tok::comma
)) {
2085 if (Tok
.is(tok::numeric_constant
)) {
2086 Action
= (Sema::PragmaMsStackAction
)(Action
| Sema::PSK_Set
);
2090 } else if (Tok
.is(tok::identifier
)) {
2091 SlotLabel
= Tok
.getIdentifierInfo()->getName();
2094 if (Tok
.is(tok::comma
)) {
2097 if (Tok
.isNot(tok::numeric_constant
)) {
2098 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_pack_malformed
);
2102 Action
= (Sema::PragmaMsStackAction
)(Action
| Sema::PSK_Set
);
2108 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_pack_malformed
);
2113 } else if (PP
.getLangOpts().ApplePragmaPack
||
2114 PP
.getLangOpts().XLPragmaPack
) {
2115 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
2116 // the push/pop stack.
2117 // In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma
2119 Action
= Sema::PSK_Pop
;
2122 if (Tok
.isNot(tok::r_paren
)) {
2123 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_rparen
) << "pack";
2127 SourceLocation RParenLoc
= Tok
.getLocation();
2129 if (Tok
.isNot(tok::eod
)) {
2130 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
) << "pack";
2134 Sema::PragmaPackInfo
*Info
=
2135 PP
.getPreprocessorAllocator().Allocate
<Sema::PragmaPackInfo
>(1);
2136 Info
->Action
= Action
;
2137 Info
->SlotLabel
= SlotLabel
;
2138 Info
->Alignment
= Alignment
;
2140 MutableArrayRef
<Token
> Toks(PP
.getPreprocessorAllocator().Allocate
<Token
>(1),
2142 Toks
[0].startToken();
2143 Toks
[0].setKind(tok::annot_pragma_pack
);
2144 Toks
[0].setLocation(PackLoc
);
2145 Toks
[0].setAnnotationEndLoc(RParenLoc
);
2146 Toks
[0].setAnnotationValue(static_cast<void*>(Info
));
2147 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
2148 /*IsReinject=*/false);
2151 // #pragma ms_struct on
2152 // #pragma ms_struct off
2153 void PragmaMSStructHandler::HandlePragma(Preprocessor
&PP
,
2154 PragmaIntroducer Introducer
,
2155 Token
&MSStructTok
) {
2156 PragmaMSStructKind Kind
= PMSST_OFF
;
2160 if (Tok
.isNot(tok::identifier
)) {
2161 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_ms_struct
);
2164 SourceLocation EndLoc
= Tok
.getLocation();
2165 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
2166 if (II
->isStr("on")) {
2170 else if (II
->isStr("off") || II
->isStr("reset"))
2173 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_ms_struct
);
2177 if (Tok
.isNot(tok::eod
)) {
2178 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
2183 MutableArrayRef
<Token
> Toks(PP
.getPreprocessorAllocator().Allocate
<Token
>(1),
2185 Toks
[0].startToken();
2186 Toks
[0].setKind(tok::annot_pragma_msstruct
);
2187 Toks
[0].setLocation(MSStructTok
.getLocation());
2188 Toks
[0].setAnnotationEndLoc(EndLoc
);
2189 Toks
[0].setAnnotationValue(reinterpret_cast<void*>(
2190 static_cast<uintptr_t>(Kind
)));
2191 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
2192 /*IsReinject=*/false);
2195 // #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
2196 void PragmaClangSectionHandler::HandlePragma(Preprocessor
&PP
,
2197 PragmaIntroducer Introducer
,
2198 Token
&FirstToken
) {
2201 auto SecKind
= Sema::PragmaClangSectionKind::PCSK_Invalid
;
2203 PP
.Lex(Tok
); // eat 'section'
2204 while (Tok
.isNot(tok::eod
)) {
2205 if (Tok
.isNot(tok::identifier
)) {
2206 PP
.Diag(Tok
.getLocation(), diag::err_pragma_expected_clang_section_name
) << "clang section";
2210 const IdentifierInfo
*SecType
= Tok
.getIdentifierInfo();
2211 if (SecType
->isStr("bss"))
2212 SecKind
= Sema::PragmaClangSectionKind::PCSK_BSS
;
2213 else if (SecType
->isStr("data"))
2214 SecKind
= Sema::PragmaClangSectionKind::PCSK_Data
;
2215 else if (SecType
->isStr("rodata"))
2216 SecKind
= Sema::PragmaClangSectionKind::PCSK_Rodata
;
2217 else if (SecType
->isStr("relro"))
2218 SecKind
= Sema::PragmaClangSectionKind::PCSK_Relro
;
2219 else if (SecType
->isStr("text"))
2220 SecKind
= Sema::PragmaClangSectionKind::PCSK_Text
;
2222 PP
.Diag(Tok
.getLocation(), diag::err_pragma_expected_clang_section_name
) << "clang section";
2226 SourceLocation PragmaLocation
= Tok
.getLocation();
2227 PP
.Lex(Tok
); // eat ['bss'|'data'|'rodata'|'text']
2228 if (Tok
.isNot(tok::equal
)) {
2229 PP
.Diag(Tok
.getLocation(), diag::err_pragma_clang_section_expected_equal
) << SecKind
;
2233 std::string SecName
;
2234 if (!PP
.LexStringLiteral(Tok
, SecName
, "pragma clang section", false))
2237 Actions
.ActOnPragmaClangSection(
2239 (SecName
.size() ? Sema::PragmaClangSectionAction::PCSA_Set
2240 : Sema::PragmaClangSectionAction::PCSA_Clear
),
2245 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
2246 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
2247 // #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'
2248 static void ParseAlignPragma(Preprocessor
&PP
, Token
&FirstTok
,
2254 if (Tok
.isNot(tok::identifier
) ||
2255 !Tok
.getIdentifierInfo()->isStr("align")) {
2256 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_options_expected_align
);
2262 if (PP
.getLangOpts().XLPragmaPack
) {
2263 if (Tok
.isNot(tok::l_paren
)) {
2264 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_lparen
) << "align";
2267 } else if (Tok
.isNot(tok::equal
)) {
2268 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_align_expected_equal
)
2274 if (Tok
.isNot(tok::identifier
)) {
2275 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_identifier
)
2276 << (IsOptions
? "options" : "align");
2280 Sema::PragmaOptionsAlignKind Kind
= Sema::POAK_Natural
;
2281 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
2282 if (II
->isStr("native"))
2283 Kind
= Sema::POAK_Native
;
2284 else if (II
->isStr("natural"))
2285 Kind
= Sema::POAK_Natural
;
2286 else if (II
->isStr("packed"))
2287 Kind
= Sema::POAK_Packed
;
2288 else if (II
->isStr("power"))
2289 Kind
= Sema::POAK_Power
;
2290 else if (II
->isStr("mac68k"))
2291 Kind
= Sema::POAK_Mac68k
;
2292 else if (II
->isStr("reset"))
2293 Kind
= Sema::POAK_Reset
;
2295 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_align_invalid_option
)
2300 if (PP
.getLangOpts().XLPragmaPack
) {
2302 if (Tok
.isNot(tok::r_paren
)) {
2303 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_rparen
) << "align";
2308 SourceLocation EndLoc
= Tok
.getLocation();
2310 if (Tok
.isNot(tok::eod
)) {
2311 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
2312 << (IsOptions
? "options" : "align");
2316 MutableArrayRef
<Token
> Toks(PP
.getPreprocessorAllocator().Allocate
<Token
>(1),
2318 Toks
[0].startToken();
2319 Toks
[0].setKind(tok::annot_pragma_align
);
2320 Toks
[0].setLocation(FirstTok
.getLocation());
2321 Toks
[0].setAnnotationEndLoc(EndLoc
);
2322 Toks
[0].setAnnotationValue(reinterpret_cast<void*>(
2323 static_cast<uintptr_t>(Kind
)));
2324 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
2325 /*IsReinject=*/false);
2328 void PragmaAlignHandler::HandlePragma(Preprocessor
&PP
,
2329 PragmaIntroducer Introducer
,
2331 ParseAlignPragma(PP
, AlignTok
, /*IsOptions=*/false);
2334 void PragmaOptionsHandler::HandlePragma(Preprocessor
&PP
,
2335 PragmaIntroducer Introducer
,
2336 Token
&OptionsTok
) {
2337 ParseAlignPragma(PP
, OptionsTok
, /*IsOptions=*/true);
2340 // #pragma unused(identifier)
2341 void PragmaUnusedHandler::HandlePragma(Preprocessor
&PP
,
2342 PragmaIntroducer Introducer
,
2344 // FIXME: Should we be expanding macros here? My guess is no.
2345 SourceLocation UnusedLoc
= UnusedTok
.getLocation();
2347 // Lex the left '('.
2350 if (Tok
.isNot(tok::l_paren
)) {
2351 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_lparen
) << "unused";
2355 // Lex the declaration reference(s).
2356 SmallVector
<Token
, 5> Identifiers
;
2357 SourceLocation RParenLoc
;
2364 if (Tok
.is(tok::identifier
)) {
2365 Identifiers
.push_back(Tok
);
2371 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_unused_expected_var
);
2375 // We are execting a ')' or a ','.
2376 if (Tok
.is(tok::comma
)) {
2381 if (Tok
.is(tok::r_paren
)) {
2382 RParenLoc
= Tok
.getLocation();
2387 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_punc
) << "unused";
2392 if (Tok
.isNot(tok::eod
)) {
2393 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
) <<
2398 // Verify that we have a location for the right parenthesis.
2399 assert(RParenLoc
.isValid() && "Valid '#pragma unused' must have ')'");
2400 assert(!Identifiers
.empty() && "Valid '#pragma unused' must have arguments");
2402 // For each identifier token, insert into the token stream a
2403 // annot_pragma_unused token followed by the identifier token.
2404 // This allows us to cache a "#pragma unused" that occurs inside an inline
2405 // C++ member function.
2407 MutableArrayRef
<Token
> Toks(
2408 PP
.getPreprocessorAllocator().Allocate
<Token
>(2 * Identifiers
.size()),
2409 2 * Identifiers
.size());
2410 for (unsigned i
=0; i
!= Identifiers
.size(); i
++) {
2411 Token
&pragmaUnusedTok
= Toks
[2*i
], &idTok
= Toks
[2*i
+1];
2412 pragmaUnusedTok
.startToken();
2413 pragmaUnusedTok
.setKind(tok::annot_pragma_unused
);
2414 pragmaUnusedTok
.setLocation(UnusedLoc
);
2415 idTok
= Identifiers
[i
];
2417 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
2418 /*IsReinject=*/false);
2421 // #pragma weak identifier
2422 // #pragma weak identifier '=' identifier
2423 void PragmaWeakHandler::HandlePragma(Preprocessor
&PP
,
2424 PragmaIntroducer Introducer
,
2426 SourceLocation WeakLoc
= WeakTok
.getLocation();
2430 if (Tok
.isNot(tok::identifier
)) {
2431 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_identifier
) << "weak";
2435 Token WeakName
= Tok
;
2436 bool HasAlias
= false;
2440 if (Tok
.is(tok::equal
)) {
2443 if (Tok
.isNot(tok::identifier
)) {
2444 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_identifier
)
2452 if (Tok
.isNot(tok::eod
)) {
2453 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
) << "weak";
2458 MutableArrayRef
<Token
> Toks(
2459 PP
.getPreprocessorAllocator().Allocate
<Token
>(3), 3);
2460 Token
&pragmaUnusedTok
= Toks
[0];
2461 pragmaUnusedTok
.startToken();
2462 pragmaUnusedTok
.setKind(tok::annot_pragma_weakalias
);
2463 pragmaUnusedTok
.setLocation(WeakLoc
);
2464 pragmaUnusedTok
.setAnnotationEndLoc(AliasName
.getLocation());
2466 Toks
[2] = AliasName
;
2467 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
2468 /*IsReinject=*/false);
2470 MutableArrayRef
<Token
> Toks(
2471 PP
.getPreprocessorAllocator().Allocate
<Token
>(2), 2);
2472 Token
&pragmaUnusedTok
= Toks
[0];
2473 pragmaUnusedTok
.startToken();
2474 pragmaUnusedTok
.setKind(tok::annot_pragma_weak
);
2475 pragmaUnusedTok
.setLocation(WeakLoc
);
2476 pragmaUnusedTok
.setAnnotationEndLoc(WeakLoc
);
2478 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
2479 /*IsReinject=*/false);
2483 // #pragma redefine_extname identifier identifier
2484 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor
&PP
,
2485 PragmaIntroducer Introducer
,
2486 Token
&RedefToken
) {
2487 SourceLocation RedefLoc
= RedefToken
.getLocation();
2491 if (Tok
.isNot(tok::identifier
)) {
2492 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_identifier
) <<
2497 Token RedefName
= Tok
;
2500 if (Tok
.isNot(tok::identifier
)) {
2501 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_identifier
)
2502 << "redefine_extname";
2506 Token AliasName
= Tok
;
2509 if (Tok
.isNot(tok::eod
)) {
2510 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
) <<
2515 MutableArrayRef
<Token
> Toks(PP
.getPreprocessorAllocator().Allocate
<Token
>(3),
2517 Token
&pragmaRedefTok
= Toks
[0];
2518 pragmaRedefTok
.startToken();
2519 pragmaRedefTok
.setKind(tok::annot_pragma_redefine_extname
);
2520 pragmaRedefTok
.setLocation(RedefLoc
);
2521 pragmaRedefTok
.setAnnotationEndLoc(AliasName
.getLocation());
2522 Toks
[1] = RedefName
;
2523 Toks
[2] = AliasName
;
2524 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
2525 /*IsReinject=*/false);
2528 void PragmaFPContractHandler::HandlePragma(Preprocessor
&PP
,
2529 PragmaIntroducer Introducer
,
2531 tok::OnOffSwitch OOS
;
2532 if (PP
.LexOnOffSwitch(OOS
))
2535 MutableArrayRef
<Token
> Toks(PP
.getPreprocessorAllocator().Allocate
<Token
>(1),
2537 Toks
[0].startToken();
2538 Toks
[0].setKind(tok::annot_pragma_fp_contract
);
2539 Toks
[0].setLocation(Tok
.getLocation());
2540 Toks
[0].setAnnotationEndLoc(Tok
.getLocation());
2541 Toks
[0].setAnnotationValue(reinterpret_cast<void*>(
2542 static_cast<uintptr_t>(OOS
)));
2543 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
2544 /*IsReinject=*/false);
2547 void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor
&PP
,
2548 PragmaIntroducer Introducer
,
2550 PP
.LexUnexpandedToken(Tok
);
2551 if (Tok
.isNot(tok::identifier
)) {
2552 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_identifier
) <<
2556 IdentifierInfo
*Ext
= Tok
.getIdentifierInfo();
2557 SourceLocation NameLoc
= Tok
.getLocation();
2560 if (Tok
.isNot(tok::colon
)) {
2561 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_colon
) << Ext
;
2566 if (Tok
.isNot(tok::identifier
)) {
2567 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_predicate
) << 0;
2570 IdentifierInfo
*Pred
= Tok
.getIdentifierInfo();
2572 OpenCLExtState State
;
2573 if (Pred
->isStr("enable")) {
2575 } else if (Pred
->isStr("disable")) {
2577 } else if (Pred
->isStr("begin"))
2579 else if (Pred
->isStr("end"))
2582 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_predicate
)
2583 << Ext
->isStr("all");
2586 SourceLocation StateLoc
= Tok
.getLocation();
2589 if (Tok
.isNot(tok::eod
)) {
2590 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
) <<
2595 auto Info
= PP
.getPreprocessorAllocator().Allocate
<OpenCLExtData
>(1);
2597 Info
->second
= State
;
2598 MutableArrayRef
<Token
> Toks(PP
.getPreprocessorAllocator().Allocate
<Token
>(1),
2600 Toks
[0].startToken();
2601 Toks
[0].setKind(tok::annot_pragma_opencl_extension
);
2602 Toks
[0].setLocation(NameLoc
);
2603 Toks
[0].setAnnotationValue(static_cast<void*>(Info
));
2604 Toks
[0].setAnnotationEndLoc(StateLoc
);
2605 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
2606 /*IsReinject=*/false);
2608 if (PP
.getPPCallbacks())
2609 PP
.getPPCallbacks()->PragmaOpenCLExtension(NameLoc
, Ext
,
2613 /// Handle '#pragma omp ...' when OpenMP is disabled.
2615 void PragmaNoOpenMPHandler::HandlePragma(Preprocessor
&PP
,
2616 PragmaIntroducer Introducer
,
2618 if (!PP
.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored
,
2619 FirstTok
.getLocation())) {
2620 PP
.Diag(FirstTok
, diag::warn_pragma_omp_ignored
);
2621 PP
.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored
,
2622 diag::Severity::Ignored
, SourceLocation());
2624 PP
.DiscardUntilEndOfDirective();
2627 /// Handle '#pragma omp ...' when OpenMP is enabled.
2629 void PragmaOpenMPHandler::HandlePragma(Preprocessor
&PP
,
2630 PragmaIntroducer Introducer
,
2632 SmallVector
<Token
, 16> Pragma
;
2635 Tok
.setKind(tok::annot_pragma_openmp
);
2636 Tok
.setLocation(Introducer
.Loc
);
2638 while (Tok
.isNot(tok::eod
) && Tok
.isNot(tok::eof
)) {
2639 Pragma
.push_back(Tok
);
2641 if (Tok
.is(tok::annot_pragma_openmp
)) {
2642 PP
.Diag(Tok
, diag::err_omp_unexpected_directive
) << 0;
2643 unsigned InnerPragmaCnt
= 1;
2644 while (InnerPragmaCnt
!= 0) {
2646 if (Tok
.is(tok::annot_pragma_openmp
))
2648 else if (Tok
.is(tok::annot_pragma_openmp_end
))
2654 SourceLocation EodLoc
= Tok
.getLocation();
2656 Tok
.setKind(tok::annot_pragma_openmp_end
);
2657 Tok
.setLocation(EodLoc
);
2658 Pragma
.push_back(Tok
);
2660 auto Toks
= std::make_unique
<Token
[]>(Pragma
.size());
2661 std::copy(Pragma
.begin(), Pragma
.end(), Toks
.get());
2662 PP
.EnterTokenStream(std::move(Toks
), Pragma
.size(),
2663 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2666 /// Handle '#pragma pointers_to_members'
2667 // The grammar for this pragma is as follows:
2669 // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2671 // #pragma pointers_to_members '(' 'best_case' ')'
2672 // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2673 // #pragma pointers_to_members '(' inheritance-model ')'
2674 void PragmaMSPointersToMembers::HandlePragma(Preprocessor
&PP
,
2675 PragmaIntroducer Introducer
,
2677 SourceLocation PointersToMembersLoc
= Tok
.getLocation();
2679 if (Tok
.isNot(tok::l_paren
)) {
2680 PP
.Diag(PointersToMembersLoc
, diag::warn_pragma_expected_lparen
)
2681 << "pointers_to_members";
2685 const IdentifierInfo
*Arg
= Tok
.getIdentifierInfo();
2687 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_identifier
)
2688 << "pointers_to_members";
2693 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod
;
2694 if (Arg
->isStr("best_case")) {
2695 RepresentationMethod
= LangOptions::PPTMK_BestCase
;
2697 if (Arg
->isStr("full_generality")) {
2698 if (Tok
.is(tok::comma
)) {
2701 Arg
= Tok
.getIdentifierInfo();
2703 PP
.Diag(Tok
.getLocation(),
2704 diag::err_pragma_pointers_to_members_unknown_kind
)
2705 << Tok
.getKind() << /*OnlyInheritanceModels*/ 0;
2709 } else if (Tok
.is(tok::r_paren
)) {
2710 // #pragma pointers_to_members(full_generality) implicitly specifies
2711 // virtual_inheritance.
2713 RepresentationMethod
= LangOptions::PPTMK_FullGeneralityVirtualInheritance
;
2715 PP
.Diag(Tok
.getLocation(), diag::err_expected_punc
)
2716 << "full_generality";
2722 if (Arg
->isStr("single_inheritance")) {
2723 RepresentationMethod
=
2724 LangOptions::PPTMK_FullGeneralitySingleInheritance
;
2725 } else if (Arg
->isStr("multiple_inheritance")) {
2726 RepresentationMethod
=
2727 LangOptions::PPTMK_FullGeneralityMultipleInheritance
;
2728 } else if (Arg
->isStr("virtual_inheritance")) {
2729 RepresentationMethod
=
2730 LangOptions::PPTMK_FullGeneralityVirtualInheritance
;
2732 PP
.Diag(Tok
.getLocation(),
2733 diag::err_pragma_pointers_to_members_unknown_kind
)
2734 << Arg
<< /*HasPointerDeclaration*/ 1;
2740 if (Tok
.isNot(tok::r_paren
)) {
2741 PP
.Diag(Tok
.getLocation(), diag::err_expected_rparen_after
)
2742 << (Arg
? Arg
->getName() : "full_generality");
2746 SourceLocation EndLoc
= Tok
.getLocation();
2748 if (Tok
.isNot(tok::eod
)) {
2749 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
2750 << "pointers_to_members";
2755 AnnotTok
.startToken();
2756 AnnotTok
.setKind(tok::annot_pragma_ms_pointers_to_members
);
2757 AnnotTok
.setLocation(PointersToMembersLoc
);
2758 AnnotTok
.setAnnotationEndLoc(EndLoc
);
2759 AnnotTok
.setAnnotationValue(
2760 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod
)));
2761 PP
.EnterToken(AnnotTok
, /*IsReinject=*/true);
2764 /// Handle '#pragma vtordisp'
2765 // The grammar for this pragma is as follows:
2767 // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2769 // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2770 // #pragma vtordisp '(' 'pop' ')'
2771 // #pragma vtordisp '(' ')'
2772 void PragmaMSVtorDisp::HandlePragma(Preprocessor
&PP
,
2773 PragmaIntroducer Introducer
, Token
&Tok
) {
2774 SourceLocation VtorDispLoc
= Tok
.getLocation();
2776 if (Tok
.isNot(tok::l_paren
)) {
2777 PP
.Diag(VtorDispLoc
, diag::warn_pragma_expected_lparen
) << "vtordisp";
2782 Sema::PragmaMsStackAction Action
= Sema::PSK_Set
;
2783 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
2785 if (II
->isStr("push")) {
2786 // #pragma vtordisp(push, mode)
2788 if (Tok
.isNot(tok::comma
)) {
2789 PP
.Diag(VtorDispLoc
, diag::warn_pragma_expected_punc
) << "vtordisp";
2793 Action
= Sema::PSK_Push_Set
;
2794 // not push, could be on/off
2795 } else if (II
->isStr("pop")) {
2796 // #pragma vtordisp(pop)
2798 Action
= Sema::PSK_Pop
;
2800 // not push or pop, could be on/off
2802 if (Tok
.is(tok::r_paren
)) {
2803 // #pragma vtordisp()
2804 Action
= Sema::PSK_Reset
;
2810 if (Action
& Sema::PSK_Push
|| Action
& Sema::PSK_Set
) {
2811 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
2812 if (II
&& II
->isStr("off")) {
2815 } else if (II
&& II
->isStr("on")) {
2818 } else if (Tok
.is(tok::numeric_constant
) &&
2819 PP
.parseSimpleIntegerLiteral(Tok
, Value
)) {
2821 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_integer
)
2822 << 0 << 2 << "vtordisp";
2826 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_invalid_action
)
2832 // Finish the pragma: ')' $
2833 if (Tok
.isNot(tok::r_paren
)) {
2834 PP
.Diag(VtorDispLoc
, diag::warn_pragma_expected_rparen
) << "vtordisp";
2837 SourceLocation EndLoc
= Tok
.getLocation();
2839 if (Tok
.isNot(tok::eod
)) {
2840 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
2845 // Enter the annotation.
2847 AnnotTok
.startToken();
2848 AnnotTok
.setKind(tok::annot_pragma_ms_vtordisp
);
2849 AnnotTok
.setLocation(VtorDispLoc
);
2850 AnnotTok
.setAnnotationEndLoc(EndLoc
);
2851 AnnotTok
.setAnnotationValue(reinterpret_cast<void *>(
2852 static_cast<uintptr_t>((Action
<< 16) | (Value
& 0xFFFF))));
2853 PP
.EnterToken(AnnotTok
, /*IsReinject=*/false);
2856 /// Handle all MS pragmas. Simply forwards the tokens after inserting
2857 /// an annotation token.
2858 void PragmaMSPragma::HandlePragma(Preprocessor
&PP
,
2859 PragmaIntroducer Introducer
, Token
&Tok
) {
2860 Token EoF
, AnnotTok
;
2862 EoF
.setKind(tok::eof
);
2863 AnnotTok
.startToken();
2864 AnnotTok
.setKind(tok::annot_pragma_ms_pragma
);
2865 AnnotTok
.setLocation(Tok
.getLocation());
2866 AnnotTok
.setAnnotationEndLoc(Tok
.getLocation());
2867 SmallVector
<Token
, 8> TokenVector
;
2868 // Suck up all of the tokens before the eod.
2869 for (; Tok
.isNot(tok::eod
); PP
.Lex(Tok
)) {
2870 TokenVector
.push_back(Tok
);
2871 AnnotTok
.setAnnotationEndLoc(Tok
.getLocation());
2873 // Add a sentinel EoF token to the end of the list.
2874 TokenVector
.push_back(EoF
);
2875 // We must allocate this array with new because EnterTokenStream is going to
2877 markAsReinjectedForRelexing(TokenVector
);
2878 auto TokenArray
= std::make_unique
<Token
[]>(TokenVector
.size());
2879 std::copy(TokenVector
.begin(), TokenVector
.end(), TokenArray
.get());
2880 auto Value
= new (PP
.getPreprocessorAllocator())
2881 std::pair
<std::unique_ptr
<Token
[]>, size_t>(std::move(TokenArray
),
2882 TokenVector
.size());
2883 AnnotTok
.setAnnotationValue(Value
);
2884 PP
.EnterToken(AnnotTok
, /*IsReinject*/ false);
2887 /// Handle the \#pragma float_control extension.
2891 /// #pragma float_control(keyword[, setting] [,push])
2893 /// Where 'keyword' and 'setting' are identifiers.
2894 // 'keyword' can be: precise, except, push, pop
2895 // 'setting' can be: on, off
2896 /// The optional arguments 'setting' and 'push' are supported only
2897 /// when the keyword is 'precise' or 'except'.
2898 void PragmaFloatControlHandler::HandlePragma(Preprocessor
&PP
,
2899 PragmaIntroducer Introducer
,
2901 Sema::PragmaMsStackAction Action
= Sema::PSK_Set
;
2902 SourceLocation FloatControlLoc
= Tok
.getLocation();
2903 Token PragmaName
= Tok
;
2904 if (!PP
.getTargetInfo().hasStrictFP() && !PP
.getLangOpts().ExpStrictFP
) {
2905 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_fp_ignored
)
2906 << PragmaName
.getIdentifierInfo()->getName();
2910 if (Tok
.isNot(tok::l_paren
)) {
2911 PP
.Diag(FloatControlLoc
, diag::err_expected
) << tok::l_paren
;
2915 // Read the identifier.
2917 if (Tok
.isNot(tok::identifier
)) {
2918 PP
.Diag(Tok
.getLocation(), diag::err_pragma_float_control_malformed
);
2922 // Verify that this is one of the float control options.
2923 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
2924 PragmaFloatControlKind Kind
=
2925 llvm::StringSwitch
<PragmaFloatControlKind
>(II
->getName())
2926 .Case("precise", PFC_Precise
)
2927 .Case("except", PFC_Except
)
2928 .Case("push", PFC_Push
)
2929 .Case("pop", PFC_Pop
)
2930 .Default(PFC_Unknown
);
2931 PP
.Lex(Tok
); // the identifier
2932 if (Kind
== PFC_Unknown
) {
2933 PP
.Diag(Tok
.getLocation(), diag::err_pragma_float_control_malformed
);
2935 } else if (Kind
== PFC_Push
|| Kind
== PFC_Pop
) {
2936 if (Tok
.isNot(tok::r_paren
)) {
2937 PP
.Diag(Tok
.getLocation(), diag::err_pragma_float_control_malformed
);
2940 PP
.Lex(Tok
); // Eat the r_paren
2941 Action
= (Kind
== PFC_Pop
) ? Sema::PSK_Pop
: Sema::PSK_Push
;
2943 if (Tok
.is(tok::r_paren
))
2944 // Selecting Precise or Except
2945 PP
.Lex(Tok
); // the r_paren
2946 else if (Tok
.isNot(tok::comma
)) {
2947 PP
.Diag(Tok
.getLocation(), diag::err_pragma_float_control_malformed
);
2951 if (!Tok
.isAnyIdentifier()) {
2952 PP
.Diag(Tok
.getLocation(), diag::err_pragma_float_control_malformed
);
2955 StringRef PushOnOff
= Tok
.getIdentifierInfo()->getName();
2956 if (PushOnOff
== "on")
2957 // Kind is set correctly
2959 else if (PushOnOff
== "off") {
2960 if (Kind
== PFC_Precise
)
2961 Kind
= PFC_NoPrecise
;
2962 if (Kind
== PFC_Except
)
2963 Kind
= PFC_NoExcept
;
2964 } else if (PushOnOff
== "push") {
2965 Action
= Sema::PSK_Push_Set
;
2967 PP
.Diag(Tok
.getLocation(), diag::err_pragma_float_control_malformed
);
2970 PP
.Lex(Tok
); // the identifier
2971 if (Tok
.is(tok::comma
)) {
2973 if (!Tok
.isAnyIdentifier()) {
2974 PP
.Diag(Tok
.getLocation(), diag::err_pragma_float_control_malformed
);
2977 StringRef ExpectedPush
= Tok
.getIdentifierInfo()->getName();
2978 if (ExpectedPush
== "push") {
2979 Action
= Sema::PSK_Push_Set
;
2981 PP
.Diag(Tok
.getLocation(), diag::err_pragma_float_control_malformed
);
2984 PP
.Lex(Tok
); // the push identifier
2986 if (Tok
.isNot(tok::r_paren
)) {
2987 PP
.Diag(Tok
.getLocation(), diag::err_pragma_float_control_malformed
);
2990 PP
.Lex(Tok
); // the r_paren
2993 SourceLocation EndLoc
= Tok
.getLocation();
2994 if (Tok
.isNot(tok::eod
)) {
2995 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
3000 // Note: there is no accomodation for PP callback for this pragma.
3002 // Enter the annotation.
3003 auto TokenArray
= std::make_unique
<Token
[]>(1);
3004 TokenArray
[0].startToken();
3005 TokenArray
[0].setKind(tok::annot_pragma_float_control
);
3006 TokenArray
[0].setLocation(FloatControlLoc
);
3007 TokenArray
[0].setAnnotationEndLoc(EndLoc
);
3008 // Create an encoding of Action and Value by shifting the Action into
3009 // the high 16 bits then union with the Kind.
3010 TokenArray
[0].setAnnotationValue(reinterpret_cast<void *>(
3011 static_cast<uintptr_t>((Action
<< 16) | (Kind
& 0xFFFF))));
3012 PP
.EnterTokenStream(std::move(TokenArray
), 1,
3013 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3016 /// Handle the Microsoft \#pragma detect_mismatch extension.
3020 /// #pragma detect_mismatch("name", "value")
3022 /// Where 'name' and 'value' are quoted strings. The values are embedded in
3023 /// the object file and passed along to the linker. If the linker detects a
3024 /// mismatch in the object file's values for the given name, a LNK2038 error
3025 /// is emitted. See MSDN for more details.
3026 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor
&PP
,
3027 PragmaIntroducer Introducer
,
3029 SourceLocation DetectMismatchLoc
= Tok
.getLocation();
3031 if (Tok
.isNot(tok::l_paren
)) {
3032 PP
.Diag(DetectMismatchLoc
, diag::err_expected
) << tok::l_paren
;
3036 // Read the name to embed, which must be a string literal.
3037 std::string NameString
;
3038 if (!PP
.LexStringLiteral(Tok
, NameString
,
3039 "pragma detect_mismatch",
3040 /*AllowMacroExpansion=*/true))
3043 // Read the comma followed by a second string literal.
3044 std::string ValueString
;
3045 if (Tok
.isNot(tok::comma
)) {
3046 PP
.Diag(Tok
.getLocation(), diag::err_pragma_detect_mismatch_malformed
);
3050 if (!PP
.LexStringLiteral(Tok
, ValueString
, "pragma detect_mismatch",
3051 /*AllowMacroExpansion=*/true))
3054 if (Tok
.isNot(tok::r_paren
)) {
3055 PP
.Diag(Tok
.getLocation(), diag::err_expected
) << tok::r_paren
;
3058 PP
.Lex(Tok
); // Eat the r_paren.
3060 if (Tok
.isNot(tok::eod
)) {
3061 PP
.Diag(Tok
.getLocation(), diag::err_pragma_detect_mismatch_malformed
);
3065 // If the pragma is lexically sound, notify any interested PPCallbacks.
3066 if (PP
.getPPCallbacks())
3067 PP
.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc
, NameString
,
3070 Actions
.ActOnPragmaDetectMismatch(DetectMismatchLoc
, NameString
, ValueString
);
3073 /// Handle the microsoft \#pragma comment extension.
3077 /// #pragma comment(linker, "foo")
3079 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
3080 /// "foo" is a string, which is fully macro expanded, and permits string
3081 /// concatenation, embedded escape characters etc. See MSDN for more details.
3082 void PragmaCommentHandler::HandlePragma(Preprocessor
&PP
,
3083 PragmaIntroducer Introducer
,
3085 SourceLocation CommentLoc
= Tok
.getLocation();
3087 if (Tok
.isNot(tok::l_paren
)) {
3088 PP
.Diag(CommentLoc
, diag::err_pragma_comment_malformed
);
3092 // Read the identifier.
3094 if (Tok
.isNot(tok::identifier
)) {
3095 PP
.Diag(CommentLoc
, diag::err_pragma_comment_malformed
);
3099 // Verify that this is one of the 5 explicitly listed options.
3100 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
3101 PragmaMSCommentKind Kind
=
3102 llvm::StringSwitch
<PragmaMSCommentKind
>(II
->getName())
3103 .Case("linker", PCK_Linker
)
3104 .Case("lib", PCK_Lib
)
3105 .Case("compiler", PCK_Compiler
)
3106 .Case("exestr", PCK_ExeStr
)
3107 .Case("user", PCK_User
)
3108 .Default(PCK_Unknown
);
3109 if (Kind
== PCK_Unknown
) {
3110 PP
.Diag(Tok
.getLocation(), diag::err_pragma_comment_unknown_kind
);
3114 if (PP
.getTargetInfo().getTriple().isOSBinFormatELF() && Kind
!= PCK_Lib
) {
3115 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_comment_ignored
)
3120 // Read the optional string if present.
3122 std::string ArgumentString
;
3123 if (Tok
.is(tok::comma
) && !PP
.LexStringLiteral(Tok
, ArgumentString
,
3125 /*AllowMacroExpansion=*/true))
3128 // FIXME: warn that 'exestr' is deprecated.
3129 // FIXME: If the kind is "compiler" warn if the string is present (it is
3131 // The MSDN docs say that "lib" and "linker" require a string and have a short
3132 // list of linker options they support, but in practice MSVC doesn't
3133 // issue a diagnostic. Therefore neither does clang.
3135 if (Tok
.isNot(tok::r_paren
)) {
3136 PP
.Diag(Tok
.getLocation(), diag::err_pragma_comment_malformed
);
3139 PP
.Lex(Tok
); // eat the r_paren.
3141 if (Tok
.isNot(tok::eod
)) {
3142 PP
.Diag(Tok
.getLocation(), diag::err_pragma_comment_malformed
);
3146 // If the pragma is lexically sound, notify any interested PPCallbacks.
3147 if (PP
.getPPCallbacks())
3148 PP
.getPPCallbacks()->PragmaComment(CommentLoc
, II
, ArgumentString
);
3150 Actions
.ActOnPragmaMSComment(CommentLoc
, Kind
, ArgumentString
);
3153 // #pragma clang optimize off
3154 // #pragma clang optimize on
3155 void PragmaOptimizeHandler::HandlePragma(Preprocessor
&PP
,
3156 PragmaIntroducer Introducer
,
3157 Token
&FirstToken
) {
3160 if (Tok
.is(tok::eod
)) {
3161 PP
.Diag(Tok
.getLocation(), diag::err_pragma_missing_argument
)
3162 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
3165 if (Tok
.isNot(tok::identifier
)) {
3166 PP
.Diag(Tok
.getLocation(), diag::err_pragma_optimize_invalid_argument
)
3167 << PP
.getSpelling(Tok
);
3170 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
3171 // The only accepted values are 'on' or 'off'.
3173 if (II
->isStr("on")) {
3175 } else if (!II
->isStr("off")) {
3176 PP
.Diag(Tok
.getLocation(), diag::err_pragma_optimize_invalid_argument
)
3177 << PP
.getSpelling(Tok
);
3182 if (Tok
.isNot(tok::eod
)) {
3183 PP
.Diag(Tok
.getLocation(), diag::err_pragma_optimize_extra_argument
)
3184 << PP
.getSpelling(Tok
);
3188 Actions
.ActOnPragmaOptimize(IsOn
, FirstToken
.getLocation());
3192 /// Used as the annotation value for tok::annot_pragma_fp.
3193 struct TokFPAnnotValue
{
3194 enum FlagKinds
{ Contract
, Reassociate
, Exceptions
, EvalMethod
};
3195 enum FlagValues
{ On
, Off
, Fast
};
3197 std::optional
<LangOptions::FPModeKind
> ContractValue
;
3198 std::optional
<LangOptions::FPModeKind
> ReassociateValue
;
3199 std::optional
<LangOptions::FPExceptionModeKind
> ExceptionsValue
;
3200 std::optional
<LangOptions::FPEvalMethodKind
> EvalMethodValue
;
3202 } // end anonymous namespace
3204 void PragmaFPHandler::HandlePragma(Preprocessor
&PP
,
3205 PragmaIntroducer Introducer
, Token
&Tok
) {
3207 Token PragmaName
= Tok
;
3208 SmallVector
<Token
, 1> TokenList
;
3211 if (Tok
.isNot(tok::identifier
)) {
3212 PP
.Diag(Tok
.getLocation(), diag::err_pragma_fp_invalid_option
)
3213 << /*MissingOption=*/true << "";
3217 auto *AnnotValue
= new (PP
.getPreprocessorAllocator()) TokFPAnnotValue
;
3218 while (Tok
.is(tok::identifier
)) {
3219 IdentifierInfo
*OptionInfo
= Tok
.getIdentifierInfo();
3222 llvm::StringSwitch
<std::optional
<TokFPAnnotValue::FlagKinds
>>(
3223 OptionInfo
->getName())
3224 .Case("contract", TokFPAnnotValue::Contract
)
3225 .Case("reassociate", TokFPAnnotValue::Reassociate
)
3226 .Case("exceptions", TokFPAnnotValue::Exceptions
)
3227 .Case("eval_method", TokFPAnnotValue::EvalMethod
)
3228 .Default(std::nullopt
);
3230 PP
.Diag(Tok
.getLocation(), diag::err_pragma_fp_invalid_option
)
3231 << /*MissingOption=*/false << OptionInfo
;
3237 if (Tok
.isNot(tok::l_paren
)) {
3238 PP
.Diag(Tok
.getLocation(), diag::err_expected
) << tok::l_paren
;
3242 bool isEvalMethodDouble
=
3243 Tok
.is(tok::kw_double
) && FlagKind
== TokFPAnnotValue::EvalMethod
;
3245 // Don't diagnose if we have an eval_metod pragma with "double" kind.
3246 if (Tok
.isNot(tok::identifier
) && !isEvalMethodDouble
) {
3247 PP
.Diag(Tok
.getLocation(), diag::err_pragma_fp_invalid_argument
)
3248 << PP
.getSpelling(Tok
) << OptionInfo
->getName()
3249 << static_cast<int>(*FlagKind
);
3252 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
3254 if (FlagKind
== TokFPAnnotValue::Contract
) {
3255 AnnotValue
->ContractValue
=
3256 llvm::StringSwitch
<std::optional
<LangOptions::FPModeKind
>>(
3258 .Case("on", LangOptions::FPModeKind::FPM_On
)
3259 .Case("off", LangOptions::FPModeKind::FPM_Off
)
3260 .Case("fast", LangOptions::FPModeKind::FPM_Fast
)
3261 .Default(std::nullopt
);
3262 if (!AnnotValue
->ContractValue
) {
3263 PP
.Diag(Tok
.getLocation(), diag::err_pragma_fp_invalid_argument
)
3264 << PP
.getSpelling(Tok
) << OptionInfo
->getName() << *FlagKind
;
3267 } else if (FlagKind
== TokFPAnnotValue::Reassociate
) {
3268 AnnotValue
->ReassociateValue
=
3269 llvm::StringSwitch
<std::optional
<LangOptions::FPModeKind
>>(
3271 .Case("on", LangOptions::FPModeKind::FPM_On
)
3272 .Case("off", LangOptions::FPModeKind::FPM_Off
)
3273 .Default(std::nullopt
);
3274 if (!AnnotValue
->ReassociateValue
) {
3275 PP
.Diag(Tok
.getLocation(), diag::err_pragma_fp_invalid_argument
)
3276 << PP
.getSpelling(Tok
) << OptionInfo
->getName() << *FlagKind
;
3279 } else if (FlagKind
== TokFPAnnotValue::Exceptions
) {
3280 AnnotValue
->ExceptionsValue
=
3281 llvm::StringSwitch
<std::optional
<LangOptions::FPExceptionModeKind
>>(
3283 .Case("ignore", LangOptions::FPE_Ignore
)
3284 .Case("maytrap", LangOptions::FPE_MayTrap
)
3285 .Case("strict", LangOptions::FPE_Strict
)
3286 .Default(std::nullopt
);
3287 if (!AnnotValue
->ExceptionsValue
) {
3288 PP
.Diag(Tok
.getLocation(), diag::err_pragma_fp_invalid_argument
)
3289 << PP
.getSpelling(Tok
) << OptionInfo
->getName() << *FlagKind
;
3292 } else if (FlagKind
== TokFPAnnotValue::EvalMethod
) {
3293 AnnotValue
->EvalMethodValue
=
3294 llvm::StringSwitch
<std::optional
<LangOptions::FPEvalMethodKind
>>(
3296 .Case("source", LangOptions::FPEvalMethodKind::FEM_Source
)
3297 .Case("double", LangOptions::FPEvalMethodKind::FEM_Double
)
3298 .Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended
)
3299 .Default(std::nullopt
);
3300 if (!AnnotValue
->EvalMethodValue
) {
3301 PP
.Diag(Tok
.getLocation(), diag::err_pragma_fp_invalid_argument
)
3302 << PP
.getSpelling(Tok
) << OptionInfo
->getName() << *FlagKind
;
3309 if (Tok
.isNot(tok::r_paren
)) {
3310 PP
.Diag(Tok
.getLocation(), diag::err_expected
) << tok::r_paren
;
3316 if (Tok
.isNot(tok::eod
)) {
3317 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
3324 FPTok
.setKind(tok::annot_pragma_fp
);
3325 FPTok
.setLocation(PragmaName
.getLocation());
3326 FPTok
.setAnnotationEndLoc(PragmaName
.getLocation());
3327 FPTok
.setAnnotationValue(reinterpret_cast<void *>(AnnotValue
));
3328 TokenList
.push_back(FPTok
);
3330 auto TokenArray
= std::make_unique
<Token
[]>(TokenList
.size());
3331 std::copy(TokenList
.begin(), TokenList
.end(), TokenArray
.get());
3333 PP
.EnterTokenStream(std::move(TokenArray
), TokenList
.size(),
3334 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3337 void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor
&PP
,
3338 PragmaIntroducer Introducer
,
3340 Token PragmaName
= Tok
;
3341 SmallVector
<Token
, 1> TokenList
;
3342 if (!PP
.getTargetInfo().hasStrictFP() && !PP
.getLangOpts().ExpStrictFP
) {
3343 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_fp_ignored
)
3344 << PragmaName
.getIdentifierInfo()->getName();
3349 if (Tok
.isNot(tok::identifier
)) {
3350 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_identifier
)
3351 << PragmaName
.getIdentifierInfo()->getName();
3354 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
3357 llvm::StringSwitch
<llvm::RoundingMode
>(II
->getName())
3358 .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero
)
3359 .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven
)
3360 .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive
)
3361 .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative
)
3362 .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway
)
3363 .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic
)
3364 .Default(llvm::RoundingMode::Invalid
);
3365 if (RM
== llvm::RoundingMode::Invalid
) {
3366 PP
.Diag(Tok
.getLocation(), diag::warn_stdc_unknown_rounding_mode
);
3371 if (Tok
.isNot(tok::eod
)) {
3372 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
3373 << "STDC FENV_ROUND";
3377 // Until the pragma is fully implemented, issue a warning.
3378 PP
.Diag(Tok
.getLocation(), diag::warn_stdc_fenv_round_not_supported
);
3380 MutableArrayRef
<Token
> Toks(PP
.getPreprocessorAllocator().Allocate
<Token
>(1),
3382 Toks
[0].startToken();
3383 Toks
[0].setKind(tok::annot_pragma_fenv_round
);
3384 Toks
[0].setLocation(Tok
.getLocation());
3385 Toks
[0].setAnnotationEndLoc(Tok
.getLocation());
3386 Toks
[0].setAnnotationValue(
3387 reinterpret_cast<void *>(static_cast<uintptr_t>(RM
)));
3388 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
3389 /*IsReinject=*/false);
3392 void Parser::HandlePragmaFP() {
3393 assert(Tok
.is(tok::annot_pragma_fp
));
3395 reinterpret_cast<TokFPAnnotValue
*>(Tok
.getAnnotationValue());
3397 if (AnnotValue
->ReassociateValue
)
3398 Actions
.ActOnPragmaFPReassociate(Tok
.getLocation(),
3399 *AnnotValue
->ReassociateValue
==
3400 LangOptions::FPModeKind::FPM_On
);
3401 if (AnnotValue
->ContractValue
)
3402 Actions
.ActOnPragmaFPContract(Tok
.getLocation(),
3403 *AnnotValue
->ContractValue
);
3404 if (AnnotValue
->ExceptionsValue
)
3405 Actions
.ActOnPragmaFPExceptions(Tok
.getLocation(),
3406 *AnnotValue
->ExceptionsValue
);
3407 if (AnnotValue
->EvalMethodValue
)
3408 Actions
.ActOnPragmaFPEvalMethod(Tok
.getLocation(),
3409 *AnnotValue
->EvalMethodValue
);
3410 ConsumeAnnotationToken();
3413 /// Parses loop or unroll pragma hint value and fills in Info.
3414 static bool ParseLoopHintValue(Preprocessor
&PP
, Token
&Tok
, Token PragmaName
,
3415 Token Option
, bool ValueInParens
,
3416 PragmaLoopHintInfo
&Info
) {
3417 SmallVector
<Token
, 1> ValueList
;
3418 int OpenParens
= ValueInParens
? 1 : 0;
3419 // Read constant expression.
3420 while (Tok
.isNot(tok::eod
)) {
3421 if (Tok
.is(tok::l_paren
))
3423 else if (Tok
.is(tok::r_paren
)) {
3425 if (OpenParens
== 0 && ValueInParens
)
3429 ValueList
.push_back(Tok
);
3433 if (ValueInParens
) {
3435 if (Tok
.isNot(tok::r_paren
)) {
3436 PP
.Diag(Tok
.getLocation(), diag::err_expected
) << tok::r_paren
;
3443 EOFTok
.startToken();
3444 EOFTok
.setKind(tok::eof
);
3445 EOFTok
.setLocation(Tok
.getLocation());
3446 ValueList
.push_back(EOFTok
); // Terminates expression for parsing.
3448 markAsReinjectedForRelexing(ValueList
);
3449 Info
.Toks
= llvm::ArrayRef(ValueList
).copy(PP
.getPreprocessorAllocator());
3451 Info
.PragmaName
= PragmaName
;
3452 Info
.Option
= Option
;
3456 /// Handle the \#pragma clang loop directive.
3457 /// #pragma clang 'loop' loop-hints
3460 /// loop-hint loop-hints[opt]
3463 /// 'vectorize' '(' loop-hint-keyword ')'
3464 /// 'interleave' '(' loop-hint-keyword ')'
3465 /// 'unroll' '(' unroll-hint-keyword ')'
3466 /// 'vectorize_predicate' '(' loop-hint-keyword ')'
3467 /// 'vectorize_width' '(' loop-hint-value ')'
3468 /// 'interleave_count' '(' loop-hint-value ')'
3469 /// 'unroll_count' '(' loop-hint-value ')'
3470 /// 'pipeline' '(' disable ')'
3471 /// 'pipeline_initiation_interval' '(' loop-hint-value ')'
3473 /// loop-hint-keyword:
3478 /// unroll-hint-keyword:
3483 /// loop-hint-value:
3484 /// constant-expression
3486 /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
3487 /// try vectorizing the instructions of the loop it precedes. Specifying
3488 /// interleave(enable) or interleave_count(_value_) instructs llvm to try
3489 /// interleaving multiple iterations of the loop it precedes. The width of the
3490 /// vector instructions is specified by vectorize_width() and the number of
3491 /// interleaved loop iterations is specified by interleave_count(). Specifying a
3492 /// value of 1 effectively disables vectorization/interleaving, even if it is
3493 /// possible and profitable, and 0 is invalid. The loop vectorizer currently
3494 /// only works on inner loops.
3496 /// The unroll and unroll_count directives control the concatenation
3497 /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
3498 /// completely if the trip count is known at compile time and unroll partially
3499 /// if the trip count is not known. Specifying unroll(full) is similar to
3500 /// unroll(enable) but will unroll the loop only if the trip count is known at
3501 /// compile time. Specifying unroll(disable) disables unrolling for the
3502 /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
3503 /// loop the number of times indicated by the value.
3504 void PragmaLoopHintHandler::HandlePragma(Preprocessor
&PP
,
3505 PragmaIntroducer Introducer
,
3507 // Incoming token is "loop" from "#pragma clang loop".
3508 Token PragmaName
= Tok
;
3509 SmallVector
<Token
, 1> TokenList
;
3511 // Lex the optimization option and verify it is an identifier.
3513 if (Tok
.isNot(tok::identifier
)) {
3514 PP
.Diag(Tok
.getLocation(), diag::err_pragma_loop_invalid_option
)
3515 << /*MissingOption=*/true << "";
3519 while (Tok
.is(tok::identifier
)) {
3521 IdentifierInfo
*OptionInfo
= Tok
.getIdentifierInfo();
3523 bool OptionValid
= llvm::StringSwitch
<bool>(OptionInfo
->getName())
3524 .Case("vectorize", true)
3525 .Case("interleave", true)
3526 .Case("unroll", true)
3527 .Case("distribute", true)
3528 .Case("vectorize_predicate", true)
3529 .Case("vectorize_width", true)
3530 .Case("interleave_count", true)
3531 .Case("unroll_count", true)
3532 .Case("pipeline", true)
3533 .Case("pipeline_initiation_interval", true)
3536 PP
.Diag(Tok
.getLocation(), diag::err_pragma_loop_invalid_option
)
3537 << /*MissingOption=*/false << OptionInfo
;
3543 if (Tok
.isNot(tok::l_paren
)) {
3544 PP
.Diag(Tok
.getLocation(), diag::err_expected
) << tok::l_paren
;
3549 auto *Info
= new (PP
.getPreprocessorAllocator()) PragmaLoopHintInfo
;
3550 if (ParseLoopHintValue(PP
, Tok
, PragmaName
, Option
, /*ValueInParens=*/true,
3554 // Generate the loop hint token.
3556 LoopHintTok
.startToken();
3557 LoopHintTok
.setKind(tok::annot_pragma_loop_hint
);
3558 LoopHintTok
.setLocation(Introducer
.Loc
);
3559 LoopHintTok
.setAnnotationEndLoc(PragmaName
.getLocation());
3560 LoopHintTok
.setAnnotationValue(static_cast<void *>(Info
));
3561 TokenList
.push_back(LoopHintTok
);
3564 if (Tok
.isNot(tok::eod
)) {
3565 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
3570 auto TokenArray
= std::make_unique
<Token
[]>(TokenList
.size());
3571 std::copy(TokenList
.begin(), TokenList
.end(), TokenArray
.get());
3573 PP
.EnterTokenStream(std::move(TokenArray
), TokenList
.size(),
3574 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3577 /// Handle the loop unroll optimization pragmas.
3579 /// #pragma unroll unroll-hint-value
3580 /// #pragma unroll '(' unroll-hint-value ')'
3581 /// #pragma nounroll
3582 /// #pragma unroll_and_jam
3583 /// #pragma unroll_and_jam unroll-hint-value
3584 /// #pragma unroll_and_jam '(' unroll-hint-value ')'
3585 /// #pragma nounroll_and_jam
3587 /// unroll-hint-value:
3588 /// constant-expression
3590 /// Loop unrolling hints can be specified with '#pragma unroll' or
3591 /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
3592 /// contained in parentheses. With no argument the directive instructs llvm to
3593 /// try to unroll the loop completely. A positive integer argument can be
3594 /// specified to indicate the number of times the loop should be unrolled. To
3595 /// maximize compatibility with other compilers the unroll count argument can be
3596 /// specified with or without parentheses. Specifying, '#pragma nounroll'
3597 /// disables unrolling of the loop.
3598 void PragmaUnrollHintHandler::HandlePragma(Preprocessor
&PP
,
3599 PragmaIntroducer Introducer
,
3601 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
3602 // "#pragma nounroll".
3603 Token PragmaName
= Tok
;
3605 auto *Info
= new (PP
.getPreprocessorAllocator()) PragmaLoopHintInfo
;
3606 if (Tok
.is(tok::eod
)) {
3607 // nounroll or unroll pragma without an argument.
3608 Info
->PragmaName
= PragmaName
;
3609 Info
->Option
.startToken();
3610 } else if (PragmaName
.getIdentifierInfo()->getName() == "nounroll" ||
3611 PragmaName
.getIdentifierInfo()->getName() == "nounroll_and_jam") {
3612 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
3613 << PragmaName
.getIdentifierInfo()->getName();
3616 // Unroll pragma with an argument: "#pragma unroll N" or
3617 // "#pragma unroll(N)".
3618 // Read '(' if it exists.
3619 bool ValueInParens
= Tok
.is(tok::l_paren
);
3624 Option
.startToken();
3625 if (ParseLoopHintValue(PP
, Tok
, PragmaName
, Option
, ValueInParens
, *Info
))
3628 // In CUDA, the argument to '#pragma unroll' should not be contained in
3630 if (PP
.getLangOpts().CUDA
&& ValueInParens
)
3631 PP
.Diag(Info
->Toks
[0].getLocation(),
3632 diag::warn_pragma_unroll_cuda_value_in_parens
);
3634 if (Tok
.isNot(tok::eod
)) {
3635 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
3641 // Generate the hint token.
3642 auto TokenArray
= std::make_unique
<Token
[]>(1);
3643 TokenArray
[0].startToken();
3644 TokenArray
[0].setKind(tok::annot_pragma_loop_hint
);
3645 TokenArray
[0].setLocation(Introducer
.Loc
);
3646 TokenArray
[0].setAnnotationEndLoc(PragmaName
.getLocation());
3647 TokenArray
[0].setAnnotationValue(static_cast<void *>(Info
));
3648 PP
.EnterTokenStream(std::move(TokenArray
), 1,
3649 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3652 /// Handle the Microsoft \#pragma intrinsic extension.
3656 /// #pragma intrinsic(memset)
3657 /// #pragma intrinsic(strlen, memcpy)
3660 /// Pragma intrisic tells the compiler to use a builtin version of the
3661 /// function. Clang does it anyway, so the pragma doesn't really do anything.
3662 /// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3663 /// isn't an intrinsic in clang and suggest to include intrin.h.
3664 void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor
&PP
,
3665 PragmaIntroducer Introducer
,
3669 if (Tok
.isNot(tok::l_paren
)) {
3670 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_lparen
)
3676 bool SuggestIntrinH
= !PP
.isMacroDefined("__INTRIN_H");
3678 while (Tok
.is(tok::identifier
)) {
3679 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
3680 if (!II
->getBuiltinID())
3681 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_intrinsic_builtin
)
3682 << II
<< SuggestIntrinH
;
3685 if (Tok
.isNot(tok::comma
))
3690 if (Tok
.isNot(tok::r_paren
)) {
3691 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_expected_rparen
)
3697 if (Tok
.isNot(tok::eod
))
3698 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
3702 bool Parser::HandlePragmaMSFunction(StringRef PragmaName
,
3703 SourceLocation PragmaLocation
) {
3704 Token FirstTok
= Tok
;
3706 if (ExpectAndConsume(tok::l_paren
, diag::warn_pragma_expected_lparen
,
3710 bool SuggestIntrinH
= !PP
.isMacroDefined("__INTRIN_H");
3712 llvm::SmallVector
<StringRef
> NoBuiltins
;
3713 while (Tok
.is(tok::identifier
)) {
3714 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
3715 if (!II
->getBuiltinID())
3716 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_intrinsic_builtin
)
3717 << II
<< SuggestIntrinH
;
3719 NoBuiltins
.emplace_back(II
->getName());
3722 if (Tok
.isNot(tok::comma
))
3727 if (ExpectAndConsume(tok::r_paren
, diag::warn_pragma_expected_rparen
,
3729 ExpectAndConsume(tok::eof
, diag::warn_pragma_extra_tokens_at_eol
,
3733 Actions
.ActOnPragmaMSFunction(FirstTok
.getLocation(), NoBuiltins
);
3737 // #pragma optimize("gsty", on|off)
3738 bool Parser::HandlePragmaMSOptimize(StringRef PragmaName
,
3739 SourceLocation PragmaLocation
) {
3740 Token FirstTok
= Tok
;
3741 if (ExpectAndConsume(tok::l_paren
, diag::warn_pragma_expected_lparen
,
3745 if (Tok
.isNot(tok::string_literal
)) {
3746 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_string
) << PragmaName
;
3749 ExprResult StringResult
= ParseStringLiteralExpression();
3750 if (StringResult
.isInvalid())
3751 return false; // Already diagnosed.
3752 StringLiteral
*OptimizationList
= cast
<StringLiteral
>(StringResult
.get());
3753 if (OptimizationList
->getCharByteWidth() != 1) {
3754 PP
.Diag(PragmaLocation
, diag::warn_pragma_expected_non_wide_string
)
3759 if (ExpectAndConsume(tok::comma
, diag::warn_pragma_expected_comma
,
3763 if (Tok
.is(tok::eof
) || Tok
.is(tok::r_paren
)) {
3764 PP
.Diag(PragmaLocation
, diag::warn_pragma_missing_argument
)
3765 << PragmaName
<< /*Expected=*/true << "'on' or 'off'";
3768 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
3769 if (!II
|| (!II
->isStr("on") && !II
->isStr("off"))) {
3770 PP
.Diag(PragmaLocation
, diag::warn_pragma_invalid_argument
)
3771 << PP
.getSpelling(Tok
) << PragmaName
<< /*Expected=*/true
3775 bool IsOn
= II
->isStr("on");
3778 if (ExpectAndConsume(tok::r_paren
, diag::warn_pragma_expected_rparen
,
3782 // TODO: Add support for "sgty"
3783 if (!OptimizationList
->getString().empty()) {
3784 PP
.Diag(PragmaLocation
, diag::warn_pragma_invalid_argument
)
3785 << OptimizationList
->getString() << PragmaName
<< /*Expected=*/true
3790 if (ExpectAndConsume(tok::eof
, diag::warn_pragma_extra_tokens_at_eol
,
3794 Actions
.ActOnPragmaMSOptimize(FirstTok
.getLocation(), IsOn
);
3798 void PragmaForceCUDAHostDeviceHandler::HandlePragma(
3799 Preprocessor
&PP
, PragmaIntroducer Introducer
, Token
&Tok
) {
3800 Token FirstTok
= Tok
;
3803 IdentifierInfo
*Info
= Tok
.getIdentifierInfo();
3804 if (!Info
|| (!Info
->isStr("begin") && !Info
->isStr("end"))) {
3805 PP
.Diag(FirstTok
.getLocation(),
3806 diag::warn_pragma_force_cuda_host_device_bad_arg
);
3810 if (Info
->isStr("begin"))
3811 Actions
.PushForceCUDAHostDevice();
3812 else if (!Actions
.PopForceCUDAHostDevice())
3813 PP
.Diag(FirstTok
.getLocation(),
3814 diag::err_pragma_cannot_end_force_cuda_host_device
);
3817 if (!Tok
.is(tok::eod
))
3818 PP
.Diag(FirstTok
.getLocation(),
3819 diag::warn_pragma_force_cuda_host_device_bad_arg
);
3822 /// Handle the #pragma clang attribute directive.
3826 /// #pragma clang attribute push (attribute, subject-set)
3827 /// #pragma clang attribute push
3828 /// #pragma clang attribute (attribute, subject-set)
3829 /// #pragma clang attribute pop
3832 /// There are also 'namespace' variants of push and pop directives. The bare
3833 /// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
3834 /// namespace, since it always applies attributes to the most recently pushed
3835 /// group, regardless of namespace.
3837 /// #pragma clang attribute namespace.push (attribute, subject-set)
3838 /// #pragma clang attribute namespace.push
3839 /// #pragma clang attribute namespace.pop
3842 /// The subject-set clause defines the set of declarations which receive the
3843 /// attribute. Its exact syntax is described in the LanguageExtensions document
3844 /// in Clang's documentation.
3846 /// This directive instructs the compiler to begin/finish applying the specified
3847 /// attribute to the set of attribute-specific declarations in the active range
3849 void PragmaAttributeHandler::HandlePragma(Preprocessor
&PP
,
3850 PragmaIntroducer Introducer
,
3851 Token
&FirstToken
) {
3854 auto *Info
= new (PP
.getPreprocessorAllocator())
3855 PragmaAttributeInfo(AttributesForPragmaAttribute
);
3857 // Parse the optional namespace followed by a period.
3858 if (Tok
.is(tok::identifier
)) {
3859 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
3860 if (!II
->isStr("push") && !II
->isStr("pop")) {
3861 Info
->Namespace
= II
;
3864 if (!Tok
.is(tok::period
)) {
3865 PP
.Diag(Tok
.getLocation(), diag::err_pragma_attribute_expected_period
)
3873 if (!Tok
.isOneOf(tok::identifier
, tok::l_paren
)) {
3874 PP
.Diag(Tok
.getLocation(),
3875 diag::err_pragma_attribute_expected_push_pop_paren
);
3879 // Determine what action this pragma clang attribute represents.
3880 if (Tok
.is(tok::l_paren
)) {
3881 if (Info
->Namespace
) {
3882 PP
.Diag(Tok
.getLocation(),
3883 diag::err_pragma_attribute_namespace_on_attribute
);
3884 PP
.Diag(Tok
.getLocation(),
3885 diag::note_pragma_attribute_namespace_on_attribute
);
3888 Info
->Action
= PragmaAttributeInfo::Attribute
;
3890 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
3891 if (II
->isStr("push"))
3892 Info
->Action
= PragmaAttributeInfo::Push
;
3893 else if (II
->isStr("pop"))
3894 Info
->Action
= PragmaAttributeInfo::Pop
;
3896 PP
.Diag(Tok
.getLocation(), diag::err_pragma_attribute_invalid_argument
)
3897 << PP
.getSpelling(Tok
);
3904 // Parse the actual attribute.
3905 if ((Info
->Action
== PragmaAttributeInfo::Push
&& Tok
.isNot(tok::eod
)) ||
3906 Info
->Action
== PragmaAttributeInfo::Attribute
) {
3907 if (Tok
.isNot(tok::l_paren
)) {
3908 PP
.Diag(Tok
.getLocation(), diag::err_expected
) << tok::l_paren
;
3913 // Lex the attribute tokens.
3914 SmallVector
<Token
, 16> AttributeTokens
;
3916 while (Tok
.isNot(tok::eod
)) {
3917 if (Tok
.is(tok::l_paren
))
3919 else if (Tok
.is(tok::r_paren
)) {
3921 if (OpenParens
== 0)
3925 AttributeTokens
.push_back(Tok
);
3929 if (AttributeTokens
.empty()) {
3930 PP
.Diag(Tok
.getLocation(), diag::err_pragma_attribute_expected_attribute
);
3933 if (Tok
.isNot(tok::r_paren
)) {
3934 PP
.Diag(Tok
.getLocation(), diag::err_expected
) << tok::r_paren
;
3937 SourceLocation EndLoc
= Tok
.getLocation();
3940 // Terminate the attribute for parsing.
3942 EOFTok
.startToken();
3943 EOFTok
.setKind(tok::eof
);
3944 EOFTok
.setLocation(EndLoc
);
3945 AttributeTokens
.push_back(EOFTok
);
3947 markAsReinjectedForRelexing(AttributeTokens
);
3949 llvm::ArrayRef(AttributeTokens
).copy(PP
.getPreprocessorAllocator());
3952 if (Tok
.isNot(tok::eod
))
3953 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
3954 << "clang attribute";
3956 // Generate the annotated pragma token.
3957 auto TokenArray
= std::make_unique
<Token
[]>(1);
3958 TokenArray
[0].startToken();
3959 TokenArray
[0].setKind(tok::annot_pragma_attribute
);
3960 TokenArray
[0].setLocation(FirstToken
.getLocation());
3961 TokenArray
[0].setAnnotationEndLoc(FirstToken
.getLocation());
3962 TokenArray
[0].setAnnotationValue(static_cast<void *>(Info
));
3963 PP
.EnterTokenStream(std::move(TokenArray
), 1,
3964 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3967 // Handle '#pragma clang max_tokens 12345'.
3968 void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor
&PP
,
3969 PragmaIntroducer Introducer
,
3972 if (Tok
.is(tok::eod
)) {
3973 PP
.Diag(Tok
.getLocation(), diag::err_pragma_missing_argument
)
3974 << "clang max_tokens_here" << /*Expected=*/true << "integer";
3978 SourceLocation Loc
= Tok
.getLocation();
3980 if (Tok
.isNot(tok::numeric_constant
) ||
3981 !PP
.parseSimpleIntegerLiteral(Tok
, MaxTokens
)) {
3982 PP
.Diag(Tok
.getLocation(), diag::err_pragma_expected_integer
)
3983 << "clang max_tokens_here";
3987 if (Tok
.isNot(tok::eod
)) {
3988 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
3989 << "clang max_tokens_here";
3993 if (PP
.getTokenCount() > MaxTokens
) {
3994 PP
.Diag(Loc
, diag::warn_max_tokens
)
3995 << PP
.getTokenCount() << (unsigned)MaxTokens
;
3999 // Handle '#pragma clang max_tokens_total 12345'.
4000 void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor
&PP
,
4001 PragmaIntroducer Introducer
,
4004 if (Tok
.is(tok::eod
)) {
4005 PP
.Diag(Tok
.getLocation(), diag::err_pragma_missing_argument
)
4006 << "clang max_tokens_total" << /*Expected=*/true << "integer";
4010 SourceLocation Loc
= Tok
.getLocation();
4012 if (Tok
.isNot(tok::numeric_constant
) ||
4013 !PP
.parseSimpleIntegerLiteral(Tok
, MaxTokens
)) {
4014 PP
.Diag(Tok
.getLocation(), diag::err_pragma_expected_integer
)
4015 << "clang max_tokens_total";
4019 if (Tok
.isNot(tok::eod
)) {
4020 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
4021 << "clang max_tokens_total";
4025 PP
.overrideMaxTokens(MaxTokens
, Loc
);
4028 // Handle '#pragma clang riscv intrinsic vector'.
4029 // '#pragma clang riscv intrinsic sifive_vector'.
4030 void PragmaRISCVHandler::HandlePragma(Preprocessor
&PP
,
4031 PragmaIntroducer Introducer
,
4032 Token
&FirstToken
) {
4035 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
4037 if (!II
|| !II
->isStr("intrinsic")) {
4038 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_invalid_argument
)
4039 << PP
.getSpelling(Tok
) << "riscv" << /*Expected=*/true << "'intrinsic'";
4044 II
= Tok
.getIdentifierInfo();
4045 if (!II
|| !(II
->isStr("vector") || II
->isStr("sifive_vector"))) {
4046 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_invalid_argument
)
4047 << PP
.getSpelling(Tok
) << "riscv" << /*Expected=*/true
4048 << "'vector' or 'sifive_vector'";
4053 if (Tok
.isNot(tok::eod
)) {
4054 PP
.Diag(Tok
.getLocation(), diag::warn_pragma_extra_tokens_at_eol
)
4055 << "clang riscv intrinsic";
4059 if (II
->isStr("vector"))
4060 Actions
.DeclareRISCVVBuiltins
= true;
4061 else if (II
->isStr("sifive_vector"))
4062 Actions
.DeclareRISCVSiFiveVectorBuiltins
= true;