Permanently end the whole "pragma got handled by the parser too early"

mess by handling all pragmas which the parser touches uniformly.
<rdar://problem/12248901>, etc.

llvm-svn: 165195
This commit is contained in:
Eli Friedman 2012-10-04 02:36:51 +00:00
parent 0b744b3105
commit 68be1649ee
12 changed files with 347 additions and 106 deletions

View File

@ -407,8 +407,6 @@ def err_object_cannot_be_passed_returned_by_value : Error<
def err_parameters_retval_cannot_have_fp16_type : Error<
"%select{parameters|function return value}0 cannot have __fp16 type; did you forget * ?">;
def warn_enum_value_overflow : Warning<"overflow in enumeration value">;
def warn_pragma_options_align_unsupported_option : Warning<
"unsupported alignment option in '#pragma options align'">;
def warn_pragma_options_align_reset_failed : Warning<
"#pragma options align=reset failed: %0">;
def err_pragma_options_align_mac68k_target_unsupported : Error<

View File

@ -602,6 +602,41 @@ ANNOTATION(pragma_pack)
// handles them.
ANNOTATION(pragma_parser_crash)
// Annotation for #pragma ms_struct...
// The lexer produces these so that they only take effect when the parser
// handles them.
ANNOTATION(pragma_msstruct)
// Annotation for #pragma align...
// The lexer produces these so that they only take effect when the parser
// handles them.
ANNOTATION(pragma_align)
// Annotation for #pragma weak id
// The lexer produces these so that they only take effect when the parser
// handles them.
ANNOTATION(pragma_weak)
// Annotation for #pragma weak id = id
// The lexer produces these so that they only take effect when the parser
// handles them.
ANNOTATION(pragma_weakalias)
// Annotation for #pragma redefine_extname...
// The lexer produces these so that they only take effect when the parser
// handles them.
ANNOTATION(pragma_redefine_extname)
// Annotation for #pragma STDC FP_CONTRACT...
// The lexer produces these so that they only take effect when the parser
// handles them.
ANNOTATION(pragma_fp_contract)
// Annotation for #pragma OPENCL EXTENSION...
// The lexer produces these so that they only take effect when the parser
// handles them.
ANNOTATION(pragma_opencl_extension)
#undef ANNOTATION
#undef TESTING_KEYWORD
#undef OBJC2_AT_KEYWORD

View File

@ -441,6 +441,34 @@ private:
/// #pragma pack...
void HandlePragmaPack();
/// \brief Handle the annotation token produced for
/// #pragma ms_struct...
void HandlePragmaMSStruct();
/// \brief Handle the annotation token produced for
/// #pragma align...
void HandlePragmaAlign();
/// \brief Handle the annotation token produced for
/// #pragma weak id...
void HandlePragmaWeak();
/// \brief Handle the annotation token produced for
/// #pragma weak id = id...
void HandlePragmaWeakAlias();
/// \brief Handle the annotation token produced for
/// #pragma redefine_extname...
void HandlePragmaRedefineExtname();
/// \brief Handle the annotation token produced for
/// #pragma STDC FP_CONTRACT...
void HandlePragmaFPContract();
/// \brief Handle the annotation token produced for
/// #pragma OPENCL EXTENSION...
void HandlePragmaOpenCLExtension();
/// GetLookAheadToken - This peeks ahead N tokens and returns that token
/// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1)
/// returns the token after Tok, etc.

View File

