Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -3083,7 +3083,7 @@ // 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 }; @@ -3254,6 +3254,12 @@ 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, Index: include/clang/Basic/LangOptions.h =================================================================== --- include/clang/Basic/LangOptions.h +++ include/clang/Basic/LangOptions.h @@ -137,6 +137,14 @@ FPC_Fast }; + // TODO: merge FENVAccessModeKind and FPContractModeKind + enum FENVAccessModeKind { + FEA_Off, + + FEA_On + }; + + public: /// Set of enabled sanitizers. SanitizerSet Sanitize; @@ -289,12 +297,24 @@ 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. Index: include/clang/Basic/TokenKinds.def =================================================================== --- include/clang/Basic/TokenKinds.def +++ include/clang/Basic/TokenKinds.def @@ -779,6 +779,11 @@ // 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. Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -668,6 +668,10 @@ 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(); Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -8433,6 +8433,10 @@ /// \#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); Index: lib/Parse/ParsePragma.cpp =================================================================== --- lib/Parse/ParsePragma.cpp +++ lib/Parse/ParsePragma.cpp @@ -106,8 +106,19 @@ 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 Toks(PP.getPreprocessorAllocator().Allocate(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( + static_cast(OOS))); + PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true); + } } }; @@ -591,6 +602,32 @@ ConsumeAnnotationToken(); } +void Parser::HandlePragmaFENVAccess() { + assert(Tok.is(tok::annot_pragma_fenv_access)); + tok::OnOffSwitch OOS = + static_cast( + reinterpret_cast(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; +#if NOTYET // FIXME: Add this cli option when it makes sense. + case tok::OOS_DEFAULT: + FPC = getLangOpts().getDefaultFENVAccessMode(); + break; +#endif + } + + Actions.ActOnPragmaFENVAccess(FPC); + ConsumeAnnotationToken(); +} + + StmtResult Parser::HandlePragmaCaptured() { assert(Tok.is(tok::annot_pragma_captured)); Index: lib/Parse/ParseStmt.cpp =================================================================== --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -348,6 +348,12 @@ ConsumeAnnotationToken(); return StmtError(); + case tok::annot_pragma_fenv_access: + ProhibitAttributes(Attrs); + //Diag(Tok, diag::err_pragma_fp_scope); + HandlePragmaFENVAccess(); + return StmtEmpty(); + case tok::annot_pragma_opencl_extension: ProhibitAttributes(Attrs); HandlePragmaOpenCLExtension(); @@ -914,6 +920,9 @@ 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; Index: lib/Parse/Parser.cpp =================================================================== --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -674,6 +674,9 @@ 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; Index: lib/Sema/SemaAttr.cpp =================================================================== --- lib/Sema/SemaAttr.cpp +++ lib/Sema/SemaAttr.cpp @@ -773,6 +773,18 @@ } } +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.