diff options
author | Tyler Nowicki <tnowicki@apple.com> | 2014-07-30 20:54:33 +0000 |
---|---|---|
committer | Tyler Nowicki <tnowicki@apple.com> | 2014-07-30 20:54:33 +0000 |
commit | cab7ca3e2a64869f6acaf730e0fb032bf1299bd7 (patch) | |
tree | ea3db3d8f014eeb585201ce62896e00006e65c2f /clang/lib/Parse/ParsePragma.cpp | |
parent | fee94b47ed5558a823702840075daffbda8d4f04 (diff) | |
download | bcm5719-llvm-cab7ca3e2a64869f6acaf730e0fb032bf1299bd7.tar.gz bcm5719-llvm-cab7ca3e2a64869f6acaf730e0fb032bf1299bd7.zip |
Add a state variable to the loop hint attribute.
This patch is necessary to support constant expressions which replaces the integer value in the loop hint attribute with an expression. The integer value was also storing the pragma’s state for options like vectorize(enable/disable) and the pragma unroll and nounroll directive. The state variable is introduced to hold the state of those options/pragmas. This moves the validation of the state (keywords) from SemaStmtAttr handler to the loop hint annotation token handler.
Reviewed by Aaron Ballman
llvm-svn: 214333
Diffstat (limited to 'clang/lib/Parse/ParsePragma.cpp')
-rw-r--r-- | clang/lib/Parse/ParsePragma.cpp | 111 |
1 files changed, 69 insertions, 42 deletions
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 20b87d92b78..bc79e3d2966 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -722,38 +722,65 @@ struct PragmaLoopHintInfo { bool HasValue; }; -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 +1782,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 +1809,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 +1899,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 +1920,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 +1964,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 +1972,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 +1986,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"; |