summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp1062
1 files changed, 1048 insertions, 14 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
index 8a374e0..d3777f3 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
@@ -11,14 +11,288 @@
//
//===----------------------------------------------------------------------===//
-#include "ParsePragma.h"
+#include "RAIIObjectsForParser.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
+#include "clang/Sema/LoopHint.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
+namespace {
+
+struct PragmaAlignHandler : public PragmaHandler {
+ explicit PragmaAlignHandler() : PragmaHandler("align") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaGCCVisibilityHandler : public PragmaHandler {
+ explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaOptionsHandler : public PragmaHandler {
+ explicit PragmaOptionsHandler() : PragmaHandler("options") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaPackHandler : public PragmaHandler {
+ explicit PragmaPackHandler() : PragmaHandler("pack") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaMSStructHandler : public PragmaHandler {
+ explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaUnusedHandler : public PragmaHandler {
+ PragmaUnusedHandler() : PragmaHandler("unused") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaWeakHandler : public PragmaHandler {
+ explicit PragmaWeakHandler() : PragmaHandler("weak") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaRedefineExtnameHandler : public PragmaHandler {
+ explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaOpenCLExtensionHandler : public PragmaHandler {
+ PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+
+struct PragmaFPContractHandler : public PragmaHandler {
+ PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaNoOpenMPHandler : public PragmaHandler {
+ PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaOpenMPHandler : public PragmaHandler {
+ PragmaOpenMPHandler() : PragmaHandler("omp") { }
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+/// PragmaCommentHandler - "\#pragma comment ...".
+struct PragmaCommentHandler : public PragmaHandler {
+ PragmaCommentHandler(Sema &Actions)
+ : PragmaHandler("comment"), Actions(Actions) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+private:
+ Sema &Actions;
+};
+
+struct PragmaDetectMismatchHandler : public PragmaHandler {
+ PragmaDetectMismatchHandler(Sema &Actions)
+ : PragmaHandler("detect_mismatch"), Actions(Actions) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+private:
+ Sema &Actions;
+};
+
+struct PragmaMSPointersToMembers : public PragmaHandler {
+ explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaMSVtorDisp : public PragmaHandler {
+ explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaMSPragma : public PragmaHandler {
+ explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
+struct PragmaOptimizeHandler : public PragmaHandler {
+ PragmaOptimizeHandler(Sema &S)
+ : PragmaHandler("optimize"), Actions(S) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+private:
+ Sema &Actions;
+};
+
+struct PragmaLoopHintHandler : public PragmaHandler {
+ PragmaLoopHintHandler() : PragmaHandler("loop") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaUnrollHintHandler : public PragmaHandler {
+ PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+} // end namespace
+
+void Parser::initializePragmaHandlers() {
+ AlignHandler.reset(new PragmaAlignHandler());
+ PP.AddPragmaHandler(AlignHandler.get());
+
+ GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
+ PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
+
+ OptionsHandler.reset(new PragmaOptionsHandler());
+ PP.AddPragmaHandler(OptionsHandler.get());
+
+ PackHandler.reset(new PragmaPackHandler());
+ PP.AddPragmaHandler(PackHandler.get());
+
+ MSStructHandler.reset(new PragmaMSStructHandler());
+ PP.AddPragmaHandler(MSStructHandler.get());
+
+ UnusedHandler.reset(new PragmaUnusedHandler());
+ PP.AddPragmaHandler(UnusedHandler.get());
+
+ WeakHandler.reset(new PragmaWeakHandler());
+ PP.AddPragmaHandler(WeakHandler.get());
+
+ RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
+ PP.AddPragmaHandler(RedefineExtnameHandler.get());
+
+ FPContractHandler.reset(new PragmaFPContractHandler());
+ PP.AddPragmaHandler("STDC", FPContractHandler.get());
+
+ if (getLangOpts().OpenCL) {
+ OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
+ PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
+
+ PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
+ }
+ if (getLangOpts().OpenMP)
+ OpenMPHandler.reset(new PragmaOpenMPHandler());
+ else
+ OpenMPHandler.reset(new PragmaNoOpenMPHandler());
+ PP.AddPragmaHandler(OpenMPHandler.get());
+
+ if (getLangOpts().MicrosoftExt) {
+ MSCommentHandler.reset(new PragmaCommentHandler(Actions));
+ PP.AddPragmaHandler(MSCommentHandler.get());
+ MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
+ PP.AddPragmaHandler(MSDetectMismatchHandler.get());
+ MSPointersToMembers.reset(new PragmaMSPointersToMembers());
+ PP.AddPragmaHandler(MSPointersToMembers.get());
+ MSVtorDisp.reset(new PragmaMSVtorDisp());
+ PP.AddPragmaHandler(MSVtorDisp.get());
+ MSInitSeg.reset(new PragmaMSPragma("init_seg"));
+ PP.AddPragmaHandler(MSInitSeg.get());
+ MSDataSeg.reset(new PragmaMSPragma("data_seg"));
+ PP.AddPragmaHandler(MSDataSeg.get());
+ MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
+ PP.AddPragmaHandler(MSBSSSeg.get());
+ MSConstSeg.reset(new PragmaMSPragma("const_seg"));
+ PP.AddPragmaHandler(MSConstSeg.get());
+ MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
+ PP.AddPragmaHandler(MSCodeSeg.get());
+ MSSection.reset(new PragmaMSPragma("section"));
+ PP.AddPragmaHandler(MSSection.get());
+ }
+
+ OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
+ PP.AddPragmaHandler("clang", OptimizeHandler.get());
+
+ LoopHintHandler.reset(new PragmaLoopHintHandler());
+ PP.AddPragmaHandler("clang", LoopHintHandler.get());
+
+ UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
+ PP.AddPragmaHandler(UnrollHintHandler.get());
+}
+
+void Parser::resetPragmaHandlers() {
+ // Remove the pragma handlers we installed.
+ PP.RemovePragmaHandler(AlignHandler.get());
+ AlignHandler.reset();
+ PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
+ GCCVisibilityHandler.reset();
+ PP.RemovePragmaHandler(OptionsHandler.get());
+ OptionsHandler.reset();
+ PP.RemovePragmaHandler(PackHandler.get());
+ PackHandler.reset();
+ PP.RemovePragmaHandler(MSStructHandler.get());
+ MSStructHandler.reset();
+ PP.RemovePragmaHandler(UnusedHandler.get());
+ UnusedHandler.reset();
+ PP.RemovePragmaHandler(WeakHandler.get());
+ WeakHandler.reset();
+ PP.RemovePragmaHandler(RedefineExtnameHandler.get());
+ RedefineExtnameHandler.reset();
+
+ if (getLangOpts().OpenCL) {
+ PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
+ OpenCLExtensionHandler.reset();
+ PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
+ }
+ PP.RemovePragmaHandler(OpenMPHandler.get());
+ OpenMPHandler.reset();
+
+ if (getLangOpts().MicrosoftExt) {
+ PP.RemovePragmaHandler(MSCommentHandler.get());
+ MSCommentHandler.reset();
+ PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
+ MSDetectMismatchHandler.reset();
+ PP.RemovePragmaHandler(MSPointersToMembers.get());
+ MSPointersToMembers.reset();
+ PP.RemovePragmaHandler(MSVtorDisp.get());
+ MSVtorDisp.reset();
+ PP.RemovePragmaHandler(MSInitSeg.get());
+ MSInitSeg.reset();
+ PP.RemovePragmaHandler(MSDataSeg.get());
+ MSDataSeg.reset();
+ PP.RemovePragmaHandler(MSBSSSeg.get());
+ MSBSSSeg.reset();
+ PP.RemovePragmaHandler(MSConstSeg.get());
+ MSConstSeg.reset();
+ PP.RemovePragmaHandler(MSCodeSeg.get());
+ MSCodeSeg.reset();
+ PP.RemovePragmaHandler(MSSection.get());
+ MSSection.reset();
+ }
+
+ PP.RemovePragmaHandler("STDC", FPContractHandler.get());
+ FPContractHandler.reset();
+
+ PP.RemovePragmaHandler("clang", OptimizeHandler.get());
+ OptimizeHandler.reset();
+
+ PP.RemovePragmaHandler("clang", LoopHintHandler.get());
+ LoopHintHandler.reset();
+
+ PP.RemovePragmaHandler(UnrollHintHandler.get());
+ UnrollHintHandler.reset();
+}
+
/// \brief Handle the annotation token produced for #pragma unused(...)
///
/// Each annot_pragma_unused is followed by the argument token so e.g.
@@ -130,7 +404,7 @@ StmtResult Parser::HandlePragmaCaptured()
ConsumeToken();
if (Tok.isNot(tok::l_brace)) {
- PP.Diag(Tok, diag::err_expected_lbrace);
+ PP.Diag(Tok, diag::err_expected) << tok::l_brace;
return StmtError();
}
@@ -180,7 +454,307 @@ void Parser::HandlePragmaOpenCLExtension() {
}
}
+void Parser::HandlePragmaMSPointersToMembers() {
+ assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
+ LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
+ static_cast<LangOptions::PragmaMSPointersToMembersKind>(
+ reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
+ SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
+ Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
+}
+
+void Parser::HandlePragmaMSVtorDisp() {
+ assert(Tok.is(tok::annot_pragma_ms_vtordisp));
+ uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
+ Sema::PragmaVtorDispKind Kind =
+ static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
+ MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
+ SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
+ Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
+}
+void Parser::HandlePragmaMSPragma() {
+ assert(Tok.is(tok::annot_pragma_ms_pragma));
+ // Grab the tokens out of the annotation and enter them into the stream.
+ auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
+ PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
+ SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
+ assert(Tok.isAnyIdentifier());
+ StringRef PragmaName = Tok.getIdentifierInfo()->getName();
+ PP.Lex(Tok); // pragma kind
+
+ // Figure out which #pragma we're dealing with. The switch has no default
+ // because lex shouldn't emit the annotation token for unrecognized pragmas.
+ typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
+ PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
+ .Case("data_seg", &Parser::HandlePragmaMSSegment)
+ .Case("bss_seg", &Parser::HandlePragmaMSSegment)
+ .Case("const_seg", &Parser::HandlePragmaMSSegment)
+ .Case("code_seg", &Parser::HandlePragmaMSSegment)
+ .Case("section", &Parser::HandlePragmaMSSection)
+ .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
+
+ if (!(this->*Handler)(PragmaName, PragmaLocation)) {
+ // Pragma handling failed, and has been diagnosed. Slurp up the tokens
+ // until eof (really end of line) to prevent follow-on errors.
+ while (Tok.isNot(tok::eof))
+ PP.Lex(Tok);
+ PP.Lex(Tok);
+ }
+}
+
+bool Parser::HandlePragmaMSSection(StringRef PragmaName,
+ SourceLocation PragmaLocation) {
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
+ return false;
+ }
+ PP.Lex(Tok); // (
+ // Parsing code for pragma section
+ if (Tok.isNot(tok::string_literal)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
+ << PragmaName;
+ return false;
+ }
+ ExprResult StringResult = ParseStringLiteralExpression();
+ if (StringResult.isInvalid())
+ return false; // Already diagnosed.
+ StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
+ if (SegmentName->getCharByteWidth() != 1) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
+ << PragmaName;
+ return false;
+ }
+ int SectionFlags = 0;
+ while (Tok.is(tok::comma)) {
+ PP.Lex(Tok); // ,
+ if (!Tok.isAnyIdentifier()) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
+ << PragmaName;
+ return false;
+ }
+ Sema::PragmaSectionFlag Flag =
+ llvm::StringSwitch<Sema::PragmaSectionFlag>(
+ Tok.getIdentifierInfo()->getName())
+ .Case("read", Sema::PSF_Read)
+ .Case("write", Sema::PSF_Write)
+ .Case("execute", Sema::PSF_Execute)
+ .Case("shared", Sema::PSF_Invalid)
+ .Case("nopage", Sema::PSF_Invalid)
+ .Case("nocache", Sema::PSF_Invalid)
+ .Case("discard", Sema::PSF_Invalid)
+ .Case("remove", Sema::PSF_Invalid)
+ .Default(Sema::PSF_None);
+ if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
+ PP.Diag(PragmaLocation, Flag == Sema::PSF_None
+ ? diag::warn_pragma_invalid_specific_action
+ : diag::warn_pragma_unsupported_action)
+ << PragmaName << Tok.getIdentifierInfo()->getName();
+ return false;
+ }
+ SectionFlags |= Flag;
+ PP.Lex(Tok); // Identifier
+ }
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
+ return false;
+ }
+ PP.Lex(Tok); // )
+ if (Tok.isNot(tok::eof)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
+ << PragmaName;
+ return false;
+ }
+ PP.Lex(Tok); // eof
+ Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
+ return true;
+}
+
+bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
+ SourceLocation PragmaLocation) {
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
+ return false;
+ }
+ PP.Lex(Tok); // (
+ Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
+ StringRef SlotLabel;
+ if (Tok.isAnyIdentifier()) {
+ StringRef PushPop = Tok.getIdentifierInfo()->getName();
+ if (PushPop == "push")
+ Action = Sema::PSK_Push;
+ else if (PushPop == "pop")
+ Action = Sema::PSK_Pop;
+ else {
+ PP.Diag(PragmaLocation,
+ diag::warn_pragma_expected_section_push_pop_or_name)
+ << PragmaName;
+ return false;
+ }
+ if (Action != Sema::PSK_Reset) {
+ PP.Lex(Tok); // push | pop
+ if (Tok.is(tok::comma)) {
+ PP.Lex(Tok); // ,
+ // If we've got a comma, we either need a label or a string.
+ if (Tok.isAnyIdentifier()) {
+ SlotLabel = Tok.getIdentifierInfo()->getName();
+ PP.Lex(Tok); // identifier
+ if (Tok.is(tok::comma))
+ PP.Lex(Tok);
+ else if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
+ << PragmaName;
+ return false;
+ }
+ }
+ } else if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
+ return false;
+ }
+ }
+ }
+ // Grab the string literal for our section name.
+ StringLiteral *SegmentName = nullptr;
+ if (Tok.isNot(tok::r_paren)) {
+ if (Tok.isNot(tok::string_literal)) {
+ unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
+ diag::warn_pragma_expected_section_name :
+ diag::warn_pragma_expected_section_label_or_name :
+ diag::warn_pragma_expected_section_push_pop_or_name;
+ PP.Diag(PragmaLocation, DiagID) << PragmaName;
+ return false;
+ }
+ ExprResult StringResult = ParseStringLiteralExpression();
+ if (StringResult.isInvalid())
+ return false; // Already diagnosed.
+ SegmentName = cast<StringLiteral>(StringResult.get());
+ if (SegmentName->getCharByteWidth() != 1) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
+ << PragmaName;
+ return false;
+ }
+ // Setting section "" has no effect
+ if (SegmentName->getLength())
+ Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
+ }
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
+ return false;
+ }
+ PP.Lex(Tok); // )
+ if (Tok.isNot(tok::eof)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
+ << PragmaName;
+ return false;
+ }
+ PP.Lex(Tok); // eof
+ Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
+ SegmentName, PragmaName);
+ return true;
+}
+
+// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
+bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
+ SourceLocation PragmaLocation) {
+ if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
+ return false;
+ }
+
+ if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
+ PragmaName))
+ return false;
+
+ // Parse either the known section names or the string section name.
+ StringLiteral *SegmentName = nullptr;
+ if (Tok.isAnyIdentifier()) {
+ auto *II = Tok.getIdentifierInfo();
+ StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
+ .Case("compiler", "\".CRT$XCC\"")
+ .Case("lib", "\".CRT$XCL\"")
+ .Case("user", "\".CRT$XCU\"")
+ .Default("");
+
+ if (!Section.empty()) {
+ // Pretend the user wrote the appropriate string literal here.
+ Token Toks[1];
+ Toks[0].startToken();
+ Toks[0].setKind(tok::string_literal);
+ Toks[0].setLocation(Tok.getLocation());
+ Toks[0].setLiteralData(Section.data());
+ Toks[0].setLength(Section.size());
+ SegmentName =
+ cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
+ PP.Lex(Tok);
+ }
+ } else if (Tok.is(tok::string_literal)) {
+ ExprResult StringResult = ParseStringLiteralExpression();
+ if (StringResult.isInvalid())
+ return false;
+ SegmentName = cast<StringLiteral>(StringResult.get());
+ if (SegmentName->getCharByteWidth() != 1) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
+ << PragmaName;
+ return false;
+ }
+ // FIXME: Add support for the '[, func-name]' part of the pragma.
+ }
+
+ if (!SegmentName) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
+ return false;
+ }
+
+ if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
+ PragmaName) ||
+ ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
+ PragmaName))
+ return false;
+
+ Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
+ return true;
+}
+
+struct PragmaLoopHintInfo {
+ Token PragmaName;
+ Token Option;
+ Token Value;
+ bool HasValue;
+};
+
+LoopHint Parser::HandlePragmaLoopHint() {
+ assert(Tok.is(tok::annot_pragma_loop_hint));
+ PragmaLoopHintInfo *Info =
+ static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
+
+ LoopHint Hint;
+ Hint.PragmaNameLoc =
+ IdentifierLoc::create(Actions.Context, Info->PragmaName.getLocation(),
+ Info->PragmaName.getIdentifierInfo());
+ Hint.OptionLoc =
+ IdentifierLoc::create(Actions.Context, Info->Option.getLocation(),
+ Info->Option.getIdentifierInfo());
+ if (Info->HasValue) {
+ Hint.Range =
+ SourceRange(Info->Option.getLocation(), Info->Value.getLocation());
+ Hint.ValueLoc =
+ IdentifierLoc::create(Actions.Context, Info->Value.getLocation(),
+ Info->Value.getIdentifierInfo());
+
+ // FIXME: We should allow non-type template parameters for the loop hint
+ // value. See bug report #19610
+ if (Info->Value.is(tok::numeric_constant))
+ Hint.ValueExpr = Actions.ActOnNumericConstant(Info->Value).get();
+ else
+ Hint.ValueExpr = nullptr;
+ } else {
+ Hint.Range = SourceRange(Info->PragmaName.getLocation());
+ Hint.ValueLoc = nullptr;
+ Hint.ValueExpr = nullptr;
+ }
+
+ return Hint;
+}
// #pragma GCC visibility comes in two variants:
// 'push' '(' [visibility] ')'
@@ -197,7 +771,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
const IdentifierInfo *VisType;
if (PushPop && PushPop->isStr("pop")) {
- VisType = 0;
+ VisType = nullptr;
} else if (PushPop && PushPop->isStr("push")) {
PP.LexUnexpandedToken(Tok);
if (Tok.isNot(tok::l_paren)) {
@@ -257,7 +831,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
}
Sema::PragmaPackKind Kind = Sema::PPK_Default;
- IdentifierInfo *Name = 0;
+ IdentifierInfo *Name = nullptr;
Token Alignment;
Alignment.startToken();
SourceLocation LParenLoc = Tok.getLocation();
@@ -283,7 +857,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
} else if (II->isStr("pop")) {
Kind = Sema::PPK_Pop;
} else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
return;
}
PP.Lex(Tok);
@@ -530,7 +1104,7 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
}
// Illegal token!
- PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
return;
}
@@ -760,13 +1334,11 @@ void
PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &FirstTok) {
- if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
- FirstTok.getLocation()) !=
- DiagnosticsEngine::Ignored) {
+ if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
+ FirstTok.getLocation())) {
PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
- PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
- diag::MAP_IGNORE,
- SourceLocation());
+ PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
+ diag::Severity::Ignored, SourceLocation());
}
PP.DiscardUntilEndOfDirective();
}
@@ -799,6 +1371,220 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
/*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
}
+/// \brief Handle '#pragma pointers_to_members'
+// The grammar for this pragma is as follows:
+//
+// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
+//
+// #pragma pointers_to_members '(' 'best_case' ')'
+// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
+// #pragma pointers_to_members '(' inheritance-model ')'
+void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ SourceLocation PointersToMembersLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
+ << "pointers_to_members";
+ return;
+ }
+ PP.Lex(Tok);
+ const IdentifierInfo *Arg = Tok.getIdentifierInfo();
+ if (!Arg) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+ << "pointers_to_members";
+ return;
+ }
+ PP.Lex(Tok);
+
+ LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
+ if (Arg->isStr("best_case")) {
+ RepresentationMethod = LangOptions::PPTMK_BestCase;
+ } else {
+ if (Arg->isStr("full_generality")) {
+ if (Tok.is(tok::comma)) {
+ PP.Lex(Tok);
+
+ Arg = Tok.getIdentifierInfo();
+ if (!Arg) {
+ PP.Diag(Tok.getLocation(),
+ diag::err_pragma_pointers_to_members_unknown_kind)
+ << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
+ return;
+ }
+ PP.Lex(Tok);
+ } else if (Tok.is(tok::r_paren)) {
+ // #pragma pointers_to_members(full_generality) implicitly specifies
+ // virtual_inheritance.
+ Arg = nullptr;
+ RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
+ } else {
+ PP.Diag(Tok.getLocation(), diag::err_expected_punc)
+ << "full_generality";
+ return;
+ }
+ }
+
+ if (Arg) {
+ if (Arg->isStr("single_inheritance")) {
+ RepresentationMethod =
+ LangOptions::PPTMK_FullGeneralitySingleInheritance;
+ } else if (Arg->isStr("multiple_inheritance")) {
+ RepresentationMethod =
+ LangOptions::PPTMK_FullGeneralityMultipleInheritance;
+ } else if (Arg->isStr("virtual_inheritance")) {
+ RepresentationMethod =
+ LangOptions::PPTMK_FullGeneralityVirtualInheritance;
+ } else {
+ PP.Diag(Tok.getLocation(),
+ diag::err_pragma_pointers_to_members_unknown_kind)
+ << Arg << /*HasPointerDeclaration*/ 1;
+ return;
+ }
+ }
+ }
+
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
+ << (Arg ? Arg->getName() : "full_generality");
+ return;
+ }
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "pointers_to_members";
+ return;
+ }
+
+ Token AnnotTok;
+ AnnotTok.startToken();
+ AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
+ AnnotTok.setLocation(PointersToMembersLoc);
+ AnnotTok.setAnnotationValue(
+ reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
+ PP.EnterToken(AnnotTok);
+}
+
+/// \brief Handle '#pragma vtordisp'
+// The grammar for this pragma is as follows:
+//
+// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
+//
+// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
+// #pragma vtordisp '(' 'pop' ')'
+// #pragma vtordisp '(' ')'
+void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ SourceLocation VtorDispLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
+ return;
+ }
+ PP.Lex(Tok);
+
+ Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II) {
+ if (II->isStr("push")) {
+ // #pragma vtordisp(push, mode)
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::comma)) {
+ PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
+ return;
+ }
+ PP.Lex(Tok);
+ Kind = Sema::PVDK_Push;
+ // not push, could be on/off
+ } else if (II->isStr("pop")) {
+ // #pragma vtordisp(pop)
+ PP.Lex(Tok);
+ Kind = Sema::PVDK_Pop;
+ }
+ // not push or pop, could be on/off
+ } else {
+ if (Tok.is(tok::r_paren)) {
+ // #pragma vtordisp()
+ Kind = Sema::PVDK_Reset;
+ }
+ }
+
+
+ uint64_t Value = 0;
+ if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II && II->isStr("off")) {
+ PP.Lex(Tok);
+ Value = 0;
+ } else if (II && II->isStr("on")) {
+ PP.Lex(Tok);
+ Value = 1;
+ } else if (Tok.is(tok::numeric_constant) &&
+ PP.parseSimpleIntegerLiteral(Tok, Value)) {
+ if (Value > 2) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
+ << 0 << 2 << "vtordisp";
+ return;
+ }
+ } else {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
+ << "vtordisp";
+ return;
+ }
+ }
+
+ // Finish the pragma: ')' $
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
+ return;
+ }
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "vtordisp";
+ return;
+ }
+
+ // Enter the annotation.
+ Token AnnotTok;
+ AnnotTok.startToken();
+ AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
+ AnnotTok.setLocation(VtorDispLoc);
+ AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
+ static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
+ PP.EnterToken(AnnotTok);
+}
+
+/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
+/// an annotation token.
+void PragmaMSPragma::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ Token EoF, AnnotTok;
+ EoF.startToken();
+ EoF.setKind(tok::eof);
+ AnnotTok.startToken();
+ AnnotTok.setKind(tok::annot_pragma_ms_pragma);
+ AnnotTok.setLocation(Tok.getLocation());
+ SmallVector<Token, 8> TokenVector;
+ // Suck up all of the tokens before the eod.
+ for (; Tok.isNot(tok::eod); PP.Lex(Tok))
+ TokenVector.push_back(Tok);
+ // Add a sentinal EoF token to the end of the list.
+ TokenVector.push_back(EoF);
+ // We must allocate this array with new because EnterTokenStream is going to
+ // delete it later.
+ Token *TokenArray = new Token[TokenVector.size()];
+ std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
+ auto Value = new (PP.getPreprocessorAllocator())
+ std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
+ AnnotTok.setAnnotationValue(Value);
+ PP.EnterToken(AnnotTok);
+}
+
/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
///
/// The syntax is:
@@ -815,7 +1601,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
SourceLocation CommentLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.isNot(tok::l_paren)) {
- PP.Diag(CommentLoc, diag::err_expected_lparen);
+ PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
return;
}
@@ -838,7 +1624,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
return;
if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_expected_rparen);
+ PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
return;
}
PP.Lex(Tok); // Eat the r_paren.
@@ -929,3 +1715,251 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
Actions.ActOnPragmaMSComment(Kind, ArgumentString);
}
+
+// #pragma clang optimize off
+// #pragma clang optimize on
+void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &FirstToken) {
+ Token Tok;
+ PP.Lex(Tok);
+ if (Tok.is(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
+ << "clang optimize"
+ << "'on' or 'off'";
+ return;
+ }
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
+ << PP.getSpelling(Tok);
+ return;
+ }
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ // The only accepted values are 'on' or 'off'.
+ bool IsOn = false;
+ if (II->isStr("on")) {
+ IsOn = true;
+ } else if (!II->isStr("off")) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
+ << PP.getSpelling(Tok);
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
+ << PP.getSpelling(Tok);
+ return;
+ }
+
+ Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
+}
+
+/// \brief Parses loop or unroll pragma hint value and fills in Info.
+static bool ParseLoopHintValue(Preprocessor &PP, Token Tok, Token &PragmaName,
+ Token &Option, bool &ValueInParens,
+ PragmaLoopHintInfo &Info) {
+ ValueInParens = Tok.is(tok::l_paren);
+ if (ValueInParens) {
+ PP.Lex(Tok);
+ if (Tok.is(tok::r_paren)) {
+ // Nothing between the parentheses.
+ std::string PragmaString;
+ if (PragmaName.getIdentifierInfo()->getName() == "loop") {
+ PragmaString = "clang loop ";
+ PragmaString += Option.getIdentifierInfo()->getName();
+ } else {
+ assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
+ "Unexpected pragma name");
+ PragmaString = "unroll";
+ }
+ PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
+ << PragmaString << "a positive integer value";
+ return true;
+ }
+ }
+
+ // FIXME: Value should be stored and parsed as a constant expression.
+ Token Value = Tok;
+
+ if (ValueInParens) {
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
+ return true;
+ }
+ }
+
+ Info.PragmaName = PragmaName;
+ Info.Option = Option;
+ Info.Value = Value;
+ Info.HasValue = true;
+ return false;
+}
+
+/// \brief Handle the \#pragma clang loop directive.
+/// #pragma clang 'loop' loop-hints
+///
+/// loop-hints:
+/// loop-hint loop-hints[opt]
+///
+/// loop-hint:
+/// 'vectorize' '(' loop-hint-keyword ')'
+/// 'interleave' '(' loop-hint-keyword ')'
+/// 'unroll' '(' loop-hint-keyword ')'
+/// 'vectorize_width' '(' loop-hint-value ')'
+/// 'interleave_count' '(' loop-hint-value ')'
+/// 'unroll_count' '(' loop-hint-value ')'
+///
+/// loop-hint-keyword:
+/// 'enable'
+/// 'disable'
+///
+/// loop-hint-value:
+/// constant-expression
+///
+/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
+/// try vectorizing the instructions of the loop it precedes. Specifying
+/// interleave(enable) or interleave_count(_value_) instructs llvm to try
+/// interleaving multiple iterations of the loop it precedes. The width of the
+/// vector instructions is specified by vectorize_width() and the number of
+/// interleaved loop iterations is specified by interleave_count(). Specifying a
+/// value of 1 effectively disables vectorization/interleaving, even if it is
+/// possible and profitable, and 0 is invalid. The loop vectorizer currently
+/// only works on inner loops.
+///
+/// The unroll and unroll_count directives control the concatenation
+/// unroller. Specifying unroll(enable) instructs llvm to try to
+/// unroll the loop completely, and unroll(disable) disables unrolling
+/// for the loop. Specifying unroll_count(_value_) instructs llvm to
+/// try to unroll the loop the number of times indicated by the value.
+/// If unroll(enable) and unroll_count are both specified only
+/// unroll_count takes effect.
+void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ // Incoming token is "loop" from "#pragma clang loop".
+ Token PragmaName = Tok;
+ SmallVector<Token, 1> TokenList;
+
+ // Lex the optimization option and verify it is an identifier.
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
+ << /*MissingOption=*/true << "";
+ return;
+ }
+
+ while (Tok.is(tok::identifier)) {
+ Token Option = Tok;
+ IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
+
+ bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
+ .Case("vectorize", true)
+ .Case("interleave", true)
+ .Case("unroll", true)
+ .Case("vectorize_width", true)
+ .Case("interleave_count", true)
+ .Case("unroll_count", true)
+ .Default(false);
+ if (!OptionValid) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
+ << /*MissingOption=*/false << OptionInfo;
+ return;
+ }
+
+ auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
+ PP.Lex(Tok);
+ bool ValueInParens;
+ if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
+ return;
+
+ if (!ValueInParens) {
+ PP.Diag(Info->Value.getLocation(), diag::err_expected) << tok::l_paren;
+ return;
+ }
+
+ // Generate the loop hint token.
+ Token LoopHintTok;
+ LoopHintTok.startToken();
+ LoopHintTok.setKind(tok::annot_pragma_loop_hint);
+ LoopHintTok.setLocation(PragmaName.getLocation());
+ LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
+ TokenList.push_back(LoopHintTok);
+
+ // Get next optimization option.
+ PP.Lex(Tok);
+ }
+
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "clang loop";
+ return;
+ }
+
+ Token *TokenArray = new Token[TokenList.size()];
+ std::copy(TokenList.begin(), TokenList.end(), TokenArray);
+
+ PP.EnterTokenStream(TokenArray, TokenList.size(),
+ /*DisableMacroExpansion=*/false,
+ /*OwnsTokens=*/true);
+}
+
+/// \brief Handle the loop unroll optimization pragmas.
+/// #pragma unroll
+/// #pragma unroll unroll-hint-value
+/// #pragma unroll '(' unroll-hint-value ')'
+///
+/// unroll-hint-value:
+/// constant-expression
+///
+/// Loop unrolling hints are specified with '#pragma unroll'. '#pragma unroll'
+/// can take a numeric argument optionally contained in parentheses. With no
+/// argument the directive instructs llvm to try to unroll the loop
+/// completely. A positive integer argument can be specified to indicate the
+/// number of times the loop should be unrolled. To maximize compatibility with
+/// other compilers the unroll count argument can be specified with or without
+/// parentheses.
+void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ // Incoming token is "unroll" of "#pragma unroll".
+ Token PragmaName = Tok;
+ PP.Lex(Tok);
+ auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
+ if (Tok.is(tok::eod)) {
+ // Unroll pragma without an argument.
+ Info->PragmaName = PragmaName;
+ Info->Option = PragmaName;
+ Info->HasValue = false;
+ } else {
+ // Unroll pragma with an argument: "#pragma unroll N" or
+ // "#pragma unroll(N)".
+ bool ValueInParens;
+ if (ParseLoopHintValue(PP, Tok, PragmaName, PragmaName, ValueInParens,
+ *Info))
+ return;
+
+ // In CUDA, the argument to '#pragma unroll' should not be contained in
+ // parentheses.
+ if (PP.getLangOpts().CUDA && ValueInParens)
+ PP.Diag(Info->Value.getLocation(),
+ diag::warn_pragma_unroll_cuda_value_in_parens);
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "unroll";
+ return;
+ }
+ }
+
+ // Generate the hint token.
+ Token *TokenArray = new Token[1];
+ TokenArray[0].startToken();
+ TokenArray[0].setKind(tok::annot_pragma_loop_hint);
+ TokenArray[0].setLocation(PragmaName.getLocation());
+ TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
+ PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false,
+ /*OwnsTokens=*/true);
+}
OpenPOWER on IntegriCloud