@ -6328,8 +6328,7 @@ public:
/// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align.
void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
SourceLocation PragmaLoc,
SourceLocation KindLoc);
SourceLocation PragmaLoc);
enum PragmaPackKind {
PPK_Default, // #pragma pack([n])

View File

@ -40,7 +40,7 @@ void Parser::HandlePragmaVisibility() {
struct PragmaPackInfo {
Sema::PragmaPackKind Kind;
IdentifierInfo *Name;
Expr *Alignment;
Token Alignment;
SourceLocation LParenLoc;
SourceLocation RParenLoc;
};
@ -50,10 +50,107 @@ void Parser::HandlePragmaPack() {
PragmaPackInfo *Info =
static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
SourceLocation PragmaLoc = ConsumeToken();
Actions.ActOnPragmaPack(Info->Kind, Info->Name, Info->Alignment, PragmaLoc,
ExprResult Alignment;
if (Info->Alignment.is(tok::numeric_constant)) {
Alignment = Actions.ActOnNumericConstant(Info->Alignment);
if (Alignment.isInvalid())
return;
}
Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
Info->LParenLoc, Info->RParenLoc);
}
void Parser::HandlePragmaMSStruct() {
assert(Tok.is(tok::annot_pragma_msstruct));
Sema::PragmaMSStructKind Kind =
static_cast<Sema::PragmaMSStructKind>(
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Actions.ActOnPragmaMSStruct(Kind);
ConsumeToken(); // The annotation token.
}
void Parser::HandlePragmaAlign() {
assert(Tok.is(tok::annot_pragma_align));
Sema::PragmaOptionsAlignKind Kind =
static_cast<Sema::PragmaOptionsAlignKind>(
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
SourceLocation PragmaLoc = ConsumeToken();
Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
}
void Parser::HandlePragmaWeak() {
assert(Tok.is(tok::annot_pragma_weak));
SourceLocation PragmaLoc = ConsumeToken();
Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
Tok.getLocation());
ConsumeToken(); // The weak name.
}
void Parser::HandlePragmaWeakAlias() {
assert(Tok.is(tok::annot_pragma_weakalias));
SourceLocation PragmaLoc = ConsumeToken();
IdentifierInfo *WeakName = Tok.getIdentifierInfo();
SourceLocation WeakNameLoc = Tok.getLocation();
ConsumeToken();
IdentifierInfo *AliasName = Tok.getIdentifierInfo();
SourceLocation AliasNameLoc = Tok.getLocation();
ConsumeToken();
Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
WeakNameLoc, AliasNameLoc);
}
void Parser::HandlePragmaRedefineExtname() {
assert(Tok.is(tok::annot_pragma_redefine_extname));
SourceLocation RedefLoc = ConsumeToken();
IdentifierInfo *RedefName = Tok.getIdentifierInfo();
SourceLocation RedefNameLoc = Tok.getLocation();
ConsumeToken();
IdentifierInfo *AliasName = Tok.getIdentifierInfo();
SourceLocation AliasNameLoc = Tok.getLocation();
ConsumeToken();
Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
RedefNameLoc, AliasNameLoc);
}
void Parser::HandlePragmaFPContract() {
assert(Tok.is(tok::annot_pragma_fp_contract));
tok::OnOffSwitch OOS =
static_cast<tok::OnOffSwitch>(
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Actions.ActOnPragmaFPContract(OOS);
ConsumeToken(); // The annotation token.
}
namespace {
typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
}
void Parser::HandlePragmaOpenCLExtension() {
assert(Tok.is(tok::annot_pragma_opencl_extension));
OpenCLExtData data =
OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
unsigned state = data.getInt();
IdentifierInfo *ename = data.getPointer();
SourceLocation NameLoc = Tok.getLocation();
ConsumeToken(); // The annotation token.
OpenCLOptions &f = Actions.getOpenCLOptions();
// OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
// overriding all previously issued extension directives, but only if the
// behavior is set to disable."
if (state == 0 && ename->isStr("all")) {
#define OPENCLEXT(nm) f.nm = 0;
#include "clang/Basic/OpenCLExtensions.def"
}
#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
#include "clang/Basic/OpenCLExtensions.def"
else {
PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
return;
}
}
// #pragma GCC visibility comes in two variants:
// 'push' '(' [visibility] ')'
// 'pop'
@ -130,13 +227,12 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
Sema::PragmaPackKind Kind = Sema::PPK_Default;
IdentifierInfo *Name = 0;
ExprResult Alignment;
Token Alignment;
Alignment.startToken();
SourceLocation LParenLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.is(tok::numeric_constant)) {
Alignment = Actions.ActOnNumericConstant(Tok);
if (Alignment.isInvalid())
return;
Alignment = Tok;
PP.Lex(Tok);
@ -165,9 +261,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
PP.Lex(Tok);
if (Tok.is(tok::numeric_constant)) {
Alignment = Actions.ActOnNumericConstant(Tok);
if (Alignment.isInvalid())
return;
Alignment = Tok;
PP.Lex(Tok);
} else if (Tok.is(tok::identifier)) {
@ -182,9 +276,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
return;
}
Alignment = Actions.ActOnNumericConstant(Tok);
if (Alignment.isInvalid())
return;
Alignment = Tok;
PP.Lex(Tok);
}
@ -219,7 +311,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
new (Info) PragmaPackInfo();
Info->Kind = Kind;
Info->Name = Name;
Info->Alignment = Alignment.release();
Info->Alignment = Alignment;
Info->LParenLoc = LParenLoc;
Info->RParenLoc = RParenLoc;
@ -265,12 +357,23 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
<< "ms_struct";
return;
}
Actions.ActOnPragmaMSStruct(Kind);
Token *Toks =
(Token*) PP.getPreprocessorAllocator().Allocate(
sizeof(Token) * 1, llvm::alignOf<Token>());
new (Toks) Token();
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_msstruct);
Toks[0].setLocation(MSStructTok.getLocation());
Toks[0].setAnnotationValue(reinterpret_cast<void*>(
static_cast<uintptr_t>(Kind)));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
/*OwnsTokens=*/false);
}
// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
bool IsOptions) {
Token Tok;
@ -317,7 +420,6 @@ static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
return;
}
SourceLocation KindLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
@ -325,19 +427,29 @@ static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
return;
}
Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
Token *Toks =
(Token*) PP.getPreprocessorAllocator().Allocate(
sizeof(Token) * 1, llvm::alignOf<Token>());
new (Toks) Token();
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_align);
Toks[0].setLocation(FirstTok.getLocation());
Toks[0].setAnnotationValue(reinterpret_cast<void*>(
static_cast<uintptr_t>(Kind)));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
/*OwnsTokens=*/false);
}
void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &AlignTok) {
ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
}
void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &OptionsTok) {
ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
}
// #pragma unused(identifier)
@ -426,7 +538,6 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &WeakTok) {
// FIXME: Should we be expanding macros here? My guess is no.
SourceLocation WeakLoc = WeakTok.getLocation();
Token Tok;
@ -436,19 +547,20 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
return;
}
IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
Token WeakName = Tok;
bool HasAlias = false;
Token AliasName;
PP.Lex(Tok);
if (Tok.is(tok::equal)) {
HasAlias = true;
PP.Lex(Tok);
if (Tok.isNot(tok::identifier)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
<< "weak";
return;
}
AliasName = Tok.getIdentifierInfo();
AliasNameLoc = Tok.getLocation();
AliasName = Tok;
PP.Lex(Tok);
}
@ -457,11 +569,29 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
return;
}
if (AliasName) {
Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
AliasNameLoc);
if (HasAlias) {
Token *Toks =
(Token*) PP.getPreprocessorAllocator().Allocate(
sizeof(Token) * 3, llvm::alignOf<Token>());
Token &pragmaUnusedTok = Toks[0];
pragmaUnusedTok.startToken();
pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
pragmaUnusedTok.setLocation(WeakLoc);
Toks[1] = WeakName;
Toks[2] = AliasName;
PP.EnterTokenStream(Toks, 3,
/*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
} else {
Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
Token *Toks =
(Token*) PP.getPreprocessorAllocator().Allocate(
sizeof(Token) * 2, llvm::alignOf<Token>());
Token &pragmaUnusedTok = Toks[0];
pragmaUnusedTok.startToken();
pragmaUnusedTok.setKind(tok::annot_pragma_weak);
pragmaUnusedTok.setLocation(WeakLoc);
Toks[1] = WeakName;
PP.EnterTokenStream(Toks, 2,
/*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
}
}
@ -479,17 +609,16 @@ void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
return;
}
IdentifierInfo *RedefName = Tok.getIdentifierInfo(), *AliasName = 0;
SourceLocation RedefNameLoc = Tok.getLocation(), AliasNameLoc;
Token RedefName = Tok;
PP.Lex(Tok);
if (Tok.isNot(tok::identifier)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
<< "redefine_extname";
return;
}
AliasName = Tok.getIdentifierInfo();
AliasNameLoc = Tok.getLocation();
Token AliasName = Tok;
PP.Lex(Tok);
if (Tok.isNot(tok::eod)) {
@ -498,8 +627,17 @@ void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
return;
}
Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
RedefNameLoc, AliasNameLoc);
Token *Toks =
(Token*) PP.getPreprocessorAllocator().Allocate(
sizeof(Token) * 3, llvm::alignOf<Token>());
Token &pragmaRedefTok = Toks[0];
pragmaRedefTok.startToken();
pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
pragmaRedefTok.setLocation(RedefLoc);
Toks[1] = RedefName;
Toks[2] = AliasName;
PP.EnterTokenStream(Toks, 3,
/*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
}
@ -511,7 +649,17 @@ PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
if (PP.LexOnOffSwitch(OOS))
return;
Actions.ActOnPragmaFPContract(OOS);
Token *Toks =
(Token*) PP.getPreprocessorAllocator().Allocate(
sizeof(Token) * 1, llvm::alignOf<Token>());
new (Toks) Token();
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_fp_contract);
Toks[0].setLocation(Tok.getLocation());
Toks[0].setAnnotationValue(reinterpret_cast<void*>(
static_cast<uintptr_t>(OOS)));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
/*OwnsTokens=*/false);
}
void
@ -550,19 +698,23 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
return;
}
OpenCLOptions &f = Actions.getOpenCLOptions();
// OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
// overriding all previously issued extension directives, but only if the
// behavior is set to disable."
if (state == 0 && ename->isStr("all")) {
#define OPENCLEXT(nm) f.nm = 0;
#include "clang/Basic/OpenCLExtensions.def"
}
#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
#include "clang/Basic/OpenCLExtensions.def"
else {
PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
PP.Lex(Tok);
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
"OPENCL EXTENSION";
return;
}
OpenCLExtData data(ename, state);
Token *Toks =
(Token*) PP.getPreprocessorAllocator().Allocate(
sizeof(Token) * 1, llvm::alignOf<Token>());
new (Toks) Token();
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_opencl_extension);
Toks[0].setLocation(NameLoc);
Toks[0].setAnnotationValue(data.getOpaqueValue());
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
/*OwnsTokens=*/false);
}

