1 //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the language specific #pragma handlers.
12 //===----------------------------------------------------------------------===//
14 #include "RAIIObjectsForParser.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/Basic/TargetInfo.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "clang/Parse/ParseDiagnostic.h"
19 #include "clang/Parse/Parser.h"
20 #include "clang/Sema/LoopHint.h"
21 #include "clang/Sema/Scope.h"
22 #include "llvm/ADT/StringSwitch.h"
23 using namespace clang;
27 struct PragmaAlignHandler : public PragmaHandler {
28 explicit PragmaAlignHandler() : PragmaHandler("align") {}
29 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
30 Token &FirstToken) override;
33 struct PragmaGCCVisibilityHandler : public PragmaHandler {
34 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
35 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
36 Token &FirstToken) override;
39 struct PragmaOptionsHandler : public PragmaHandler {
40 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
41 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
42 Token &FirstToken) override;
45 struct PragmaPackHandler : public PragmaHandler {
46 explicit PragmaPackHandler() : PragmaHandler("pack") {}
47 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
48 Token &FirstToken) override;
51 struct PragmaMSStructHandler : public PragmaHandler {
52 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
53 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
54 Token &FirstToken) override;
57 struct PragmaUnusedHandler : public PragmaHandler {
58 PragmaUnusedHandler() : PragmaHandler("unused") {}
59 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
60 Token &FirstToken) override;
63 struct PragmaWeakHandler : public PragmaHandler {
64 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
65 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
66 Token &FirstToken) override;
69 struct PragmaRedefineExtnameHandler : public PragmaHandler {
70 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
71 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
72 Token &FirstToken) override;
75 struct PragmaOpenCLExtensionHandler : public PragmaHandler {
76 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
77 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
78 Token &FirstToken) override;
82 struct PragmaFPContractHandler : public PragmaHandler {
83 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
84 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
85 Token &FirstToken) override;
88 struct PragmaNoOpenMPHandler : public PragmaHandler {
89 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
90 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
91 Token &FirstToken) override;
94 struct PragmaOpenMPHandler : public PragmaHandler {
95 PragmaOpenMPHandler() : PragmaHandler("omp") { }
96 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
97 Token &FirstToken) override;
100 /// PragmaCommentHandler - "\#pragma comment ...".
101 struct PragmaCommentHandler : public PragmaHandler {
102 PragmaCommentHandler(Sema &Actions)
103 : PragmaHandler("comment"), Actions(Actions) {}
104 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
105 Token &FirstToken) override;
110 struct PragmaDetectMismatchHandler : public PragmaHandler {
111 PragmaDetectMismatchHandler(Sema &Actions)
112 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
113 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
114 Token &FirstToken) override;
119 struct PragmaMSPointersToMembers : public PragmaHandler {
120 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
121 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
122 Token &FirstToken) override;
125 struct PragmaMSVtorDisp : public PragmaHandler {
126 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
127 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
128 Token &FirstToken) override;
131 struct PragmaMSPragma : public PragmaHandler {
132 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
133 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
134 Token &FirstToken) override;
137 /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
138 struct PragmaOptimizeHandler : public PragmaHandler {
139 PragmaOptimizeHandler(Sema &S)
140 : PragmaHandler("optimize"), Actions(S) {}
141 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
142 Token &FirstToken) override;
147 struct PragmaLoopHintHandler : public PragmaHandler {
148 PragmaLoopHintHandler() : PragmaHandler("loop") {}
149 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
150 Token &FirstToken) override;
153 struct PragmaUnrollHintHandler : public PragmaHandler {
154 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
155 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
156 Token &FirstToken) override;
159 struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
160 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
165 void Parser::initializePragmaHandlers() {
166 AlignHandler.reset(new PragmaAlignHandler());
167 PP.AddPragmaHandler(AlignHandler.get());
169 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
170 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
172 OptionsHandler.reset(new PragmaOptionsHandler());
173 PP.AddPragmaHandler(OptionsHandler.get());
175 PackHandler.reset(new PragmaPackHandler());
176 PP.AddPragmaHandler(PackHandler.get());
178 MSStructHandler.reset(new PragmaMSStructHandler());
179 PP.AddPragmaHandler(MSStructHandler.get());
181 UnusedHandler.reset(new PragmaUnusedHandler());
182 PP.AddPragmaHandler(UnusedHandler.get());
184 WeakHandler.reset(new PragmaWeakHandler());
185 PP.AddPragmaHandler(WeakHandler.get());
187 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
188 PP.AddPragmaHandler(RedefineExtnameHandler.get());
190 FPContractHandler.reset(new PragmaFPContractHandler());
191 PP.AddPragmaHandler("STDC", FPContractHandler.get());
193 if (getLangOpts().OpenCL) {
194 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
195 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
197 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
199 if (getLangOpts().OpenMP)
200 OpenMPHandler.reset(new PragmaOpenMPHandler());
202 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
203 PP.AddPragmaHandler(OpenMPHandler.get());
205 if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
206 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
207 PP.AddPragmaHandler(MSCommentHandler.get());
210 if (getLangOpts().MicrosoftExt) {
211 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
212 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
213 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
214 PP.AddPragmaHandler(MSPointersToMembers.get());
215 MSVtorDisp.reset(new PragmaMSVtorDisp());
216 PP.AddPragmaHandler(MSVtorDisp.get());
217 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
218 PP.AddPragmaHandler(MSInitSeg.get());
219 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
220 PP.AddPragmaHandler(MSDataSeg.get());
221 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
222 PP.AddPragmaHandler(MSBSSSeg.get());
223 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
224 PP.AddPragmaHandler(MSConstSeg.get());
225 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
226 PP.AddPragmaHandler(MSCodeSeg.get());
227 MSSection.reset(new PragmaMSPragma("section"));
228 PP.AddPragmaHandler(MSSection.get());
229 MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler());
230 PP.AddPragmaHandler(MSRuntimeChecks.get());
233 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
234 PP.AddPragmaHandler("clang", OptimizeHandler.get());
236 LoopHintHandler.reset(new PragmaLoopHintHandler());
237 PP.AddPragmaHandler("clang", LoopHintHandler.get());
239 UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
240 PP.AddPragmaHandler(UnrollHintHandler.get());
242 NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
243 PP.AddPragmaHandler(NoUnrollHintHandler.get());
246 void Parser::resetPragmaHandlers() {
247 // Remove the pragma handlers we installed.
248 PP.RemovePragmaHandler(AlignHandler.get());
249 AlignHandler.reset();
250 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
251 GCCVisibilityHandler.reset();
252 PP.RemovePragmaHandler(OptionsHandler.get());
253 OptionsHandler.reset();
254 PP.RemovePragmaHandler(PackHandler.get());
256 PP.RemovePragmaHandler(MSStructHandler.get());
257 MSStructHandler.reset();
258 PP.RemovePragmaHandler(UnusedHandler.get());
259 UnusedHandler.reset();
260 PP.RemovePragmaHandler(WeakHandler.get());
262 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
263 RedefineExtnameHandler.reset();
265 if (getLangOpts().OpenCL) {
266 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
267 OpenCLExtensionHandler.reset();
268 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
270 PP.RemovePragmaHandler(OpenMPHandler.get());
271 OpenMPHandler.reset();
273 if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
274 PP.RemovePragmaHandler(MSCommentHandler.get());
275 MSCommentHandler.reset();
278 if (getLangOpts().MicrosoftExt) {
279 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
280 MSDetectMismatchHandler.reset();
281 PP.RemovePragmaHandler(MSPointersToMembers.get());
282 MSPointersToMembers.reset();
283 PP.RemovePragmaHandler(MSVtorDisp.get());
285 PP.RemovePragmaHandler(MSInitSeg.get());
287 PP.RemovePragmaHandler(MSDataSeg.get());
289 PP.RemovePragmaHandler(MSBSSSeg.get());
291 PP.RemovePragmaHandler(MSConstSeg.get());
293 PP.RemovePragmaHandler(MSCodeSeg.get());
295 PP.RemovePragmaHandler(MSSection.get());
297 PP.RemovePragmaHandler(MSRuntimeChecks.get());
298 MSRuntimeChecks.reset();
301 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
302 FPContractHandler.reset();
304 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
305 OptimizeHandler.reset();
307 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
308 LoopHintHandler.reset();
310 PP.RemovePragmaHandler(UnrollHintHandler.get());
311 UnrollHintHandler.reset();
313 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
314 NoUnrollHintHandler.reset();
317 /// \brief Handle the annotation token produced for #pragma unused(...)
319 /// Each annot_pragma_unused is followed by the argument token so e.g.
320 /// "#pragma unused(x,y)" becomes:
321 /// annot_pragma_unused 'x' annot_pragma_unused 'y'
322 void Parser::HandlePragmaUnused() {
323 assert(Tok.is(tok::annot_pragma_unused));
324 SourceLocation UnusedLoc = ConsumeToken();
325 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
326 ConsumeToken(); // The argument token.
329 void Parser::HandlePragmaVisibility() {
330 assert(Tok.is(tok::annot_pragma_vis));
331 const IdentifierInfo *VisType =
332 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
333 SourceLocation VisLoc = ConsumeToken();
334 Actions.ActOnPragmaVisibility(VisType, VisLoc);
338 struct PragmaPackInfo {
339 Sema::PragmaPackKind Kind;
340 IdentifierInfo *Name;
342 SourceLocation LParenLoc;
343 SourceLocation RParenLoc;
345 } // end anonymous namespace
347 void Parser::HandlePragmaPack() {
348 assert(Tok.is(tok::annot_pragma_pack));
349 PragmaPackInfo *Info =
350 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
351 SourceLocation PragmaLoc = ConsumeToken();
352 ExprResult Alignment;
353 if (Info->Alignment.is(tok::numeric_constant)) {
354 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
355 if (Alignment.isInvalid())
358 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
359 Info->LParenLoc, Info->RParenLoc);
362 void Parser::HandlePragmaMSStruct() {
363 assert(Tok.is(tok::annot_pragma_msstruct));
364 Sema::PragmaMSStructKind Kind =
365 static_cast<Sema::PragmaMSStructKind>(
366 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
367 Actions.ActOnPragmaMSStruct(Kind);
368 ConsumeToken(); // The annotation token.
371 void Parser::HandlePragmaAlign() {
372 assert(Tok.is(tok::annot_pragma_align));
373 Sema::PragmaOptionsAlignKind Kind =
374 static_cast<Sema::PragmaOptionsAlignKind>(
375 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
376 SourceLocation PragmaLoc = ConsumeToken();
377 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
380 void Parser::HandlePragmaDump() {
381 assert(Tok.is(tok::annot_pragma_dump));
383 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
384 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
388 void Parser::HandlePragmaWeak() {
389 assert(Tok.is(tok::annot_pragma_weak));
390 SourceLocation PragmaLoc = ConsumeToken();
391 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
393 ConsumeToken(); // The weak name.
396 void Parser::HandlePragmaWeakAlias() {
397 assert(Tok.is(tok::annot_pragma_weakalias));
398 SourceLocation PragmaLoc = ConsumeToken();
399 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
400 SourceLocation WeakNameLoc = Tok.getLocation();
402 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
403 SourceLocation AliasNameLoc = Tok.getLocation();
405 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
406 WeakNameLoc, AliasNameLoc);
410 void Parser::HandlePragmaRedefineExtname() {
411 assert(Tok.is(tok::annot_pragma_redefine_extname));
412 SourceLocation RedefLoc = ConsumeToken();
413 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
414 SourceLocation RedefNameLoc = Tok.getLocation();
416 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
417 SourceLocation AliasNameLoc = Tok.getLocation();
419 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
420 RedefNameLoc, AliasNameLoc);
423 void Parser::HandlePragmaFPContract() {
424 assert(Tok.is(tok::annot_pragma_fp_contract));
425 tok::OnOffSwitch OOS =
426 static_cast<tok::OnOffSwitch>(
427 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
428 Actions.ActOnPragmaFPContract(OOS);
429 ConsumeToken(); // The annotation token.
432 StmtResult Parser::HandlePragmaCaptured()
434 assert(Tok.is(tok::annot_pragma_captured));
437 if (Tok.isNot(tok::l_brace)) {
438 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
442 SourceLocation Loc = Tok.getLocation();
444 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
445 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
448 StmtResult R = ParseCompoundStatement();
449 CapturedRegionScope.Exit();
452 Actions.ActOnCapturedRegionError();
456 return Actions.ActOnCapturedRegionEnd(R.get());
460 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
463 void Parser::HandlePragmaOpenCLExtension() {
464 assert(Tok.is(tok::annot_pragma_opencl_extension));
466 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
467 unsigned state = data.getInt();
468 IdentifierInfo *ename = data.getPointer();
469 SourceLocation NameLoc = Tok.getLocation();
470 ConsumeToken(); // The annotation token.
472 OpenCLOptions &f = Actions.getOpenCLOptions();
473 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
474 // overriding all previously issued extension directives, but only if the
475 // behavior is set to disable."
476 if (state == 0 && ename->isStr("all")) {
477 #define OPENCLEXT(nm) f.nm = 0;
478 #include "clang/Basic/OpenCLExtensions.def"
480 #define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
481 #include "clang/Basic/OpenCLExtensions.def"
483 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
488 void Parser::HandlePragmaMSPointersToMembers() {
489 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
490 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
491 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
492 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
493 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
494 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
497 void Parser::HandlePragmaMSVtorDisp() {
498 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
499 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
500 Sema::PragmaVtorDispKind Kind =
501 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
502 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
503 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
504 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
507 void Parser::HandlePragmaMSPragma() {
508 assert(Tok.is(tok::annot_pragma_ms_pragma));
509 // Grab the tokens out of the annotation and enter them into the stream.
510 auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
511 PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
512 SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
513 assert(Tok.isAnyIdentifier());
514 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
515 PP.Lex(Tok); // pragma kind
517 // Figure out which #pragma we're dealing with. The switch has no default
518 // because lex shouldn't emit the annotation token for unrecognized pragmas.
519 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
520 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
521 .Case("data_seg", &Parser::HandlePragmaMSSegment)
522 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
523 .Case("const_seg", &Parser::HandlePragmaMSSegment)
524 .Case("code_seg", &Parser::HandlePragmaMSSegment)
525 .Case("section", &Parser::HandlePragmaMSSection)
526 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
528 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
529 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
530 // until eof (really end of line) to prevent follow-on errors.
531 while (Tok.isNot(tok::eof))
537 bool Parser::HandlePragmaMSSection(StringRef PragmaName,
538 SourceLocation PragmaLocation) {
539 if (Tok.isNot(tok::l_paren)) {
540 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
544 // Parsing code for pragma section
545 if (Tok.isNot(tok::string_literal)) {
546 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
550 ExprResult StringResult = ParseStringLiteralExpression();
551 if (StringResult.isInvalid())
552 return false; // Already diagnosed.
553 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
554 if (SegmentName->getCharByteWidth() != 1) {
555 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
559 int SectionFlags = ASTContext::PSF_Read;
560 bool SectionFlagsAreDefault = true;
561 while (Tok.is(tok::comma)) {
563 // Ignore "long" and "short".
564 // They are undocumented, but widely used, section attributes which appear
566 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
567 PP.Lex(Tok); // long/short
571 if (!Tok.isAnyIdentifier()) {
572 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
576 ASTContext::PragmaSectionFlag Flag =
577 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
578 Tok.getIdentifierInfo()->getName())
579 .Case("read", ASTContext::PSF_Read)
580 .Case("write", ASTContext::PSF_Write)
581 .Case("execute", ASTContext::PSF_Execute)
582 .Case("shared", ASTContext::PSF_Invalid)
583 .Case("nopage", ASTContext::PSF_Invalid)
584 .Case("nocache", ASTContext::PSF_Invalid)
585 .Case("discard", ASTContext::PSF_Invalid)
586 .Case("remove", ASTContext::PSF_Invalid)
587 .Default(ASTContext::PSF_None);
588 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
589 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
590 ? diag::warn_pragma_invalid_specific_action
591 : diag::warn_pragma_unsupported_action)
592 << PragmaName << Tok.getIdentifierInfo()->getName();
595 SectionFlags |= Flag;
596 SectionFlagsAreDefault = false;
597 PP.Lex(Tok); // Identifier
599 // If no section attributes are specified, the section will be marked as
601 if (SectionFlagsAreDefault)
602 SectionFlags |= ASTContext::PSF_Write;
603 if (Tok.isNot(tok::r_paren)) {
604 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
608 if (Tok.isNot(tok::eof)) {
609 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
614 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
618 bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
619 SourceLocation PragmaLocation) {
620 if (Tok.isNot(tok::l_paren)) {
621 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
625 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
627 if (Tok.isAnyIdentifier()) {
628 StringRef PushPop = Tok.getIdentifierInfo()->getName();
629 if (PushPop == "push")
630 Action = Sema::PSK_Push;
631 else if (PushPop == "pop")
632 Action = Sema::PSK_Pop;
634 PP.Diag(PragmaLocation,
635 diag::warn_pragma_expected_section_push_pop_or_name)
639 if (Action != Sema::PSK_Reset) {
640 PP.Lex(Tok); // push | pop
641 if (Tok.is(tok::comma)) {
643 // If we've got a comma, we either need a label or a string.
644 if (Tok.isAnyIdentifier()) {
645 SlotLabel = Tok.getIdentifierInfo()->getName();
646 PP.Lex(Tok); // identifier
647 if (Tok.is(tok::comma))
649 else if (Tok.isNot(tok::r_paren)) {
650 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
655 } else if (Tok.isNot(tok::r_paren)) {
656 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
661 // Grab the string literal for our section name.
662 StringLiteral *SegmentName = nullptr;
663 if (Tok.isNot(tok::r_paren)) {
664 if (Tok.isNot(tok::string_literal)) {
665 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
666 diag::warn_pragma_expected_section_name :
667 diag::warn_pragma_expected_section_label_or_name :
668 diag::warn_pragma_expected_section_push_pop_or_name;
669 PP.Diag(PragmaLocation, DiagID) << PragmaName;
672 ExprResult StringResult = ParseStringLiteralExpression();
673 if (StringResult.isInvalid())
674 return false; // Already diagnosed.
675 SegmentName = cast<StringLiteral>(StringResult.get());
676 if (SegmentName->getCharByteWidth() != 1) {
677 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
681 // Setting section "" has no effect
682 if (SegmentName->getLength())
683 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
685 if (Tok.isNot(tok::r_paren)) {
686 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
690 if (Tok.isNot(tok::eof)) {
691 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
696 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
697 SegmentName, PragmaName);
701 // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
702 bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
703 SourceLocation PragmaLocation) {
704 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
705 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
709 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
713 // Parse either the known section names or the string section name.
714 StringLiteral *SegmentName = nullptr;
715 if (Tok.isAnyIdentifier()) {
716 auto *II = Tok.getIdentifierInfo();
717 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
718 .Case("compiler", "\".CRT$XCC\"")
719 .Case("lib", "\".CRT$XCL\"")
720 .Case("user", "\".CRT$XCU\"")
723 if (!Section.empty()) {
724 // Pretend the user wrote the appropriate string literal here.
726 Toks[0].startToken();
727 Toks[0].setKind(tok::string_literal);
728 Toks[0].setLocation(Tok.getLocation());
729 Toks[0].setLiteralData(Section.data());
730 Toks[0].setLength(Section.size());
732 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
735 } else if (Tok.is(tok::string_literal)) {
736 ExprResult StringResult = ParseStringLiteralExpression();
737 if (StringResult.isInvalid())
739 SegmentName = cast<StringLiteral>(StringResult.get());
740 if (SegmentName->getCharByteWidth() != 1) {
741 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
745 // FIXME: Add support for the '[, func-name]' part of the pragma.
749 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
753 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
755 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
759 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
764 struct PragmaLoopHintInfo {
767 ArrayRef<Token> Toks;
769 } // end anonymous namespace
771 static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
772 std::string PragmaString;
773 if (PragmaName.getIdentifierInfo()->getName() == "loop") {
774 PragmaString = "clang loop ";
775 PragmaString += Option.getIdentifierInfo()->getName();
777 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
778 "Unexpected pragma name");
779 PragmaString = "unroll";
784 bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
785 assert(Tok.is(tok::annot_pragma_loop_hint));
786 PragmaLoopHintInfo *Info =
787 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
789 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
790 Hint.PragmaNameLoc = IdentifierLoc::create(
791 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
793 // It is possible that the loop hint has no option identifier, such as
794 // #pragma unroll(4).
795 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
796 ? Info->Option.getIdentifierInfo()
798 Hint.OptionLoc = IdentifierLoc::create(
799 Actions.Context, Info->Option.getLocation(), OptionInfo);
801 const Token *Toks = Info->Toks.data();
802 size_t TokSize = Info->Toks.size();
804 // Return a valid hint if pragma unroll or nounroll were specified
805 // without an argument.
806 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
807 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
808 if (TokSize == 0 && (PragmaUnroll || PragmaNoUnroll)) {
809 ConsumeToken(); // The annotation token.
810 Hint.Range = Info->PragmaName.getLocation();
814 // The constant expression is always followed by an eof token, which increases
816 assert(TokSize > 0 &&
817 "PragmaLoopHintInfo::Toks must contain at least one token.");
819 // If no option is specified the argument is assumed to be a constant expr.
820 bool OptionUnroll = false;
821 bool StateOption = false;
822 if (OptionInfo) { // Pragma Unroll does not specify an option.
823 OptionUnroll = OptionInfo->isStr("unroll");
824 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
825 .Case("vectorize", true)
826 .Case("interleave", true)
827 .Case("unroll", true)
831 // Verify loop hint has an argument.
832 if (Toks[0].is(tok::eof)) {
833 ConsumeToken(); // The annotation token.
834 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
835 << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll;
839 // Validate the argument.
841 ConsumeToken(); // The annotation token.
842 SourceLocation StateLoc = Toks[0].getLocation();
843 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
845 (!StateInfo->isStr("enable") && !StateInfo->isStr("disable") &&
846 ((OptionUnroll && !StateInfo->isStr("full")) ||
847 (!OptionUnroll && !StateInfo->isStr("assume_safety"))))) {
848 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
849 << /*FullKeyword=*/OptionUnroll;
853 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
854 << PragmaLoopHintString(Info->PragmaName, Info->Option);
855 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
857 // Enter constant expression including eof terminator into token stream.
858 PP.EnterTokenStream(Toks, TokSize, /*DisableMacroExpansion=*/false,
859 /*OwnsTokens=*/false);
860 ConsumeToken(); // The annotation token.
862 ExprResult R = ParseConstantExpression();
864 // Tokens following an error in an ill-formed constant expression will
865 // remain in the token stream and must be removed.
866 if (Tok.isNot(tok::eof)) {
867 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
868 << PragmaLoopHintString(Info->PragmaName, Info->Option);
869 while (Tok.isNot(tok::eof))
873 ConsumeToken(); // Consume the constant expression eof terminator.
876 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
879 // Argument is a constant expression with an integer type.
880 Hint.ValueExpr = R.get();
883 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
884 Info->Toks[TokSize - 1].getLocation());
888 // #pragma GCC visibility comes in two variants:
889 // 'push' '(' [visibility] ')'
891 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
892 PragmaIntroducerKind Introducer,
894 SourceLocation VisLoc = VisTok.getLocation();
897 PP.LexUnexpandedToken(Tok);
899 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
901 const IdentifierInfo *VisType;
902 if (PushPop && PushPop->isStr("pop")) {
904 } else if (PushPop && PushPop->isStr("push")) {
905 PP.LexUnexpandedToken(Tok);
906 if (Tok.isNot(tok::l_paren)) {
907 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
911 PP.LexUnexpandedToken(Tok);
912 VisType = Tok.getIdentifierInfo();
914 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
918 PP.LexUnexpandedToken(Tok);
919 if (Tok.isNot(tok::r_paren)) {
920 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
925 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
929 SourceLocation EndLoc = Tok.getLocation();
930 PP.LexUnexpandedToken(Tok);
931 if (Tok.isNot(tok::eod)) {
932 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
937 Token *Toks = new Token[1];
938 Toks[0].startToken();
939 Toks[0].setKind(tok::annot_pragma_vis);
940 Toks[0].setLocation(VisLoc);
941 Toks[0].setAnnotationEndLoc(EndLoc);
942 Toks[0].setAnnotationValue(
943 const_cast<void*>(static_cast<const void*>(VisType)));
944 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
945 /*OwnsTokens=*/true);
948 // #pragma pack(...) comes in the following delicious flavors:
949 // pack '(' [integer] ')'
950 // pack '(' 'show' ')'
951 // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
952 void PragmaPackHandler::HandlePragma(Preprocessor &PP,
953 PragmaIntroducerKind Introducer,
955 SourceLocation PackLoc = PackTok.getLocation();
959 if (Tok.isNot(tok::l_paren)) {
960 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
964 Sema::PragmaPackKind Kind = Sema::PPK_Default;
965 IdentifierInfo *Name = nullptr;
967 Alignment.startToken();
968 SourceLocation LParenLoc = Tok.getLocation();
970 if (Tok.is(tok::numeric_constant)) {
975 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
976 // the push/pop stack.
977 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
978 if (PP.getLangOpts().ApplePragmaPack)
979 Kind = Sema::PPK_Push;
980 } else if (Tok.is(tok::identifier)) {
981 const IdentifierInfo *II = Tok.getIdentifierInfo();
982 if (II->isStr("show")) {
983 Kind = Sema::PPK_Show;
986 if (II->isStr("push")) {
987 Kind = Sema::PPK_Push;
988 } else if (II->isStr("pop")) {
989 Kind = Sema::PPK_Pop;
991 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
996 if (Tok.is(tok::comma)) {
999 if (Tok.is(tok::numeric_constant)) {
1003 } else if (Tok.is(tok::identifier)) {
1004 Name = Tok.getIdentifierInfo();
1007 if (Tok.is(tok::comma)) {
1010 if (Tok.isNot(tok::numeric_constant)) {
1011 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
1020 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
1025 } else if (PP.getLangOpts().ApplePragmaPack) {
1026 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1027 // the push/pop stack.
1028 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
1029 Kind = Sema::PPK_Pop;
1032 if (Tok.isNot(tok::r_paren)) {
1033 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
1037 SourceLocation RParenLoc = Tok.getLocation();
1039 if (Tok.isNot(tok::eod)) {
1040 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1044 PragmaPackInfo *Info =
1045 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
1046 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
1047 new (Info) PragmaPackInfo();
1050 Info->Alignment = Alignment;
1051 Info->LParenLoc = LParenLoc;
1052 Info->RParenLoc = RParenLoc;
1055 (Token*) PP.getPreprocessorAllocator().Allocate(
1056 sizeof(Token) * 1, llvm::alignOf<Token>());
1058 Toks[0].startToken();
1059 Toks[0].setKind(tok::annot_pragma_pack);
1060 Toks[0].setLocation(PackLoc);
1061 Toks[0].setAnnotationEndLoc(RParenLoc);
1062 Toks[0].setAnnotationValue(static_cast<void*>(Info));
1063 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1064 /*OwnsTokens=*/false);
1067 // #pragma ms_struct on
1068 // #pragma ms_struct off
1069 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1070 PragmaIntroducerKind Introducer,
1071 Token &MSStructTok) {
1072 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
1076 if (Tok.isNot(tok::identifier)) {
1077 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1080 SourceLocation EndLoc = Tok.getLocation();
1081 const IdentifierInfo *II = Tok.getIdentifierInfo();
1082 if (II->isStr("on")) {
1083 Kind = Sema::PMSST_ON;
1086 else if (II->isStr("off") || II->isStr("reset"))
1089 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1093 if (Tok.isNot(tok::eod)) {
1094 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1100 (Token*) PP.getPreprocessorAllocator().Allocate(
1101 sizeof(Token) * 1, llvm::alignOf<Token>());
1103 Toks[0].startToken();
1104 Toks[0].setKind(tok::annot_pragma_msstruct);
1105 Toks[0].setLocation(MSStructTok.getLocation());
1106 Toks[0].setAnnotationEndLoc(EndLoc);
1107 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1108 static_cast<uintptr_t>(Kind)));
1109 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1110 /*OwnsTokens=*/false);
1113 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1114 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
1115 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
1121 if (Tok.isNot(tok::identifier) ||
1122 !Tok.getIdentifierInfo()->isStr("align")) {
1123 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1129 if (Tok.isNot(tok::equal)) {
1130 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1136 if (Tok.isNot(tok::identifier)) {
1137 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1138 << (IsOptions ? "options" : "align");
1142 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
1143 const IdentifierInfo *II = Tok.getIdentifierInfo();
1144 if (II->isStr("native"))
1145 Kind = Sema::POAK_Native;
1146 else if (II->isStr("natural"))
1147 Kind = Sema::POAK_Natural;
1148 else if (II->isStr("packed"))
1149 Kind = Sema::POAK_Packed;
1150 else if (II->isStr("power"))
1151 Kind = Sema::POAK_Power;
1152 else if (II->isStr("mac68k"))
1153 Kind = Sema::POAK_Mac68k;
1154 else if (II->isStr("reset"))
1155 Kind = Sema::POAK_Reset;
1157 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1162 SourceLocation EndLoc = Tok.getLocation();
1164 if (Tok.isNot(tok::eod)) {
1165 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1166 << (IsOptions ? "options" : "align");
1171 (Token*) PP.getPreprocessorAllocator().Allocate(
1172 sizeof(Token) * 1, llvm::alignOf<Token>());
1174 Toks[0].startToken();
1175 Toks[0].setKind(tok::annot_pragma_align);
1176 Toks[0].setLocation(FirstTok.getLocation());
1177 Toks[0].setAnnotationEndLoc(EndLoc);
1178 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1179 static_cast<uintptr_t>(Kind)));
1180 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1181 /*OwnsTokens=*/false);
1184 void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1185 PragmaIntroducerKind Introducer,
1187 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
1190 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1191 PragmaIntroducerKind Introducer,
1192 Token &OptionsTok) {
1193 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
1196 // #pragma unused(identifier)
1197 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1198 PragmaIntroducerKind Introducer,
1200 // FIXME: Should we be expanding macros here? My guess is no.
1201 SourceLocation UnusedLoc = UnusedTok.getLocation();
1203 // Lex the left '('.
1206 if (Tok.isNot(tok::l_paren)) {
1207 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1211 // Lex the declaration reference(s).
1212 SmallVector<Token, 5> Identifiers;
1213 SourceLocation RParenLoc;
1220 if (Tok.is(tok::identifier)) {
1221 Identifiers.push_back(Tok);
1227 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1231 // We are execting a ')' or a ','.
1232 if (Tok.is(tok::comma)) {
1237 if (Tok.is(tok::r_paren)) {
1238 RParenLoc = Tok.getLocation();
1243 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
1248 if (Tok.isNot(tok::eod)) {
1249 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1254 // Verify that we have a location for the right parenthesis.
1255 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
1256 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
1258 // For each identifier token, insert into the token stream a
1259 // annot_pragma_unused token followed by the identifier token.
1260 // This allows us to cache a "#pragma unused" that occurs inside an inline
1261 // C++ member function.
1264 (Token*) PP.getPreprocessorAllocator().Allocate(
1265 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
1266 for (unsigned i=0; i != Identifiers.size(); i++) {
1267 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1268 pragmaUnusedTok.startToken();
1269 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1270 pragmaUnusedTok.setLocation(UnusedLoc);
1271 idTok = Identifiers[i];
1273 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
1274 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1277 // #pragma weak identifier
1278 // #pragma weak identifier '=' identifier
1279 void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1280 PragmaIntroducerKind Introducer,
1282 SourceLocation WeakLoc = WeakTok.getLocation();
1286 if (Tok.isNot(tok::identifier)) {
1287 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1291 Token WeakName = Tok;
1292 bool HasAlias = false;
1296 if (Tok.is(tok::equal)) {
1299 if (Tok.isNot(tok::identifier)) {
1300 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1308 if (Tok.isNot(tok::eod)) {
1309 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1315 (Token*) PP.getPreprocessorAllocator().Allocate(
1316 sizeof(Token) * 3, llvm::alignOf<Token>());
1317 Token &pragmaUnusedTok = Toks[0];
1318 pragmaUnusedTok.startToken();
1319 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1320 pragmaUnusedTok.setLocation(WeakLoc);
1321 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
1323 Toks[2] = AliasName;
1324 PP.EnterTokenStream(Toks, 3,
1325 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1328 (Token*) PP.getPreprocessorAllocator().Allocate(
1329 sizeof(Token) * 2, llvm::alignOf<Token>());
1330 Token &pragmaUnusedTok = Toks[0];
1331 pragmaUnusedTok.startToken();
1332 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1333 pragmaUnusedTok.setLocation(WeakLoc);
1334 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
1336 PP.EnterTokenStream(Toks, 2,
1337 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1341 // #pragma redefine_extname identifier identifier
1342 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1343 PragmaIntroducerKind Introducer,
1344 Token &RedefToken) {
1345 SourceLocation RedefLoc = RedefToken.getLocation();
1349 if (Tok.isNot(tok::identifier)) {
1350 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1355 Token RedefName = Tok;
1358 if (Tok.isNot(tok::identifier)) {
1359 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1360 << "redefine_extname";
1364 Token AliasName = Tok;
1367 if (Tok.isNot(tok::eod)) {
1368 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1374 (Token*) PP.getPreprocessorAllocator().Allocate(
1375 sizeof(Token) * 3, llvm::alignOf<Token>());
1376 Token &pragmaRedefTok = Toks[0];
1377 pragmaRedefTok.startToken();
1378 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1379 pragmaRedefTok.setLocation(RedefLoc);
1380 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
1381 Toks[1] = RedefName;
1382 Toks[2] = AliasName;
1383 PP.EnterTokenStream(Toks, 3,
1384 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1389 PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1390 PragmaIntroducerKind Introducer,
1392 tok::OnOffSwitch OOS;
1393 if (PP.LexOnOffSwitch(OOS))
1397 (Token*) PP.getPreprocessorAllocator().Allocate(
1398 sizeof(Token) * 1, llvm::alignOf<Token>());
1400 Toks[0].startToken();
1401 Toks[0].setKind(tok::annot_pragma_fp_contract);
1402 Toks[0].setLocation(Tok.getLocation());
1403 Toks[0].setAnnotationEndLoc(Tok.getLocation());
1404 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1405 static_cast<uintptr_t>(OOS)));
1406 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1407 /*OwnsTokens=*/false);
1411 PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1412 PragmaIntroducerKind Introducer,
1414 PP.LexUnexpandedToken(Tok);
1415 if (Tok.isNot(tok::identifier)) {
1416 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1420 IdentifierInfo *ename = Tok.getIdentifierInfo();
1421 SourceLocation NameLoc = Tok.getLocation();
1424 if (Tok.isNot(tok::colon)) {
1425 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
1430 if (Tok.isNot(tok::identifier)) {
1431 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1434 IdentifierInfo *op = Tok.getIdentifierInfo();
1437 if (op->isStr("enable")) {
1439 } else if (op->isStr("disable")) {
1442 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1445 SourceLocation StateLoc = Tok.getLocation();
1448 if (Tok.isNot(tok::eod)) {
1449 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1454 OpenCLExtData data(ename, state);
1456 (Token*) PP.getPreprocessorAllocator().Allocate(
1457 sizeof(Token) * 1, llvm::alignOf<Token>());
1459 Toks[0].startToken();
1460 Toks[0].setKind(tok::annot_pragma_opencl_extension);
1461 Toks[0].setLocation(NameLoc);
1462 Toks[0].setAnnotationValue(data.getOpaqueValue());
1463 Toks[0].setAnnotationEndLoc(StateLoc);
1464 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1465 /*OwnsTokens=*/false);
1467 if (PP.getPPCallbacks())
1468 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
1472 /// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1475 PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1476 PragmaIntroducerKind Introducer,
1478 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
1479 FirstTok.getLocation())) {
1480 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
1481 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
1482 diag::Severity::Ignored, SourceLocation());
1484 PP.DiscardUntilEndOfDirective();
1487 /// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1490 PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1491 PragmaIntroducerKind Introducer,
1493 SmallVector<Token, 16> Pragma;
1496 Tok.setKind(tok::annot_pragma_openmp);
1497 Tok.setLocation(FirstTok.getLocation());
1499 while (Tok.isNot(tok::eod)) {
1500 Pragma.push_back(Tok);
1503 SourceLocation EodLoc = Tok.getLocation();
1505 Tok.setKind(tok::annot_pragma_openmp_end);
1506 Tok.setLocation(EodLoc);
1507 Pragma.push_back(Tok);
1509 Token *Toks = new Token[Pragma.size()];
1510 std::copy(Pragma.begin(), Pragma.end(), Toks);
1511 PP.EnterTokenStream(Toks, Pragma.size(),
1512 /*DisableMacroExpansion=*/false, /*OwnsTokens=*/true);
1515 /// \brief Handle '#pragma pointers_to_members'
1516 // The grammar for this pragma is as follows:
1518 // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1520 // #pragma pointers_to_members '(' 'best_case' ')'
1521 // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1522 // #pragma pointers_to_members '(' inheritance-model ')'
1523 void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1524 PragmaIntroducerKind Introducer,
1526 SourceLocation PointersToMembersLoc = Tok.getLocation();
1528 if (Tok.isNot(tok::l_paren)) {
1529 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1530 << "pointers_to_members";
1534 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1536 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1537 << "pointers_to_members";
1542 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
1543 if (Arg->isStr("best_case")) {
1544 RepresentationMethod = LangOptions::PPTMK_BestCase;
1546 if (Arg->isStr("full_generality")) {
1547 if (Tok.is(tok::comma)) {
1550 Arg = Tok.getIdentifierInfo();
1552 PP.Diag(Tok.getLocation(),
1553 diag::err_pragma_pointers_to_members_unknown_kind)
1554 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1558 } else if (Tok.is(tok::r_paren)) {
1559 // #pragma pointers_to_members(full_generality) implicitly specifies
1560 // virtual_inheritance.
1562 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1564 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1565 << "full_generality";
1571 if (Arg->isStr("single_inheritance")) {
1572 RepresentationMethod =
1573 LangOptions::PPTMK_FullGeneralitySingleInheritance;
1574 } else if (Arg->isStr("multiple_inheritance")) {
1575 RepresentationMethod =
1576 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
1577 } else if (Arg->isStr("virtual_inheritance")) {
1578 RepresentationMethod =
1579 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1581 PP.Diag(Tok.getLocation(),
1582 diag::err_pragma_pointers_to_members_unknown_kind)
1583 << Arg << /*HasPointerDeclaration*/ 1;
1589 if (Tok.isNot(tok::r_paren)) {
1590 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1591 << (Arg ? Arg->getName() : "full_generality");
1595 SourceLocation EndLoc = Tok.getLocation();
1597 if (Tok.isNot(tok::eod)) {
1598 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1599 << "pointers_to_members";
1604 AnnotTok.startToken();
1605 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1606 AnnotTok.setLocation(PointersToMembersLoc);
1607 AnnotTok.setAnnotationEndLoc(EndLoc);
1608 AnnotTok.setAnnotationValue(
1609 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1610 PP.EnterToken(AnnotTok);
1613 /// \brief Handle '#pragma vtordisp'
1614 // The grammar for this pragma is as follows:
1616 // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1618 // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1619 // #pragma vtordisp '(' 'pop' ')'
1620 // #pragma vtordisp '(' ')'
1621 void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1622 PragmaIntroducerKind Introducer,
1624 SourceLocation VtorDispLoc = Tok.getLocation();
1626 if (Tok.isNot(tok::l_paren)) {
1627 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1632 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
1633 const IdentifierInfo *II = Tok.getIdentifierInfo();
1635 if (II->isStr("push")) {
1636 // #pragma vtordisp(push, mode)
1638 if (Tok.isNot(tok::comma)) {
1639 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1643 Kind = Sema::PVDK_Push;
1644 // not push, could be on/off
1645 } else if (II->isStr("pop")) {
1646 // #pragma vtordisp(pop)
1648 Kind = Sema::PVDK_Pop;
1650 // not push or pop, could be on/off
1652 if (Tok.is(tok::r_paren)) {
1653 // #pragma vtordisp()
1654 Kind = Sema::PVDK_Reset;
1660 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
1661 const IdentifierInfo *II = Tok.getIdentifierInfo();
1662 if (II && II->isStr("off")) {
1665 } else if (II && II->isStr("on")) {
1668 } else if (Tok.is(tok::numeric_constant) &&
1669 PP.parseSimpleIntegerLiteral(Tok, Value)) {
1671 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1672 << 0 << 2 << "vtordisp";
1676 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1682 // Finish the pragma: ')' $
1683 if (Tok.isNot(tok::r_paren)) {
1684 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1687 SourceLocation EndLoc = Tok.getLocation();
1689 if (Tok.isNot(tok::eod)) {
1690 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1695 // Enter the annotation.
1697 AnnotTok.startToken();
1698 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1699 AnnotTok.setLocation(VtorDispLoc);
1700 AnnotTok.setAnnotationEndLoc(EndLoc);
1701 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1702 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
1703 PP.EnterToken(AnnotTok);
1706 /// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
1707 /// an annotation token.
1708 void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1709 PragmaIntroducerKind Introducer,
1711 Token EoF, AnnotTok;
1713 EoF.setKind(tok::eof);
1714 AnnotTok.startToken();
1715 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1716 AnnotTok.setLocation(Tok.getLocation());
1717 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
1718 SmallVector<Token, 8> TokenVector;
1719 // Suck up all of the tokens before the eod.
1720 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
1721 TokenVector.push_back(Tok);
1722 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
1724 // Add a sentinal EoF token to the end of the list.
1725 TokenVector.push_back(EoF);
1726 // We must allocate this array with new because EnterTokenStream is going to
1728 Token *TokenArray = new Token[TokenVector.size()];
1729 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
1730 auto Value = new (PP.getPreprocessorAllocator())
1731 std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
1732 AnnotTok.setAnnotationValue(Value);
1733 PP.EnterToken(AnnotTok);
1736 /// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1740 /// #pragma detect_mismatch("name", "value")
1742 /// Where 'name' and 'value' are quoted strings. The values are embedded in
1743 /// the object file and passed along to the linker. If the linker detects a
1744 /// mismatch in the object file's values for the given name, a LNK2038 error
1745 /// is emitted. See MSDN for more details.
1746 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1747 PragmaIntroducerKind Introducer,
1749 SourceLocation CommentLoc = Tok.getLocation();
1751 if (Tok.isNot(tok::l_paren)) {
1752 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
1756 // Read the name to embed, which must be a string literal.
1757 std::string NameString;
1758 if (!PP.LexStringLiteral(Tok, NameString,
1759 "pragma detect_mismatch",
1760 /*MacroExpansion=*/true))
1763 // Read the comma followed by a second string literal.
1764 std::string ValueString;
1765 if (Tok.isNot(tok::comma)) {
1766 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1770 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1771 /*MacroExpansion=*/true))
1774 if (Tok.isNot(tok::r_paren)) {
1775 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1778 PP.Lex(Tok); // Eat the r_paren.
1780 if (Tok.isNot(tok::eod)) {
1781 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1785 // If the pragma is lexically sound, notify any interested PPCallbacks.
1786 if (PP.getPPCallbacks())
1787 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1790 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1793 /// \brief Handle the microsoft \#pragma comment extension.
1797 /// #pragma comment(linker, "foo")
1799 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1800 /// "foo" is a string, which is fully macro expanded, and permits string
1801 /// concatenation, embedded escape characters etc. See MSDN for more details.
1802 void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1803 PragmaIntroducerKind Introducer,
1805 SourceLocation CommentLoc = Tok.getLocation();
1807 if (Tok.isNot(tok::l_paren)) {
1808 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1812 // Read the identifier.
1814 if (Tok.isNot(tok::identifier)) {
1815 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1819 // Verify that this is one of the 5 whitelisted options.
1820 IdentifierInfo *II = Tok.getIdentifierInfo();
1821 Sema::PragmaMSCommentKind Kind =
1822 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1823 .Case("linker", Sema::PCK_Linker)
1824 .Case("lib", Sema::PCK_Lib)
1825 .Case("compiler", Sema::PCK_Compiler)
1826 .Case("exestr", Sema::PCK_ExeStr)
1827 .Case("user", Sema::PCK_User)
1828 .Default(Sema::PCK_Unknown);
1829 if (Kind == Sema::PCK_Unknown) {
1830 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1834 // On PS4, issue a warning about any pragma comments other than
1835 // #pragma comment lib.
1836 if (PP.getTargetInfo().getTriple().isPS4() && Kind != Sema::PCK_Lib) {
1837 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
1842 // Read the optional string if present.
1844 std::string ArgumentString;
1845 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1847 /*MacroExpansion=*/true))
1850 // FIXME: warn that 'exestr' is deprecated.
1851 // FIXME: If the kind is "compiler" warn if the string is present (it is
1853 // The MSDN docs say that "lib" and "linker" require a string and have a short
1854 // whitelist of linker options they support, but in practice MSVC doesn't
1855 // issue a diagnostic. Therefore neither does clang.
1857 if (Tok.isNot(tok::r_paren)) {
1858 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1861 PP.Lex(Tok); // eat the r_paren.
1863 if (Tok.isNot(tok::eod)) {
1864 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1868 // If the pragma is lexically sound, notify any interested PPCallbacks.
1869 if (PP.getPPCallbacks())
1870 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
1872 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
1875 // #pragma clang optimize off
1876 // #pragma clang optimize on
1877 void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
1878 PragmaIntroducerKind Introducer,
1879 Token &FirstToken) {
1882 if (Tok.is(tok::eod)) {
1883 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
1884 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
1887 if (Tok.isNot(tok::identifier)) {
1888 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1889 << PP.getSpelling(Tok);
1892 const IdentifierInfo *II = Tok.getIdentifierInfo();
1893 // The only accepted values are 'on' or 'off'.
1895 if (II->isStr("on")) {
1897 } else if (!II->isStr("off")) {
1898 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1899 << PP.getSpelling(Tok);
1904 if (Tok.isNot(tok::eod)) {
1905 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
1906 << PP.getSpelling(Tok);
1910 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
1913 /// \brief Parses loop or unroll pragma hint value and fills in Info.
1914 static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
1915 Token Option, bool ValueInParens,
1916 PragmaLoopHintInfo &Info) {
1917 SmallVector<Token, 1> ValueList;
1918 int OpenParens = ValueInParens ? 1 : 0;
1919 // Read constant expression.
1920 while (Tok.isNot(tok::eod)) {
1921 if (Tok.is(tok::l_paren))
1923 else if (Tok.is(tok::r_paren)) {
1925 if (OpenParens == 0 && ValueInParens)
1929 ValueList.push_back(Tok);
1933 if (ValueInParens) {
1935 if (Tok.isNot(tok::r_paren)) {
1936 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1943 EOFTok.startToken();
1944 EOFTok.setKind(tok::eof);
1945 EOFTok.setLocation(Tok.getLocation());
1946 ValueList.push_back(EOFTok); // Terminates expression for parsing.
1948 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
1950 Info.PragmaName = PragmaName;
1951 Info.Option = Option;
1955 /// \brief Handle the \#pragma clang loop directive.
1956 /// #pragma clang 'loop' loop-hints
1959 /// loop-hint loop-hints[opt]
1962 /// 'vectorize' '(' loop-hint-keyword ')'
1963 /// 'interleave' '(' loop-hint-keyword ')'
1964 /// 'unroll' '(' unroll-hint-keyword ')'
1965 /// 'vectorize_width' '(' loop-hint-value ')'
1966 /// 'interleave_count' '(' loop-hint-value ')'
1967 /// 'unroll_count' '(' loop-hint-value ')'
1969 /// loop-hint-keyword:
1974 /// unroll-hint-keyword:
1979 /// loop-hint-value:
1980 /// constant-expression
1982 /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
1983 /// try vectorizing the instructions of the loop it precedes. Specifying
1984 /// interleave(enable) or interleave_count(_value_) instructs llvm to try
1985 /// interleaving multiple iterations of the loop it precedes. The width of the
1986 /// vector instructions is specified by vectorize_width() and the number of
1987 /// interleaved loop iterations is specified by interleave_count(). Specifying a
1988 /// value of 1 effectively disables vectorization/interleaving, even if it is
1989 /// possible and profitable, and 0 is invalid. The loop vectorizer currently
1990 /// only works on inner loops.
1992 /// The unroll and unroll_count directives control the concatenation
1993 /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
1994 /// completely if the trip count is known at compile time and unroll partially
1995 /// if the trip count is not known. Specifying unroll(full) is similar to
1996 /// unroll(enable) but will unroll the loop only if the trip count is known at
1997 /// compile time. Specifying unroll(disable) disables unrolling for the
1998 /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
1999 /// loop the number of times indicated by the value.
2000 void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
2001 PragmaIntroducerKind Introducer,
2003 // Incoming token is "loop" from "#pragma clang loop".
2004 Token PragmaName = Tok;
2005 SmallVector<Token, 1> TokenList;
2007 // Lex the optimization option and verify it is an identifier.
2009 if (Tok.isNot(tok::identifier)) {
2010 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2011 << /*MissingOption=*/true << "";
2015 while (Tok.is(tok::identifier)) {
2017 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2019 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
2020 .Case("vectorize", true)
2021 .Case("interleave", true)
2022 .Case("unroll", true)
2023 .Case("vectorize_width", true)
2024 .Case("interleave_count", true)
2025 .Case("unroll_count", true)
2028 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2029 << /*MissingOption=*/false << OptionInfo;
2035 if (Tok.isNot(tok::l_paren)) {
2036 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2041 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2042 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2046 // Generate the loop hint token.
2048 LoopHintTok.startToken();
2049 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
2050 LoopHintTok.setLocation(PragmaName.getLocation());
2051 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
2052 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2053 TokenList.push_back(LoopHintTok);
2056 if (Tok.isNot(tok::eod)) {
2057 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2062 Token *TokenArray = new Token[TokenList.size()];
2063 std::copy(TokenList.begin(), TokenList.end(), TokenArray);
2065 PP.EnterTokenStream(TokenArray, TokenList.size(),
2066 /*DisableMacroExpansion=*/false,
2067 /*OwnsTokens=*/true);
2070 /// \brief Handle the loop unroll optimization pragmas.
2072 /// #pragma unroll unroll-hint-value
2073 /// #pragma unroll '(' unroll-hint-value ')'
2074 /// #pragma nounroll
2076 /// unroll-hint-value:
2077 /// constant-expression
2079 /// Loop unrolling hints can be specified with '#pragma unroll' or
2080 /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2081 /// contained in parentheses. With no argument the directive instructs llvm to
2082 /// try to unroll the loop completely. A positive integer argument can be
2083 /// specified to indicate the number of times the loop should be unrolled. To
2084 /// maximize compatibility with other compilers the unroll count argument can be
2085 /// specified with or without parentheses. Specifying, '#pragma nounroll'
2086 /// disables unrolling of the loop.
2087 void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2088 PragmaIntroducerKind Introducer,
2090 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2091 // "#pragma nounroll".
2092 Token PragmaName = Tok;
2094 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2095 if (Tok.is(tok::eod)) {
2096 // nounroll or unroll pragma without an argument.
2097 Info->PragmaName = PragmaName;
2098 Info->Option.startToken();
2099 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
2100 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2104 // Unroll pragma with an argument: "#pragma unroll N" or
2105 // "#pragma unroll(N)".
2106 // Read '(' if it exists.
2107 bool ValueInParens = Tok.is(tok::l_paren);
2112 Option.startToken();
2113 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
2116 // In CUDA, the argument to '#pragma unroll' should not be contained in
2118 if (PP.getLangOpts().CUDA && ValueInParens)
2119 PP.Diag(Info->Toks[0].getLocation(),
2120 diag::warn_pragma_unroll_cuda_value_in_parens);
2122 if (Tok.isNot(tok::eod)) {
2123 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2129 // Generate the hint token.
2130 Token *TokenArray = new Token[1];
2131 TokenArray[0].startToken();
2132 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2133 TokenArray[0].setLocation(PragmaName.getLocation());
2134 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
2135 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
2136 PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false,
2137 /*OwnsTokens=*/true);