diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -531,7 +531,7 @@ /// This is only meaningful for operations on floating point /// types and 0 otherwise. - unsigned FPFeatures : 8; + unsigned FPFeatures : 7; SourceLocation OpLoc; }; @@ -614,7 +614,7 @@ unsigned OperatorKind : 6; // Only meaningful for floating point types. - unsigned FPFeatures : 8; + unsigned FPFeatures : 7; }; class CXXRewrittenBinaryOperatorBitfields { diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -356,26 +356,24 @@ /// Floating point control options class FPOptions { public: - FPOptions() : fp_contract(LangOptions::FPC_Off), - fenv_access(LangOptions::FEA_Off), - rounding(LangOptions::FPR_ToNearest), - exceptions(LangOptions::FPE_Ignore) - {} + FPOptions() + : fp_contract(LangOptions::FPC_Off), fenv_access(LangOptions::FEA_Off) { + setRoundingAndExceptionMode(LangOptions::FPR_ToNearest, + LangOptions::FPE_Ignore); + } // Used for serializing. explicit FPOptions(unsigned I) : fp_contract(static_cast(I & 3)), fenv_access(static_cast((I >> 2) & 1)), - rounding(static_cast((I >> 3) & 7)), - exceptions(static_cast((I >> 6) & 3)) - {} + rounding_and_exceptions(I >> 3) {} explicit FPOptions(const LangOptions &LangOpts) : fp_contract(LangOpts.getDefaultFPContractMode()), - fenv_access(LangOptions::FEA_Off), - rounding(LangOptions::FPR_ToNearest), - exceptions(LangOptions::FPE_Ignore) - {} + fenv_access(LangOptions::FEA_Off) { + setRoundingAndExceptionMode(LangOptions::FPR_ToNearest, + LangOptions::FPE_Ignore); + } // FIXME: Use getDefaultFEnvAccessMode() when available. bool allowFPContractWithinStatement() const { @@ -407,19 +405,19 @@ void setDisallowFEnvAccess() { fenv_access = LangOptions::FEA_Off; } LangOptions::FPRoundingModeKind getRoundingMode() const { - return static_cast(rounding); + return getRoundingAndExceptionMode().first; } void setRoundingMode(LangOptions::FPRoundingModeKind RM) { - rounding = RM; + setRoundingAndExceptionMode(RM, getExceptionMode()); } LangOptions::FPExceptionModeKind getExceptionMode() const { - return static_cast(exceptions); + return getRoundingAndExceptionMode().second; } void setExceptionMode(LangOptions::FPExceptionModeKind EM) { - exceptions = EM; + setRoundingAndExceptionMode(getRoundingMode(), EM); } bool isFPConstrained() const { @@ -430,18 +428,37 @@ /// Used to serialize this. unsigned getInt() const { - return fp_contract | (fenv_access << 2) | (rounding << 3) - | (exceptions << 6); + return fp_contract | (fenv_access << 2) | (rounding_and_exceptions << 3); } private: + void setRoundingAndExceptionMode(LangOptions::FPRoundingModeKind RM, + LangOptions::FPExceptionModeKind EM) { + static_assert(LangOptions::FPExceptionModeKind::FPE_Strict < + MaxExceptionValue, + "Max exception value must be less than 3"); + rounding_and_exceptions = RM * MaxExceptionValue + EM; + } + + std::pair + getRoundingAndExceptionMode() const { + unsigned exceptions = rounding_and_exceptions % MaxExceptionValue; + unsigned rounding = rounding_and_exceptions / MaxExceptionValue; + return {static_cast(rounding), + static_cast(exceptions)}; + } + + /// Adjust BinaryOperatorBitfields::FPFeatures and /// CXXOperatorCallExprBitfields::FPFeatures to match the total bit-field size /// of these fields. unsigned fp_contract : 2; unsigned fenv_access : 1; - unsigned rounding : 3; - unsigned exceptions : 2; + // A packed field for encoding rounding and exceptions. + // FIXME: unpack this once saving one bit isn't critical here. + // rounding_and_exceptions = MaxExceptionValue * rounding + exceptions. + constexpr static unsigned MaxExceptionValue = 3; + unsigned rounding_and_exceptions: 4; }; /// Describes the kind of translation unit being processed.