View File

@ -21,9 +21,8 @@ namespace clang {
class Parser;
class PragmaAlignHandler : public PragmaHandler {
Sema &Actions;
public:
explicit PragmaAlignHandler(Sema &A) : PragmaHandler("align"), Actions(A) {}
explicit PragmaAlignHandler() : PragmaHandler("align") {}
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken);
@ -31,38 +30,31 @@ public:
class PragmaGCCVisibilityHandler : public PragmaHandler {
public:
explicit PragmaGCCVisibilityHandler(Sema &/*A*/)
: PragmaHandler("visibility") {}
explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken);
};
class PragmaOptionsHandler : public PragmaHandler {
Sema &Actions;
public:
explicit PragmaOptionsHandler(Sema &A) : PragmaHandler("options"),
Actions(A) {}
explicit PragmaOptionsHandler() : PragmaHandler("options") {}
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken);
};
class PragmaPackHandler : public PragmaHandler {
Sema &Actions;
public:
explicit PragmaPackHandler(Sema &A) : PragmaHandler("pack"),
Actions(A) {}
explicit PragmaPackHandler() : PragmaHandler("pack") {}
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken);
};
class PragmaMSStructHandler : public PragmaHandler {
Sema &Actions;
public:
explicit PragmaMSStructHandler(Sema &A) : PragmaHandler("ms_struct"),
Actions(A) {}
explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken);
@ -70,48 +62,39 @@ public:
class PragmaUnusedHandler : public PragmaHandler {
public:
PragmaUnusedHandler(Sema &/*A*/)
: PragmaHandler("unused") {}
PragmaUnusedHandler() : PragmaHandler("unused") {}
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken);
};
class PragmaWeakHandler : public PragmaHandler {
Sema &Actions;
public:
explicit PragmaWeakHandler(Sema &A)
: PragmaHandler("weak"), Actions(A) {}
explicit PragmaWeakHandler() : PragmaHandler("weak") {}
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken);
};
class PragmaRedefineExtnameHandler : public PragmaHandler {
Sema &Actions;
public:
explicit PragmaRedefineExtnameHandler(Sema &A)
: PragmaHandler("redefine_extname"), Actions(A) {}
explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken);
};
class PragmaOpenCLExtensionHandler : public PragmaHandler {
Sema &Actions;
public:
PragmaOpenCLExtensionHandler(Sema &A) :
PragmaHandler("EXTENSION"), Actions(A) {}
PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken);
};
class PragmaFPContractHandler : public PragmaHandler {
Sema &Actions;
public:
PragmaFPContractHandler(Sema &A) :
PragmaHandler("FP_CONTRACT"), Actions(A) {}
PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken);
};

