aboutsummaryrefslogtreecommitdiff
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.cpp330
1 files changed, 288 insertions, 42 deletions
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index df411e1928d6..6402b31d00b2 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -108,6 +108,7 @@ struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
return;
if (OOS == tok::OOS_ON) {
PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
+ return;
}
MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
@@ -184,6 +185,13 @@ private:
Sema &Actions;
};
+struct PragmaFloatControlHandler : public PragmaHandler {
+ PragmaFloatControlHandler(Sema &Actions)
+ : PragmaHandler("float_control") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+ Token &FirstToken) override;
+};
+
struct PragmaMSPointersToMembers : public PragmaHandler {
explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
@@ -262,6 +270,18 @@ struct PragmaAttributeHandler : public PragmaHandler {
ParsedAttributes AttributesForPragmaAttribute;
};
+struct PragmaMaxTokensHereHandler : public PragmaHandler {
+ PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaMaxTokensTotalHandler : public PragmaHandler {
+ PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+ Token &FirstToken) override;
+};
+
} // end namespace
void Parser::initializePragmaHandlers() {
@@ -322,6 +342,8 @@ void Parser::initializePragmaHandlers() {
PP.AddPragmaHandler(MSCommentHandler.get());
}
+ FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);
+ PP.AddPragmaHandler(FloatControlHandler.get());
if (getLangOpts().MicrosoftExt) {
MSDetectMismatchHandler =
std::make_unique<PragmaDetectMismatchHandler>(Actions);
@@ -382,6 +404,12 @@ void Parser::initializePragmaHandlers() {
AttributePragmaHandler =
std::make_unique<PragmaAttributeHandler>(AttrFactory);
PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
+
+ MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();
+ PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());
+
+ MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
+ PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
}
void Parser::resetPragmaHandlers() {
@@ -420,6 +448,8 @@ void Parser::resetPragmaHandlers() {
PP.RemovePragmaHandler("clang", PCSectionHandler.get());
PCSectionHandler.reset();
+ PP.RemovePragmaHandler(FloatControlHandler.get());
+ FloatControlHandler.reset();
if (getLangOpts().MicrosoftExt) {
PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
MSDetectMismatchHandler.reset();
@@ -487,6 +517,12 @@ void Parser::resetPragmaHandlers() {
PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
AttributePragmaHandler.reset();
+
+ PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());
+ MaxTokensHerePragmaHandler.reset();
+
+ PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
+ MaxTokensTotalPragmaHandler.reset();
}
/// Handle the annotation token produced for #pragma unused(...)
@@ -605,21 +641,37 @@ void Parser::HandlePragmaFPContract() {
static_cast<tok::OnOffSwitch>(
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
- LangOptions::FPContractModeKind FPC;
+ LangOptions::FPModeKind FPC;
switch (OOS) {
case tok::OOS_ON:
- FPC = LangOptions::FPC_On;
+ FPC = LangOptions::FPM_On;
break;
case tok::OOS_OFF:
- FPC = LangOptions::FPC_Off;
+ FPC = LangOptions::FPM_Off;
break;
case tok::OOS_DEFAULT:
FPC = getLangOpts().getDefaultFPContractMode();
break;
}
- Actions.ActOnPragmaFPContract(FPC);
- ConsumeAnnotationToken();
+ SourceLocation PragmaLoc = ConsumeAnnotationToken();
+ Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
+}
+
+void Parser::HandlePragmaFloatControl() {
+ assert(Tok.is(tok::annot_pragma_float_control));
+
+ // The value that is held on the PragmaFloatControlStack encodes
+ // the PragmaFloatControl kind and the MSStackAction kind
+ // into a single 32-bit word. The MsStackAction is the high 16 bits
+ // and the FloatControl is the lower 16 bits. Use shift and bit-and
+ // to decode the parts.
+ uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
+ Sema::PragmaMsStackAction Action =
+ static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
+ PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF);
+ SourceLocation PragmaLoc = ConsumeAnnotationToken();
+ Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);
}
void Parser::HandlePragmaFEnvAccess() {
@@ -628,21 +680,21 @@ void Parser::HandlePragmaFEnvAccess() {
static_cast<tok::OnOffSwitch>(
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
- LangOptions::FEnvAccessModeKind FPC;
+ bool IsEnabled;
switch (OOS) {
case tok::OOS_ON:
- FPC = LangOptions::FEA_On;
+ IsEnabled = true;
break;
case tok::OOS_OFF:
- FPC = LangOptions::FEA_Off;
+ IsEnabled = false;
break;
case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
- FPC = LangOptions::FEA_Off;
+ IsEnabled = false;
break;
}
- Actions.ActOnPragmaFEnvAccess(FPC);
- ConsumeAnnotationToken();
+ SourceLocation PragmaLoc = ConsumeAnnotationToken();
+ Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);
}
@@ -1008,11 +1060,11 @@ struct PragmaLoopHintInfo {
static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
StringRef Str = PragmaName.getIdentifierInfo()->getName();
std::string ClangLoopStr = (llvm::Twine("clang loop ") + Str).str();
- return llvm::StringSwitch<StringRef>(Str)
- .Case("loop", ClangLoopStr)
- .Case("unroll_and_jam", Str)
- .Case("unroll", Str)
- .Default("");
+ return std::string(llvm::StringSwitch<StringRef>(Str)
+ .Case("loop", ClangLoopStr)
+ .Case("unroll_and_jam", Str)
+ .Case("unroll", Str)
+ .Default(""));
}
bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
@@ -1821,6 +1873,7 @@ void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
return;
}
+ SourceLocation PragmaLocation = Tok.getLocation();
PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
if (Tok.isNot(tok::equal)) {
PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
@@ -1831,10 +1884,11 @@ void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
return;
- Actions.ActOnPragmaClangSection(Tok.getLocation(),
- (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
- Sema::PragmaClangSectionAction::PCSA_Clear),
- SecKind, SecName);
+ Actions.ActOnPragmaClangSection(
+ PragmaLocation,
+ (SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set
+ : Sema::PragmaClangSectionAction::PCSA_Clear),
+ SecKind, SecName);
}
}
@@ -2465,6 +2519,129 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP,
PP.EnterToken(AnnotTok, /*IsReinject*/ false);
}
+/// Handle the \#pragma float_control extension.
+///
+/// The syntax is:
+/// \code
+/// #pragma float_control(keyword[, setting] [,push])
+/// \endcode
+/// Where 'keyword' and 'setting' are identifiers.
+// 'keyword' can be: precise, except, push, pop
+// 'setting' can be: on, off
+/// The optional arguments 'setting' and 'push' are supported only
+/// when the keyword is 'precise' or 'except'.
+void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducer Introducer,
+ Token &Tok) {
+ Sema::PragmaMsStackAction Action = Sema::PSK_Set;
+ SourceLocation FloatControlLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
+ return;
+ }
+
+ // Read the identifier.
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
+ return;
+ }
+
+ // Verify that this is one of the float control options.
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ PragmaFloatControlKind Kind =
+ llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
+ .Case("precise", PFC_Precise)
+ .Case("except", PFC_Except)
+ .Case("push", PFC_Push)
+ .Case("pop", PFC_Pop)
+ .Default(PFC_Unknown);
+ PP.Lex(Tok); // the identifier
+ if (Kind == PFC_Unknown) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
+ return;
+ } else if (Kind == PFC_Push || Kind == PFC_Pop) {
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
+ return;
+ }
+ PP.Lex(Tok); // Eat the r_paren
+ Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push;
+ } else {
+ if (Tok.is(tok::r_paren))
+ // Selecting Precise or Except
+ PP.Lex(Tok); // the r_paren
+ else if (Tok.isNot(tok::comma)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
+ return;
+ } else {
+ PP.Lex(Tok); // ,
+ if (!Tok.isAnyIdentifier()) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
+ return;
+ }
+ StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
+ if (PushOnOff == "on")
+ // Kind is set correctly
+ ;
+ else if (PushOnOff == "off") {
+ if (Kind == PFC_Precise)
+ Kind = PFC_NoPrecise;
+ if (Kind == PFC_Except)
+ Kind = PFC_NoExcept;
+ } else if (PushOnOff == "push") {
+ Action = Sema::PSK_Push_Set;
+ } else {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
+ return;
+ }
+ PP.Lex(Tok); // the identifier
+ if (Tok.is(tok::comma)) {
+ PP.Lex(Tok); // ,
+ if (!Tok.isAnyIdentifier()) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
+ return;
+ }
+ StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
+ if (ExpectedPush == "push") {
+ Action = Sema::PSK_Push_Set;
+ } else {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
+ return;
+ }
+ PP.Lex(Tok); // the push identifier
+ }
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
+ return;
+ }
+ PP.Lex(Tok); // the r_paren
+ }
+ }
+ SourceLocation EndLoc = Tok.getLocation();
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "float_control";
+ return;
+ }
+
+ // Note: there is no accomodation for PP callback for this pragma.
+
+ // Enter the annotation.
+ auto TokenArray = std::make_unique<Token[]>(1);
+ TokenArray[0].startToken();
+ TokenArray[0].setKind(tok::annot_pragma_float_control);
+ TokenArray[0].setLocation(FloatControlLoc);
+ TokenArray[0].setAnnotationEndLoc(EndLoc);
+ // Create an encoding of Action and Value by shifting the Action into
+ // the high 16 bits then union with the Kind.
+ TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(
+ static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
+ PP.EnterTokenStream(std::move(TokenArray), 1,
+ /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
+}
+
/// Handle the Microsoft \#pragma detect_mismatch extension.
///
/// The syntax is:
@@ -2548,7 +2725,7 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
return;
}
- // Verify that this is one of the 5 whitelisted options.
+ // Verify that this is one of the 5 explicitly listed options.
IdentifierInfo *II = Tok.getIdentifierInfo();
PragmaMSCommentKind Kind =
llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
@@ -2589,7 +2766,7 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
// FIXME: If the kind is "compiler" warn if the string is present (it is
// ignored).
// The MSDN docs say that "lib" and "linker" require a string and have a short
- // whitelist of linker options they support, but in practice MSVC doesn't
+ // list of linker options they support, but in practice MSVC doesn't
// issue a diagnostic. Therefore neither does clang.
if (Tok.isNot(tok::r_paren)) {
@@ -2651,7 +2828,7 @@ void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
namespace {
/// Used as the annotation value for tok::annot_pragma_fp.
struct TokFPAnnotValue {
- enum FlagKinds { Contract };
+ enum FlagKinds { Contract, Reassociate };
enum FlagValues { On, Off, Fast };
FlagKinds FlagKind;
@@ -2679,6 +2856,7 @@ void PragmaFPHandler::HandlePragma(Preprocessor &PP,
llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
OptionInfo->getName())
.Case("contract", TokFPAnnotValue::Contract)
+ .Case("reassociate", TokFPAnnotValue::Reassociate)
.Default(None);
if (!FlagKind) {
PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
@@ -2696,7 +2874,8 @@ void PragmaFPHandler::HandlePragma(Preprocessor &PP,
if (Tok.isNot(tok::identifier)) {
PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
- << PP.getSpelling(Tok) << OptionInfo->getName();
+ << PP.getSpelling(Tok) << OptionInfo->getName()
+ << (FlagKind == TokFPAnnotValue::Reassociate);
return;
}
const IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -2709,9 +2888,11 @@ void PragmaFPHandler::HandlePragma(Preprocessor &PP,
.Case("fast", TokFPAnnotValue::Fast)
.Default(llvm::None);
- if (!FlagValue) {
+ if (!FlagValue || (FlagKind == TokFPAnnotValue::Reassociate &&
+ FlagValue == TokFPAnnotValue::Fast)) {
PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
- << PP.getSpelling(Tok) << OptionInfo->getName();
+ << PP.getSpelling(Tok) << OptionInfo->getName()
+ << (FlagKind == TokFPAnnotValue::Reassociate);
return;
}
PP.Lex(Tok);
@@ -2725,7 +2906,7 @@ void PragmaFPHandler::HandlePragma(Preprocessor &PP,
auto *AnnotValue = new (PP.getPreprocessorAllocator())
TokFPAnnotValue{*FlagKind, *FlagValue};
- // Generate the loop hint token.
+ // Generate the fp annotation token.
Token FPTok;
FPTok.startToken();
FPTok.setKind(tok::annot_pragma_fp);
@@ -2753,20 +2934,24 @@ void Parser::HandlePragmaFP() {
auto *AnnotValue =
reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
- LangOptions::FPContractModeKind FPC;
- switch (AnnotValue->FlagValue) {
- case TokFPAnnotValue::On:
- FPC = LangOptions::FPC_On;
- break;
- case TokFPAnnotValue::Fast:
- FPC = LangOptions::FPC_Fast;
- break;
- case TokFPAnnotValue::Off:
- FPC = LangOptions::FPC_Off;
- break;
+ if (AnnotValue->FlagKind == TokFPAnnotValue::Reassociate)
+ Actions.ActOnPragmaFPReassociate(
+ Tok.getLocation(), AnnotValue->FlagValue == TokFPAnnotValue::On);
+ else {
+ LangOptions::FPModeKind FPC;
+ switch (AnnotValue->FlagValue) {
+ case TokFPAnnotValue::Off:
+ FPC = LangOptions::FPM_Off;
+ break;
+ case TokFPAnnotValue::On:
+ FPC = LangOptions::FPM_On;
+ break;
+ case TokFPAnnotValue::Fast:
+ FPC = LangOptions::FPM_Fast;
+ break;
+ }
+ Actions.ActOnPragmaFPContract(Tok.getLocation(), FPC);
}
-
- Actions.ActOnPragmaFPContract(FPC);
ConsumeAnnotationToken();
}
@@ -2914,7 +3099,7 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
Token LoopHintTok;
LoopHintTok.startToken();
LoopHintTok.setKind(tok::annot_pragma_loop_hint);
- LoopHintTok.setLocation(PragmaName.getLocation());
+ LoopHintTok.setLocation(Introducer.Loc);
LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
TokenList.push_back(LoopHintTok);
@@ -3001,7 +3186,7 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
auto TokenArray = std::make_unique<Token[]>(1);
TokenArray[0].startToken();
TokenArray[0].setKind(tok::annot_pragma_loop_hint);
- TokenArray[0].setLocation(PragmaName.getLocation());
+ TokenArray[0].setLocation(Introducer.Loc);
TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
PP.EnterTokenStream(std::move(TokenArray), 1,
@@ -3279,3 +3464,64 @@ void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
PP.EnterTokenStream(std::move(TokenArray), 1,
/*DisableMacroExpansion=*/false, /*IsReinject=*/false);
}
+
+// Handle '#pragma clang max_tokens 12345'.
+void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducer Introducer,
+ Token &Tok) {
+ PP.Lex(Tok);
+ if (Tok.is(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
+ << "clang max_tokens_here" << /*Expected=*/true << "integer";
+ return;
+ }
+
+ SourceLocation Loc = Tok.getLocation();
+ uint64_t MaxTokens;
+ if (Tok.isNot(tok::numeric_constant) ||
+ !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
+ << "clang max_tokens_here";
+ return;
+ }
+
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "clang max_tokens_here";
+ return;
+ }
+
+ if (PP.getTokenCount() > MaxTokens) {
+ PP.Diag(Loc, diag::warn_max_tokens)
+ << PP.getTokenCount() << (unsigned)MaxTokens;
+ }
+}
+
+// Handle '#pragma clang max_tokens_total 12345'.
+void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducer Introducer,
+ Token &Tok) {
+ PP.Lex(Tok);
+ if (Tok.is(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
+ << "clang max_tokens_total" << /*Expected=*/true << "integer";
+ return;
+ }
+
+ SourceLocation Loc = Tok.getLocation();
+ uint64_t MaxTokens;
+ if (Tok.isNot(tok::numeric_constant) ||
+ !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
+ << "clang max_tokens_total";
+ return;
+ }
+
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "clang max_tokens_total";
+ return;
+ }
+
+ PP.overrideMaxTokens(MaxTokens, Loc);
+}