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 @@ -197,7 +197,7 @@ /// Possible rounding modes. enum FPRoundingModeKind { /// Rounding to nearest, corresponds to "round.tonearest". - FPR_ToNearest, + FPR_ToNearest = 0, /// Rounding toward -Inf, corresponds to "round.downward". FPR_Downward, /// Rounding toward +Inf, corresponds to "round.upward". @@ -211,7 +211,7 @@ /// Possible floating point exception behavior. enum FPExceptionModeKind { /// Assume that floating-point exceptions are masked. - FPE_Ignore, + FPE_Ignore = 0, /// Transformations do not cause new exceptions but may hide some. FPE_MayTrap, /// Strictly preserve the floating-point exception semantics. @@ -358,23 +358,20 @@ public: FPOptions() : fp_contract(LangOptions::FPC_Off), fenv_access(LangOptions::FEA_Off), - rounding(LangOptions::FPR_ToNearest), - exceptions(LangOptions::FPE_Ignore) + packed(0) {} // 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)) + packed(I >> 3) {} explicit FPOptions(const LangOptions &LangOpts) : fp_contract(LangOpts.getDefaultFPContractMode()), fenv_access(LangOptions::FEA_Off), - rounding(LangOptions::FPR_ToNearest), - exceptions(LangOptions::FPE_Ignore) + packed(0) {} // FIXME: Use getDefaultFEnvAccessMode() when available. @@ -407,19 +404,24 @@ void setDisallowFEnvAccess() { fenv_access = LangOptions::FEA_Off; } LangOptions::FPRoundingModeKind getRoundingMode() const { + unsigned rounding = packed / MaxExceptionValue; return static_cast(rounding); } void setRoundingMode(LangOptions::FPRoundingModeKind RM) { - rounding = RM; + packed = RM * MaxExceptionValue + getExceptionMode(); } LangOptions::FPExceptionModeKind getExceptionMode() const { + static_assert(LangOptions::FPExceptionModeKind::FPE_Strict < + MaxExceptionValue, + "Max exception value must less than 3"); + unsigned exceptions = packed % MaxExceptionValue; return static_cast(exceptions); } void setExceptionMode(LangOptions::FPExceptionModeKind EM) { - exceptions = EM; + packed = getRoundingMode() * MaxExceptionValue + EM; } bool isFPConstrained() const { @@ -430,8 +432,7 @@ /// Used to serialize this. unsigned getInt() const { - return fp_contract | (fenv_access << 2) | (rounding << 3) - | (exceptions << 6); + return fp_contract | (fenv_access << 2) | (packed << 3); } private: @@ -440,8 +441,10 @@ /// 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. + // packed = MaxExceptionValue * rounding + exceptions. + constexpr static unsigned MaxExceptionValue = 3; + unsigned packed: 4; }; /// Describes the kind of translation unit being processed.