View File

@ -253,6 +253,16 @@ Retry:
ProhibitAttributes(Attrs);
HandlePragmaPack();
return StmtEmpty();
case tok::annot_pragma_fp_contract:
ProhibitAttributes(Attrs);
HandlePragmaFPContract();
return StmtEmpty();
case tok::annot_pragma_opencl_extension:
ProhibitAttributes(Attrs);
HandlePragmaOpenCLExtension();
return StmtEmpty();
}
// If we reached this code, the statement must end in a semicolon.

View File

@ -60,35 +60,35 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool SkipFunctionBodies)
// Add #pragma handlers. These are removed and destroyed in the
// destructor.
AlignHandler.reset(new PragmaAlignHandler(actions));
AlignHandler.reset(new PragmaAlignHandler());
PP.AddPragmaHandler(AlignHandler.get());
GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler(actions));
GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
OptionsHandler.reset(new PragmaOptionsHandler(actions));
OptionsHandler.reset(new PragmaOptionsHandler());
PP.AddPragmaHandler(OptionsHandler.get());
PackHandler.reset(new PragmaPackHandler(actions));
PackHandler.reset(new PragmaPackHandler());
PP.AddPragmaHandler(PackHandler.get());
MSStructHandler.reset(new PragmaMSStructHandler(actions));
MSStructHandler.reset(new PragmaMSStructHandler());
PP.AddPragmaHandler(MSStructHandler.get());
UnusedHandler.reset(new PragmaUnusedHandler(actions));
UnusedHandler.reset(new PragmaUnusedHandler());
PP.AddPragmaHandler(UnusedHandler.get());
WeakHandler.reset(new PragmaWeakHandler(actions));
WeakHandler.reset(new PragmaWeakHandler());
PP.AddPragmaHandler(WeakHandler.get());
RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler(actions));
RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
PP.AddPragmaHandler(RedefineExtnameHandler.get());
FPContractHandler.reset(new PragmaFPContractHandler(actions));
FPContractHandler.reset(new PragmaFPContractHandler());
PP.AddPragmaHandler("STDC", FPContractHandler.get());
if (getLangOpts().OpenCL) {
OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler(actions));
OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
@ -635,6 +635,27 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
case tok::annot_pragma_pack:
HandlePragmaPack();
return DeclGroupPtrTy();
case tok::annot_pragma_msstruct:
HandlePragmaMSStruct();
return DeclGroupPtrTy();
case tok::annot_pragma_align:
HandlePragmaAlign();
return DeclGroupPtrTy();
case tok::annot_pragma_weak:
HandlePragmaWeak();
return DeclGroupPtrTy();
case tok::annot_pragma_weakalias:
HandlePragmaWeakAlias();
return DeclGroupPtrTy();
case tok::annot_pragma_redefine_extname:
HandlePragmaRedefineExtname();
return DeclGroupPtrTy();
case tok::annot_pragma_fp_contract:
HandlePragmaFPContract();
return DeclGroupPtrTy();
case tok::annot_pragma_opencl_extension:
HandlePragmaOpenCLExtension();
return DeclGroupPtrTy();
case tok::semi:
ConsumeExtraSemi(OutsideFunction);
// TODO: Invoke action for top-level semicolon.

