summaryrefslogtreecommitdiff
path: root/lib/Parse/ParsePragma.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParsePragma.cpp')
-rw-r--r--lib/Parse/ParsePragma.cpp273
1 files changed, 203 insertions, 70 deletions
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 07f48e0779dc6..380eb64997a71 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -15,10 +15,10 @@
#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/LoopHint.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
-#include "clang/Sema/LoopHint.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
@@ -106,8 +106,19 @@ struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
tok::OnOffSwitch OOS;
if (PP.LexOnOffSwitch(OOS))
return;
- if (OOS == tok::OOS_ON)
+ if (OOS == tok::OOS_ON) {
PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
+ }
+
+ MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
+ 1);
+ Toks[0].startToken();
+ Toks[0].setKind(tok::annot_pragma_fenv_access);
+ Toks[0].setLocation(Tok.getLocation());
+ Toks[0].setAnnotationEndLoc(Tok.getLocation());
+ Toks[0].setAnnotationValue(reinterpret_cast<void*>(
+ static_cast<uintptr_t>(OOS)));
+ PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
}
};
@@ -250,112 +261,122 @@ struct PragmaAttributeHandler : public PragmaHandler {
} // end namespace
void Parser::initializePragmaHandlers() {
- AlignHandler.reset(new PragmaAlignHandler());
+ AlignHandler = llvm::make_unique<PragmaAlignHandler>();
PP.AddPragmaHandler(AlignHandler.get());
- GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
+ GCCVisibilityHandler = llvm::make_unique<PragmaGCCVisibilityHandler>();
PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
- OptionsHandler.reset(new PragmaOptionsHandler());
+ OptionsHandler = llvm::make_unique<PragmaOptionsHandler>();
PP.AddPragmaHandler(OptionsHandler.get());
- PackHandler.reset(new PragmaPackHandler());
+ PackHandler = llvm::make_unique<PragmaPackHandler>();
PP.AddPragmaHandler(PackHandler.get());
- MSStructHandler.reset(new PragmaMSStructHandler());
+ MSStructHandler = llvm::make_unique<PragmaMSStructHandler>();
PP.AddPragmaHandler(MSStructHandler.get());
- UnusedHandler.reset(new PragmaUnusedHandler());
+ UnusedHandler = llvm::make_unique<PragmaUnusedHandler>();
PP.AddPragmaHandler(UnusedHandler.get());
- WeakHandler.reset(new PragmaWeakHandler());
+ WeakHandler = llvm::make_unique<PragmaWeakHandler>();
PP.AddPragmaHandler(WeakHandler.get());
- RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
+ RedefineExtnameHandler = llvm::make_unique<PragmaRedefineExtnameHandler>();
PP.AddPragmaHandler(RedefineExtnameHandler.get());
- FPContractHandler.reset(new PragmaFPContractHandler());
+ FPContractHandler = llvm::make_unique<PragmaFPContractHandler>();
PP.AddPragmaHandler("STDC", FPContractHandler.get());
- STDCFENVHandler.reset(new PragmaSTDC_FENV_ACCESSHandler());
+ STDCFENVHandler = llvm::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
PP.AddPragmaHandler("STDC", STDCFENVHandler.get());
- STDCCXLIMITHandler.reset(new PragmaSTDC_CX_LIMITED_RANGEHandler());
+ STDCCXLIMITHandler = llvm::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
- STDCUnknownHandler.reset(new PragmaSTDC_UnknownHandler());
+ STDCUnknownHandler = llvm::make_unique<PragmaSTDC_UnknownHandler>();
PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
- PCSectionHandler.reset(new PragmaClangSectionHandler(Actions));
+ PCSectionHandler = llvm::make_unique<PragmaClangSectionHandler>(Actions);
PP.AddPragmaHandler("clang", PCSectionHandler.get());
if (getLangOpts().OpenCL) {
- OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
+ OpenCLExtensionHandler = llvm::make_unique<PragmaOpenCLExtensionHandler>();
PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
}
if (getLangOpts().OpenMP)
- OpenMPHandler.reset(new PragmaOpenMPHandler());
+ OpenMPHandler = llvm::make_unique<PragmaOpenMPHandler>();
else
- OpenMPHandler.reset(new PragmaNoOpenMPHandler());
+ OpenMPHandler = llvm::make_unique<PragmaNoOpenMPHandler>();
PP.AddPragmaHandler(OpenMPHandler.get());
if (getLangOpts().MicrosoftExt ||
getTargetInfo().getTriple().isOSBinFormatELF()) {
- MSCommentHandler.reset(new PragmaCommentHandler(Actions));
+ MSCommentHandler = llvm::make_unique<PragmaCommentHandler>(Actions);
PP.AddPragmaHandler(MSCommentHandler.get());
}
if (getLangOpts().MicrosoftExt) {
- MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
+ MSDetectMismatchHandler =
+ llvm::make_unique<PragmaDetectMismatchHandler>(Actions);
PP.AddPragmaHandler(MSDetectMismatchHandler.get());
- MSPointersToMembers.reset(new PragmaMSPointersToMembers());
+ MSPointersToMembers = llvm::make_unique<PragmaMSPointersToMembers>();
PP.AddPragmaHandler(MSPointersToMembers.get());
- MSVtorDisp.reset(new PragmaMSVtorDisp());
+ MSVtorDisp = llvm::make_unique<PragmaMSVtorDisp>();
PP.AddPragmaHandler(MSVtorDisp.get());
- MSInitSeg.reset(new PragmaMSPragma("init_seg"));
+ MSInitSeg = llvm::make_unique<PragmaMSPragma>("init_seg");
PP.AddPragmaHandler(MSInitSeg.get());
- MSDataSeg.reset(new PragmaMSPragma("data_seg"));
+ MSDataSeg = llvm::make_unique<PragmaMSPragma>("data_seg");
PP.AddPragmaHandler(MSDataSeg.get());
- MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
+ MSBSSSeg = llvm::make_unique<PragmaMSPragma>("bss_seg");
PP.AddPragmaHandler(MSBSSSeg.get());
- MSConstSeg.reset(new PragmaMSPragma("const_seg"));
+ MSConstSeg = llvm::make_unique<PragmaMSPragma>("const_seg");
PP.AddPragmaHandler(MSConstSeg.get());
- MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
+ MSCodeSeg = llvm::make_unique<PragmaMSPragma>("code_seg");
PP.AddPragmaHandler(MSCodeSeg.get());
- MSSection.reset(new PragmaMSPragma("section"));
+ MSSection = llvm::make_unique<PragmaMSPragma>("section");
PP.AddPragmaHandler(MSSection.get());
- MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler());
+ MSRuntimeChecks = llvm::make_unique<PragmaMSRuntimeChecksHandler>();
PP.AddPragmaHandler(MSRuntimeChecks.get());
- MSIntrinsic.reset(new PragmaMSIntrinsicHandler());
+ MSIntrinsic = llvm::make_unique<PragmaMSIntrinsicHandler>();
PP.AddPragmaHandler(MSIntrinsic.get());
- MSOptimize.reset(new PragmaMSOptimizeHandler());
+ MSOptimize = llvm::make_unique<PragmaMSOptimizeHandler>();
PP.AddPragmaHandler(MSOptimize.get());
}
if (getLangOpts().CUDA) {
- CUDAForceHostDeviceHandler.reset(
- new PragmaForceCUDAHostDeviceHandler(Actions));
+ CUDAForceHostDeviceHandler =
+ llvm::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
}
- OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
+ OptimizeHandler = llvm::make_unique<PragmaOptimizeHandler>(Actions);
PP.AddPragmaHandler("clang", OptimizeHandler.get());
- LoopHintHandler.reset(new PragmaLoopHintHandler());
+ LoopHintHandler = llvm::make_unique<PragmaLoopHintHandler>();
PP.AddPragmaHandler("clang", LoopHintHandler.get());
- UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
+ UnrollHintHandler = llvm::make_unique<PragmaUnrollHintHandler>("unroll");
PP.AddPragmaHandler(UnrollHintHandler.get());
- NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
+ NoUnrollHintHandler = llvm::make_unique<PragmaUnrollHintHandler>("nounroll");
PP.AddPragmaHandler(NoUnrollHintHandler.get());
- FPHandler.reset(new PragmaFPHandler());
+ UnrollAndJamHintHandler =
+ llvm::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
+ PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
+
+ NoUnrollAndJamHintHandler =
+ llvm::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
+ PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
+
+ FPHandler = llvm::make_unique<PragmaFPHandler>();
PP.AddPragmaHandler("clang", FPHandler.get());
- AttributePragmaHandler.reset(new PragmaAttributeHandler(AttrFactory));
+ AttributePragmaHandler =
+ llvm::make_unique<PragmaAttributeHandler>(AttrFactory);
PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
}
@@ -451,6 +472,12 @@ void Parser::resetPragmaHandlers() {
PP.RemovePragmaHandler(NoUnrollHintHandler.get());
NoUnrollHintHandler.reset();
+ PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
+ UnrollAndJamHintHandler.reset();
+
+ PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
+ NoUnrollAndJamHintHandler.reset();
+
PP.RemovePragmaHandler("clang", FPHandler.get());
FPHandler.reset();
@@ -591,6 +618,30 @@ void Parser::HandlePragmaFPContract() {
ConsumeAnnotationToken();
}
+void Parser::HandlePragmaFEnvAccess() {
+ assert(Tok.is(tok::annot_pragma_fenv_access));
+ tok::OnOffSwitch OOS =
+ static_cast<tok::OnOffSwitch>(
+ reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
+
+ LangOptions::FEnvAccessModeKind FPC;
+ switch (OOS) {
+ case tok::OOS_ON:
+ FPC = LangOptions::FEA_On;
+ break;
+ case tok::OOS_OFF:
+ FPC = LangOptions::FEA_Off;
+ break;
+ case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
+ FPC = LangOptions::FEA_Off;
+ break;
+ }
+
+ Actions.ActOnPragmaFEnvAccess(FPC);
+ ConsumeAnnotationToken();
+}
+
+
StmtResult Parser::HandlePragmaCaptured()
{
assert(Tok.is(tok::annot_pragma_captured));
@@ -955,6 +1006,8 @@ static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
if (PragmaName.getIdentifierInfo()->getName() == "loop") {
PragmaString = "clang loop ";
PragmaString += Option.getIdentifierInfo()->getName();
+ } else if (PragmaName.getIdentifierInfo()->getName() == "unroll_and_jam") {
+ PragmaString = "unroll_and_jam";
} else {
assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
"Unexpected pragma name");
@@ -986,7 +1039,10 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
// without an argument.
bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
- if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) {
+ bool PragmaUnrollAndJam = PragmaNameInfo->getName() == "unroll_and_jam";
+ bool PragmaNoUnrollAndJam = PragmaNameInfo->getName() == "nounroll_and_jam";
+ if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll || PragmaUnrollAndJam ||
+ PragmaNoUnrollAndJam)) {
ConsumeAnnotationToken();
Hint.Range = Info->PragmaName.getLocation();
return true;
@@ -999,24 +1055,31 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
// If no option is specified the argument is assumed to be a constant expr.
bool OptionUnroll = false;
+ bool OptionUnrollAndJam = false;
bool OptionDistribute = false;
+ bool OptionPipelineDisabled = false;
bool StateOption = false;
if (OptionInfo) { // Pragma Unroll does not specify an option.
OptionUnroll = OptionInfo->isStr("unroll");
+ OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
OptionDistribute = OptionInfo->isStr("distribute");
+ OptionPipelineDisabled = OptionInfo->isStr("pipeline");
StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
.Case("vectorize", true)
.Case("interleave", true)
.Default(false) ||
- OptionUnroll || OptionDistribute;
+ OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
+ OptionPipelineDisabled;
}
- bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute;
+ bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
+ !OptionDistribute && !OptionPipelineDisabled;
// Verify loop hint has an argument.
if (Toks[0].is(tok::eof)) {
ConsumeAnnotationToken();
Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
- << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll
+ << /*StateArgument=*/StateOption
+ << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
<< /*AssumeSafetyKeyword=*/AssumeSafetyArg;
return false;
}
@@ -1029,14 +1092,19 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
bool Valid = StateInfo &&
llvm::StringSwitch<bool>(StateInfo->getName())
- .Cases("enable", "disable", true)
- .Case("full", OptionUnroll)
+ .Case("disable", true)
+ .Case("enable", !OptionPipelineDisabled)
+ .Case("full", OptionUnroll || OptionUnrollAndJam)
.Case("assume_safety", AssumeSafetyArg)
.Default(false);
if (!Valid) {
- Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
- << /*FullKeyword=*/OptionUnroll
- << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
+ if (OptionPipelineDisabled) {
+ Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
+ } else {
+ Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
+ << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
+ << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
+ }
return false;
}
if (Toks.size() > 2)
@@ -1076,9 +1144,10 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
namespace {
struct PragmaAttributeInfo {
- enum ActionType { Push, Pop };
+ enum ActionType { Push, Pop, Attribute };
ParsedAttributes &Attributes;
ActionType Action;
+ const IdentifierInfo *Namespace = nullptr;
ArrayRef<Token> Tokens;
PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
@@ -1333,12 +1402,20 @@ void Parser::HandlePragmaAttribute() {
auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
if (Info->Action == PragmaAttributeInfo::Pop) {
ConsumeAnnotationToken();
- Actions.ActOnPragmaAttributePop(PragmaLoc);
+ Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
return;
}
// Parse the actual attribute with its arguments.
- assert(Info->Action == PragmaAttributeInfo::Push &&
+ assert((Info->Action == PragmaAttributeInfo::Push ||
+ Info->Action == PragmaAttributeInfo::Attribute) &&
"Unexpected #pragma attribute command");
+
+ if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
+ ConsumeAnnotationToken();
+ Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
+ return;
+ }
+
PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false);
ConsumeAnnotationToken();
@@ -1485,8 +1562,12 @@ void Parser::HandlePragmaAttribute() {
// Consume the eof terminator token.
ConsumeToken();
- Actions.ActOnPragmaAttributePush(Attribute, PragmaLoc,
- std::move(SubjectMatchRules));
+ // Handle a mixed push/attribute by desurging to a push, then an attribute.
+ if (Info->Action == PragmaAttributeInfo::Push)
+ Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
+
+ Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
+ std::move(SubjectMatchRules));
}
// #pragma GCC visibility comes in two variants:
@@ -2737,6 +2818,8 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
/// 'vectorize_width' '(' loop-hint-value ')'
/// 'interleave_count' '(' loop-hint-value ')'
/// 'unroll_count' '(' loop-hint-value ')'
+/// 'pipeline' '(' disable ')'
+/// 'pipeline_initiation_interval' '(' loop-hint-value ')'
///
/// loop-hint-keyword:
/// 'enable'
@@ -2796,6 +2879,8 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
.Case("vectorize_width", true)
.Case("interleave_count", true)
.Case("unroll_count", true)
+ .Case("pipeline", true)
+ .Case("pipeline_initiation_interval", true)
.Default(false);
if (!OptionValid) {
PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
@@ -2844,6 +2929,10 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
/// #pragma unroll unroll-hint-value
/// #pragma unroll '(' unroll-hint-value ')'
/// #pragma nounroll
+/// #pragma unroll_and_jam
+/// #pragma unroll_and_jam unroll-hint-value
+/// #pragma unroll_and_jam '(' unroll-hint-value ')'
+/// #pragma nounroll_and_jam
///
/// unroll-hint-value:
/// constant-expression
@@ -2868,9 +2957,10 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
// nounroll or unroll pragma without an argument.
Info->PragmaName = PragmaName;
Info->Option.startToken();
- } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
+ } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
+ PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "nounroll";
+ << PragmaName.getIdentifierInfo()->getName();
return;
} else {
// Unroll pragma with an argument: "#pragma unroll N" or
@@ -3041,10 +3131,22 @@ void PragmaForceCUDAHostDeviceHandler::HandlePragma(
///
/// The syntax is:
/// \code
-/// #pragma clang attribute push(attribute, subject-set)
+/// #pragma clang attribute push (attribute, subject-set)
+/// #pragma clang attribute push
+/// #pragma clang attribute (attribute, subject-set)
/// #pragma clang attribute pop
/// \endcode
///
+/// There are also 'namespace' variants of push and pop directives. The bare
+/// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
+/// namespace, since it always applies attributes to the most recently pushed
+/// group, regardless of namespace.
+/// \code
+/// #pragma clang attribute namespace.push (attribute, subject-set)
+/// #pragma clang attribute namespace.push
+/// #pragma clang attribute namespace.pop
+/// \endcode
+///
/// The subject-set clause defines the set of declarations which receive the
/// attribute. Its exact syntax is described in the LanguageExtensions document
/// in Clang's documentation.
@@ -3060,25 +3162,56 @@ void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
auto *Info = new (PP.getPreprocessorAllocator())
PragmaAttributeInfo(AttributesForPragmaAttribute);
- // Parse the 'push' or 'pop'.
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_push_pop);
- return;
+ // Parse the optional namespace followed by a period.
+ if (Tok.is(tok::identifier)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (!II->isStr("push") && !II->isStr("pop")) {
+ Info->Namespace = II;
+ PP.Lex(Tok);
+
+ if (!Tok.is(tok::period)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
+ << II;
+ return;
+ }
+ PP.Lex(Tok);
+ }
}
- const auto *II = Tok.getIdentifierInfo();
- if (II->isStr("push"))
- Info->Action = PragmaAttributeInfo::Push;
- else if (II->isStr("pop"))
- Info->Action = PragmaAttributeInfo::Pop;
- else {
- PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
- << PP.getSpelling(Tok);
+
+ if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
+ PP.Diag(Tok.getLocation(),
+ diag::err_pragma_attribute_expected_push_pop_paren);
return;
}
- PP.Lex(Tok);
+
+ // Determine what action this pragma clang attribute represents.
+ if (Tok.is(tok::l_paren)) {
+ if (Info->Namespace) {
+ PP.Diag(Tok.getLocation(),
+ diag::err_pragma_attribute_namespace_on_attribute);
+ PP.Diag(Tok.getLocation(),
+ diag::note_pragma_attribute_namespace_on_attribute);
+ return;
+ }
+ Info->Action = PragmaAttributeInfo::Attribute;
+ } else {
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II->isStr("push"))
+ Info->Action = PragmaAttributeInfo::Push;
+ else if (II->isStr("pop"))
+ Info->Action = PragmaAttributeInfo::Pop;
+ else {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
+ << PP.getSpelling(Tok);
+ return;
+ }
+
+ PP.Lex(Tok);
+ }
// Parse the actual attribute.
- if (Info->Action == PragmaAttributeInfo::Push) {
+ if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
+ Info->Action == PragmaAttributeInfo::Attribute) {
if (Tok.isNot(tok::l_paren)) {
PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
return;