From: Eli Friedman Date: Thu, 4 Oct 2012 02:36:51 +0000 (+0000) Subject: Permanently end the whole "pragma got handled by the parser too early" X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9595c7e2533c836537dc300e75d059c29feb7094;p=clang Permanently end the whole "pragma got handled by the parser too early" mess by handling all pragmas which the parser touches uniformly. , etc. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165195 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 4561f8709f..cac57d39cd 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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< diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 9b61403f45..25e8d5a635 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -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 diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 25fe4cf4aa..20b13baf69 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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. diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 1847220ddf..2a6d4bbe88 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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]) diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index eb13e0d357..a7605f0cf4 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -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(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( + reinterpret_cast(Tok.getAnnotationValue())); + Actions.ActOnPragmaMSStruct(Kind); + ConsumeToken(); // The annotation token. +} + +void Parser::HandlePragmaAlign() { + assert(Tok.is(tok::annot_pragma_align)); + Sema::PragmaOptionsAlignKind Kind = + static_cast( + reinterpret_cast(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( + reinterpret_cast(Tok.getAnnotationValue())); + Actions.ActOnPragmaFPContract(OOS); + ConsumeToken(); // The annotation token. +} + +namespace { + typedef llvm::PointerIntPair 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()); + new (Toks) Token(); + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_msstruct); + Toks[0].setLocation(MSStructTok.getLocation()); + Toks[0].setAnnotationValue(reinterpret_cast( + static_cast(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()); + new (Toks) Token(); + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_align); + Toks[0].setLocation(FirstTok.getLocation()); + Toks[0].setAnnotationValue(reinterpret_cast( + static_cast(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 &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 &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 &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()); + new (Toks) Token(); + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_fp_contract); + Toks[0].setLocation(Tok.getLocation()); + Toks[0].setAnnotationValue(reinterpret_cast( + static_cast(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()); + 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); } diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h index fef6960813..b9a2a251fc 100644 --- a/lib/Parse/ParsePragma.h +++ b/lib/Parse/ParsePragma.h @@ -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); }; diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index eb2a672fdc..776423c28b 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -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. diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 2b19c973ce..99c36365c3 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -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. diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index e935fc735b..f1154c1a8a 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -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(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; } } diff --git a/test/CodeGen/fp-contract-pragma.cpp b/test/CodeGen/fp-contract-pragma.cpp index 723ac1f463..9be9afc4c2 100644 --- a/test/CodeGen/fp-contract-pragma.cpp +++ b/test/CodeGen/fp-contract-pragma.cpp @@ -34,3 +34,15 @@ float fp_contract_3(float a, float b, float c) { // CHECK: tail call float @llvm.fmuladd return template_muladd(a, b, c); } + +template 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; +// CHECK: _ZN13fp_contract_4IiE6methodEfff +// CHECK: tail call float @llvm.fmuladd diff --git a/test/Misc/warning-flags.c b/test/Misc/warning-flags.c index fb5cd5cc27..6c7643c004 100644 --- a/test/Misc/warning-flags.c +++ b/test/Misc/warning-flags.c @@ -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 diff --git a/test/Sema/pragma-pack-and-options-align.c b/test/Sema/pragma-pack-and-options-align.c index ebf1adee02..5bc7c83594 100644 --- a/test/Sema/pragma-pack-and-options-align.c +++ b/test/Sema/pragma-pack-and-options-align.c @@ -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) +