View File

@ -136,23 +136,12 @@ void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
}
void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
SourceLocation PragmaLoc,
SourceLocation KindLoc) {
SourceLocation PragmaLoc) {
if (PackContext == 0)
PackContext = new PragmaPackStack();
PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
// Reset just pops the top of the stack, or resets the current alignment to
// default.
if (Kind == Sema::POAK_Reset) {
if (!Context->pop(0, /*IsReset=*/true)) {
Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
<< "stack empty";
}
return;
}
switch (Kind) {
// For all targets we support native and natural are the same.
//
@ -181,9 +170,13 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
break;
default:
Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
<< KindLoc;
case POAK_Reset:
// Reset just pops the top of the stack, or resets the current alignment to
// default.
if (!Context->pop(0, /*IsReset=*/true)) {
Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
<< "stack empty";
}
break;
}
}

View File

@ -34,3 +34,15 @@ float fp_contract_3(float a, float b, float c) {
// CHECK: tail call float @llvm.fmuladd
return template_muladd<float>(a, b, c);
}
template<typename T> class fp_contract_4 {
float method(float a, float b, float c) {
#pragma STDC FP_CONTRACT ON
return a * b + c;
#pragma STDC FP_CONTRACT OFF
}
};
template class fp_contract_4<int>;
// CHECK: _ZN13fp_contract_4IiE6methodEfff
// CHECK: tail call float @llvm.fmuladd

