diff options
author | Kevin P. Neal <kevin.neal@sas.com> | 2018-08-14 17:06:56 +0000 |
---|---|---|
committer | Kevin P. Neal <kevin.neal@sas.com> | 2018-08-14 17:06:56 +0000 |
commit | 26dbd400930e046ea1730e14fd70a9e3c16cb14a (patch) | |
tree | e673171dee3bf6f0f06fe09e57dfd500d2792f43 | |
parent | 7964dc77eed2dd83115b7672dbd57ea7d468cd33 (diff) |
We have in place support for parsing #pragma FENV_ACCESS, but that
information is then discarded with a warning to the user that we don't
support it.
This patch gets us one step closer by getting the info down into the
AST in most cases.
Reviewed by: rsmith
Differential Revision: https://reviews.llvm.org/D49865
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@339693 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/Expr.h | 8 | ||||
-rw-r--r-- | include/clang/Basic/LangOptions.h | 35 | ||||
-rw-r--r-- | include/clang/Basic/TokenKinds.def | 5 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 4 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 4 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.cpp | 37 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 8 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaAttr.cpp | 12 |
9 files changed, 109 insertions, 7 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 0a457d6b97..474b796ea6 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -3269,7 +3269,7 @@ private: // This is only meaningful for operations on floating point types and 0 // otherwise. - unsigned FPFeatures : 2; + unsigned FPFeatures : 3; SourceLocation OpLoc; enum { LHS, RHS, END_EXPR }; @@ -3448,6 +3448,12 @@ public: return FPOptions(FPFeatures).allowFPContractWithinStatement(); } + // Get the FENV_ACCESS status of this operator. Only meaningful for + // operations on floating point types. + bool isFEnvAccessOn() const { + return FPOptions(FPFeatures).allowFEnvAccess(); + } + protected: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index a1396f8435..a7a5105fdf 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -137,6 +137,14 @@ public: FPC_Fast }; + // TODO: merge FEnvAccessModeKind and FPContractModeKind + enum FEnvAccessModeKind { + FEA_Off, + + FEA_On + }; + + public: /// Set of enabled sanitizers. SanitizerSet Sanitize; @@ -262,14 +270,19 @@ public: /// Floating point control options class FPOptions { public: - FPOptions() : fp_contract(LangOptions::FPC_Off) {} + FPOptions() : fp_contract(LangOptions::FPC_Off), + fenv_access(LangOptions::FEA_Off) {} // Used for serializing. explicit FPOptions(unsigned I) - : fp_contract(static_cast<LangOptions::FPContractModeKind>(I)) {} + : fp_contract(static_cast<LangOptions::FPContractModeKind>(I & 3)), + fenv_access(static_cast<LangOptions::FEnvAccessModeKind>((I >> 2) & 1)) + {} explicit FPOptions(const LangOptions &LangOpts) - : fp_contract(LangOpts.getDefaultFPContractMode()) {} + : fp_contract(LangOpts.getDefaultFPContractMode()), + fenv_access(LangOptions::FEA_Off) {} + // FIXME: Use getDefaultFEnvAccessMode() when available. bool allowFPContractWithinStatement() const { return fp_contract == LangOptions::FPC_On; @@ -289,12 +302,24 @@ public: void setDisallowFPContract() { fp_contract = LangOptions::FPC_Off; } + bool allowFEnvAccess() const { + return fenv_access == LangOptions::FEA_On; + } + + void setAllowFEnvAccess() { + fenv_access = LangOptions::FEA_On; + } + + void setDisallowFEnvAccess() { fenv_access = LangOptions::FEA_Off; } + /// Used to serialize this. - unsigned getInt() const { return fp_contract; } + unsigned getInt() const { return fp_contract | (fenv_access << 2); } private: - /// Adjust BinaryOperator::FPFeatures to match the bit-field size of this. + /// Adjust BinaryOperator::FPFeatures to match the total bit-field size + /// of these two. unsigned fp_contract : 2; + unsigned fenv_access : 1; }; /// Describes the kind of translation unit being processed. diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 30cb022f1c..caea67adba 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -780,6 +780,11 @@ ANNOTATION(pragma_redefine_extname) // handles them. ANNOTATION(pragma_fp_contract) +// Annotation for #pragma STDC FENV_ACCESS +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_fenv_access) + // Annotation for #pragma pointers_to_members... // The lexer produces these so that they only take effect when the parser // handles them. diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 1d6849cd5b..32874ee44f 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -670,6 +670,10 @@ private: void HandlePragmaFPContract(); /// Handle the annotation token produced for + /// #pragma STDC FENV_ACCESS... + void HandlePragmaFEnvAccess(); + + /// \brief Handle the annotation token produced for /// #pragma clang fp ... void HandlePragmaFP(); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index b3d1c96bdf..aa6e4b7cfe 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -8434,6 +8434,10 @@ public: /// \#pragma clang fp contract void ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC); + /// ActOnPragmaFenvAccess - Called on well formed + /// \#pragma STDC FENV_ACCESS + void ActOnPragmaFEnvAccess(LangOptions::FEnvAccessModeKind FPC); + /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'. void AddAlignmentAttributesForRecord(RecordDecl *RD); diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index fb862c706f..26b363f280 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -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); } }; @@ -604,6 +615,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)); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 338a8ab7e8..574293f518 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -348,6 +348,11 @@ Retry: ConsumeAnnotationToken(); return StmtError(); + case tok::annot_pragma_fenv_access: + ProhibitAttributes(Attrs); + HandlePragmaFEnvAccess(); + return StmtEmpty(); + case tok::annot_pragma_opencl_extension: ProhibitAttributes(Attrs); HandlePragmaOpenCLExtension(); @@ -902,6 +907,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_fp: HandlePragmaFP(); break; + case tok::annot_pragma_fenv_access: + HandlePragmaFEnvAccess(); + break; case tok::annot_pragma_ms_pointers_to_members: HandlePragmaMSPointersToMembers(); break; diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index c3085654f5..1736629121 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -674,6 +674,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_fp_contract: HandlePragmaFPContract(); return nullptr; + case tok::annot_pragma_fenv_access: + HandlePragmaFEnvAccess(); + return nullptr; case tok::annot_pragma_fp: HandlePragmaFP(); break; diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index 056d031fd8..8024e1a051 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -773,6 +773,18 @@ void Sema::ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC) { } } +void Sema::ActOnPragmaFEnvAccess(LangOptions::FEnvAccessModeKind FPC) { + switch (FPC) { + case LangOptions::FEA_On: + FPFeatures.setAllowFEnvAccess(); + break; + case LangOptions::FEA_Off: + FPFeatures.setDisallowFEnvAccess(); + break; + } +} + + void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, SourceLocation Loc) { // Visibility calculations will consider the namespace's visibility. |