summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParsePragma.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParsePragma.cpp')
-rw-r--r--clang/lib/Parse/ParsePragma.cpp112
1 files changed, 70 insertions, 42 deletions
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index 20b87d92b78..106c02b362f 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -720,40 +720,68 @@ struct PragmaLoopHintInfo {
Token Option;
Token Value;
bool HasValue;
+ PragmaLoopHintInfo() : HasValue(false) {}
};
-LoopHint Parser::HandlePragmaLoopHint() {
+bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
assert(Tok.is(tok::annot_pragma_loop_hint));
PragmaLoopHintInfo *Info =
static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
+ ConsumeToken(); // The annotation token.
- 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());
-
+ IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
+ Hint.PragmaNameLoc = IdentifierLoc::create(
+ Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
+
+ IdentifierInfo *OptionInfo = Info->Option.getIdentifierInfo();
+ Hint.OptionLoc = IdentifierLoc::create(
+ Actions.Context, Info->Option.getLocation(), OptionInfo);
+
+ // Return a valid hint if pragma unroll or nounroll were specified
+ // without an argument.
+ bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
+ bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
+ if (!Info->HasValue && (PragmaUnroll || PragmaNoUnroll)) {
+ Hint.Range = Info->PragmaName.getLocation();
+ return true;
+ }
+
+ // If no option is specified the argument is assumed to be numeric.
+ bool StateOption = false;
+ if (OptionInfo)
+ StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
+ .Case("vectorize", true)
+ .Case("interleave", true)
+ .Case("unroll", true)
+ .Default(false);
+
+ // Validate the argument.
+ if (StateOption) {
+ bool OptionUnroll = OptionInfo->isStr("unroll");
+ SourceLocation StateLoc = Info->Value.getLocation();
+ IdentifierInfo *StateInfo = Info->Value.getIdentifierInfo();
+ if (!StateInfo || ((OptionUnroll ? !StateInfo->isStr("full")
+ : !StateInfo->isStr("enable")) &&
+ !StateInfo->isStr("disable"))) {
+ Diag(StateLoc, diag::err_pragma_invalid_keyword)
+ << /*MissingArgument=*/false << /*FullKeyword=*/OptionUnroll;
+ return false;
+ }
+ Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
+ } else {
// 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;
+ else {
+ Diag(Info->Value.getLocation(), diag::err_pragma_loop_numeric_value);
+ return false;
+ }
}
- return Hint;
+ Hint.Range =
+ SourceRange(Info->PragmaName.getLocation(), Info->Value.getLocation());
+ return true;
}
// #pragma GCC visibility comes in two variants:
@@ -1755,12 +1783,10 @@ void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
}
/// \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,
+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;
@@ -1784,13 +1810,15 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token Tok, Token &PragmaName,
// FIXME: Value should be stored and parsed as a constant expression.
Token Value = Tok;
+ PP.Lex(Tok);
if (ValueInParens) {
- PP.Lex(Tok);
+ // Read ')'
if (Tok.isNot(tok::r_paren)) {
PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
return true;
}
+ PP.Lex(Tok);
}
Info.PragmaName = PragmaName;
@@ -1872,17 +1900,19 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
<< /*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;
+ // Read '('
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
return;
}
+ PP.Lex(Tok);
+
+ auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
+ if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
+ *Info))
+ return;
// Generate the loop hint token.
Token LoopHintTok;
@@ -1891,9 +1921,6 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
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)) {
@@ -1938,7 +1965,6 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
if (Tok.is(tok::eod)) {
// nounroll or unroll pragma without an argument.
Info->PragmaName = PragmaName;
- Info->Option = PragmaName;
Info->HasValue = false;
} else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
@@ -1947,9 +1973,12 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
} else {
// Unroll pragma with an argument: "#pragma unroll N" or
// "#pragma unroll(N)".
- bool ValueInParens;
- if (ParseLoopHintValue(PP, Tok, PragmaName, PragmaName, ValueInParens,
- *Info))
+ // Read '(' if it exists.
+ bool ValueInParens = Tok.is(tok::l_paren);
+ if (ValueInParens)
+ PP.Lex(Tok);
+
+ if (ParseLoopHintValue(PP, Tok, PragmaName, Token(), ValueInParens, *Info))
return;
// In CUDA, the argument to '#pragma unroll' should not be contained in
@@ -1958,7 +1987,6 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
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";
OpenPOWER on IntegriCloud