View File

@ -18,7 +18,7 @@ This test serves two purposes:
The list of warnings below should NEVER grow. It should gradually shrink to 0.
CHECK: Warnings without flags (158):
CHECK: Warnings without flags (157):
CHECK-NEXT: ext_delete_void_ptr_operand
CHECK-NEXT: ext_enum_friend
CHECK-NEXT: ext_expected_semi_decl_list
@ -133,7 +133,6 @@ CHECK-NEXT: warn_pragma_expected_rparen
CHECK-NEXT: warn_pragma_extra_tokens_at_eol
CHECK-NEXT: warn_pragma_ms_struct
CHECK-NEXT: warn_pragma_options_align_reset_failed
CHECK-NEXT: warn_pragma_options_align_unsupported_option
CHECK-NEXT: warn_pragma_options_expected_align
CHECK-NEXT: warn_pragma_pack_invalid_action
CHECK-NEXT: warn_pragma_pack_invalid_alignment

View File

@ -38,5 +38,16 @@ struct s3 {
};
extern int a[sizeof(struct s3) == 8 ? 1 : -1];
#pragma pack(push,2)
#pragma options align=power
struct s4 {
char c;
int x;
};
#pragma pack(pop)
#pragma options align=reset
extern int a[sizeof(struct s4) == 8 ? 1 : -1];
/* expected-warning {{#pragma options align=reset failed: stack empty}} */ #pragma options align=reset
/* expected-warning {{#pragma pack(pop, ...) failed: stack empty}} */ #pragma pack(pop)