Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -2917,11 +2917,9 @@ private: unsigned Opc : 6; - // Records the FP_CONTRACT pragma status at the point that this binary - // operator was parsed. This bit is only meaningful for operations on - // floating point types. For all other types it should default to - // false. - unsigned FPContractable : 1; + // This is only meaningful for operations on floating point types and 0 + // otherwise. + unsigned FPFeatures : 1; SourceLocation OpLoc; enum { LHS, RHS, END_EXPR }; @@ -2930,7 +2928,7 @@ BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, - SourceLocation opLoc, bool fpContractable) + SourceLocation opLoc, FPOptions FPFeatures) : Expr(BinaryOperatorClass, ResTy, VK, OK, lhs->isTypeDependent() || rhs->isTypeDependent(), lhs->isValueDependent() || rhs->isValueDependent(), @@ -2938,7 +2936,7 @@ rhs->isInstantiationDependent()), (lhs->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack())), - Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) { + Opc(opc), FPFeatures(FPFeatures.getInt()), OpLoc(opLoc) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; assert(!isCompoundAssignmentOp() && @@ -3073,16 +3071,20 @@ // Set the FP contractability status of this operator. Only meaningful for // operations on floating point types. - void setFPContractable(bool FPC) { FPContractable = FPC; } + void setFPFeatures(FPOptions F) { FPFeatures = F.getInt(); } + + FPOptions getFPFeatures() const { return FPOptions(FPFeatures); } // Get the FP contractability status of this operator. Only meaningful for // operations on floating point types. - bool isFPContractable() const { return FPContractable; } + bool isFPContractable() const { + return FPOptions(FPFeatures).isFPContractable(); + } protected: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, - SourceLocation opLoc, bool fpContractable, bool dead2) + SourceLocation opLoc, FPOptions FPFeatures, bool dead2) : Expr(CompoundAssignOperatorClass, ResTy, VK, OK, lhs->isTypeDependent() || rhs->isTypeDependent(), lhs->isValueDependent() || rhs->isValueDependent(), @@ -3090,7 +3092,7 @@ rhs->isInstantiationDependent()), (lhs->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack())), - Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) { + Opc(opc), FPFeatures(FPFeatures.getInt()), OpLoc(opLoc) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; } @@ -3112,8 +3114,8 @@ CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType, ExprValueKind VK, ExprObjectKind OK, QualType CompLHSType, QualType CompResultType, - SourceLocation OpLoc, bool fpContractable) - : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, fpContractable, + SourceLocation OpLoc, FPOptions FPFeatures) + : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, FPFeatures, true), ComputationLHSType(CompLHSType), ComputationResultType(CompResultType) { Index: include/clang/AST/ExprCXX.h =================================================================== --- include/clang/AST/ExprCXX.h +++ include/clang/AST/ExprCXX.h @@ -54,18 +54,17 @@ OverloadedOperatorKind Operator; SourceRange Range; - // Record the FP_CONTRACT state that applies to this operator call. Only - // meaningful for floating point types. For other types this value can be + // Only meaningful for floating point types. For other types this value can be // set to false. - unsigned FPContractable : 1; + FPOptions FPFeatures; SourceRange getSourceRangeImpl() const LLVM_READONLY; public: CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, ArrayRef args, QualType t, ExprValueKind VK, - SourceLocation operatorloc, bool fpContractable) + SourceLocation operatorloc, FPOptions FPFeatures) : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc), - Operator(Op), FPContractable(fpContractable) { + Operator(Op), FPFeatures(FPFeatures) { Range = getSourceRangeImpl(); } explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) : @@ -113,11 +112,13 @@ // Set the FP contractability status of this operator. Only meaningful for // operations on floating point types. - void setFPContractable(bool FPC) { FPContractable = FPC; } + void setFPFeatures(FPOptions F) { FPFeatures = F; } + + FPOptions getFPFeatures() const { return FPFeatures; } // Get the FP contractability status of this operator. Only meaningful for // operations on floating point types. - bool isFPContractable() const { return FPContractable; } + bool isFPContractable() const { return FPFeatures.isFPContractable(); } friend class ASTStmtReader; friend class ASTStmtWriter; Index: include/clang/Basic/LangOptions.h =================================================================== --- include/clang/Basic/LangOptions.h +++ include/clang/Basic/LangOptions.h @@ -175,12 +175,22 @@ /// \brief Floating point control options class FPOptions { public: - unsigned fp_contract : 1; - FPOptions() : fp_contract(0) {} - FPOptions(const LangOptions &LangOpts) : - fp_contract(LangOpts.DefaultFPContract) {} + explicit FPOptions(uint64_t I) : fp_contract(I) {} + + FPOptions(const LangOptions &LangOpts) + : fp_contract(LangOpts.DefaultFPContract) {} + + void setFPContractable(bool V) { fp_contract = V; } + bool isFPContractable() const { return fp_contract; } + + /// Used to serialize this. + uint64_t getInt() const { return fp_contract; } + +private: + /// Adjust BinaryOperator::FPFeatures to match the bit-field size of this. + unsigned fp_contract : 1; }; /// \brief Describes the kind of translation unit being processed. Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -1065,14 +1065,12 @@ /// statements. class FPContractStateRAII { public: - FPContractStateRAII(Sema& S) - : S(S), OldFPContractState(S.FPFeatures.fp_contract) {} - ~FPContractStateRAII() { - S.FPFeatures.fp_contract = OldFPContractState; - } + FPContractStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.FPFeatures) {} + ~FPContractStateRAII() { S.FPFeatures = OldFPFeaturesState; } + private: Sema& S; - bool OldFPContractState : 1; + FPOptions OldFPFeaturesState; }; void addImplicitTypedef(StringRef Name, QualType T); Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -6068,7 +6068,7 @@ T, E->getValueKind(), E->getObjectKind(), Importer.Import(E->getOperatorLoc()), - E->isFPContractable()); + E->getFPFeatures()); } Expr *ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) { @@ -6218,7 +6218,7 @@ E->getObjectKind(), CompLHSType, CompResultType, Importer.Import(E->getOperatorLoc()), - E->isFPContractable()); + E->getFPFeatures()); } bool ASTNodeImporter::ImportCastPath(CastExpr *CE, CXXCastPath &Path) { Index: lib/Analysis/BodyFarm.cpp =================================================================== --- lib/Analysis/BodyFarm.cpp +++ lib/Analysis/BodyFarm.cpp @@ -87,7 +87,7 @@ QualType Ty) { return new (C) BinaryOperator(const_cast(LHS), const_cast(RHS), BO_Assign, Ty, VK_RValue, - OK_Ordinary, SourceLocation(), false); + OK_Ordinary, SourceLocation(), FPOptions()); } BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS, @@ -99,7 +99,7 @@ Op, C.getLogicalOperationType(), VK_RValue, - OK_Ordinary, SourceLocation(), false); + OK_Ordinary, SourceLocation(), FPOptions()); } CompoundStmt *ASTMaker::makeCompound(ArrayRef Stmts) { Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp +++ lib/CodeGen/CGExprScalar.cpp @@ -49,7 +49,7 @@ Value *RHS; QualType Ty; // Computation Type. BinaryOperator::Opcode Opcode; // Opcode of BinOp to perform - bool FPContractable; + FPOptions FPFeatures; const Expr *E; // Entire expr, for error unsupported. May not be binop. }; @@ -1709,7 +1709,7 @@ BinOp.RHS = llvm::ConstantInt::get(InVal->getType(), 1, false); BinOp.Ty = E->getType(); BinOp.Opcode = IsInc ? BO_Add : BO_Sub; - BinOp.FPContractable = false; + // FIXME: once UnaryOperator carries FPFeatures, copy it here. BinOp.E = E; return BinOp; } @@ -1975,7 +1975,7 @@ BinOp.LHS = llvm::Constant::getNullValue(BinOp.RHS->getType()); BinOp.Ty = E->getType(); BinOp.Opcode = BO_Sub; - BinOp.FPContractable = false; + // FIXME: once UnaryOperator carries FPFeatures, copy it here. BinOp.E = E; return EmitSub(BinOp); } @@ -2196,7 +2196,7 @@ Result.RHS = Visit(E->getRHS()); Result.Ty = E->getType(); Result.Opcode = E->getOpcode(); - Result.FPContractable = E->isFPContractable(); + Result.FPFeatures = E->getFPFeatures(); Result.E = E; return Result; } @@ -2216,7 +2216,7 @@ OpInfo.RHS = Visit(E->getRHS()); OpInfo.Ty = E->getComputationResultType(); OpInfo.Opcode = E->getOpcode(); - OpInfo.FPContractable = E->isFPContractable(); + OpInfo.FPFeatures = E->getFPFeatures(); OpInfo.E = E; // Load/convert the LHS. LValue LHSLV = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store); @@ -2663,7 +2663,7 @@ "Only fadd/fsub can be the root of an fmuladd."); // Check whether this op is marked as fusable. - if (!op.FPContractable) + if (!op.FPFeatures.isFPContractable()) return nullptr; // Check whether -ffp-contract=on. (If -ffp-contract=off/fast, fusing is Index: lib/CodeGen/CGObjC.cpp =================================================================== --- lib/CodeGen/CGObjC.cpp +++ lib/CodeGen/CGObjC.cpp @@ -1316,7 +1316,7 @@ BinaryOperator assign(&ivarRef, finalArg, BO_Assign, ivarRef.getType(), VK_RValue, OK_Ordinary, - SourceLocation(), false); + SourceLocation(), FPOptions()); EmitStmt(&assign); } @@ -3263,7 +3263,7 @@ CallExpr *CalleeExp = cast(PID->getSetterCXXAssignment()); CXXOperatorCallExpr TheCall(C, OO_Equal, CalleeExp->getCallee(), Args, DestTy->getPointeeType(), - VK_LValue, SourceLocation(), false); + VK_LValue, SourceLocation(), FPOptions()); EmitStmt(&TheCall); Index: lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- lib/CodeGen/CGStmtOpenMP.cpp +++ lib/CodeGen/CGStmtOpenMP.cpp @@ -2346,8 +2346,7 @@ CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB); // Generate condition for loop. BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue, - OK_Ordinary, S.getLocStart(), - /*fpContractable=*/false); + OK_Ordinary, S.getLocStart(), FPOptions()); // Increment for loop counter. UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary, S.getLocStart()); Index: lib/Frontend/Rewrite/RewriteModernObjC.cpp =================================================================== --- lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -7500,7 +7500,7 @@ BinaryOperator *addExpr = new (Context) BinaryOperator(castExpr, DRE, BO_Add, Context->getPointerType(Context->CharTy), - VK_RValue, OK_Ordinary, SourceLocation(), false); + VK_RValue, OK_Ordinary, SourceLocation(), FPOptions()); // Don't forget the parens to enforce the proper binding. ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), Index: lib/Frontend/Rewrite/RewriteObjC.cpp =================================================================== --- lib/Frontend/Rewrite/RewriteObjC.cpp +++ lib/Frontend/Rewrite/RewriteObjC.cpp @@ -2992,7 +2992,7 @@ BinaryOperator *lessThanExpr = new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy, VK_RValue, OK_Ordinary, SourceLocation(), - false); + FPOptions()); // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) ConditionalOperator *CondExpr = new (Context) ConditionalOperator(lessThanExpr, Index: lib/Sema/SemaAttr.cpp =================================================================== --- lib/Sema/SemaAttr.cpp +++ lib/Sema/SemaAttr.cpp @@ -450,13 +450,13 @@ void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) { switch (OOS) { case tok::OOS_ON: - FPFeatures.fp_contract = 1; + FPFeatures.setFPContractable(true); break; case tok::OOS_OFF: - FPFeatures.fp_contract = 0; + FPFeatures.setFPContractable(false); break; case tok::OOS_DEFAULT: - FPFeatures.fp_contract = getLangOpts().DefaultFPContract; + FPFeatures.setFPContractable(getLangOpts().DefaultFPContract); break; } } Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -11111,7 +11111,7 @@ = new (S.Context) BinaryOperator(IterationVarRefRVal.build(S, Loc), IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), BO_NE, S.Context.BoolTy, - VK_RValue, OK_Ordinary, Loc, false); + VK_RValue, OK_Ordinary, Loc, FPOptions()); // Create the pre-increment of the iteration variable. Expr *Increment Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -11240,7 +11240,7 @@ if (CompResultTy.isNull()) return new (Context) BinaryOperator(LHS.get(), RHS.get(), Opc, ResultTy, VK, - OK, OpLoc, FPFeatures.fp_contract); + OK, OpLoc, FPFeatures); if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() != OK_ObjCProperty) { VK = VK_LValue; @@ -11248,7 +11248,7 @@ } return new (Context) CompoundAssignOperator( LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, CompLHSTy, CompResultTy, - OpLoc, FPFeatures.fp_contract); + OpLoc, FPFeatures); } /// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -6177,7 +6177,7 @@ return E; return new (Context) BinaryOperator( BO->getLHS(), RHS.get(), BO_Comma, BO->getType(), BO->getValueKind(), - BO->getObjectKind(), BO->getOperatorLoc(), BO->isFPContractable()); + BO->getObjectKind(), BO->getOperatorLoc(), BO->getFPFeatures()); } } Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -11963,7 +11963,7 @@ Fns.begin(), Fns.end()); return new (Context) CXXOperatorCallExpr(Context, Op, Fn, ArgsArray, Context.DependentTy, - VK_RValue, OpLoc, false); + VK_RValue, OpLoc, FPOptions()); } // Build an empty overload set. @@ -12033,7 +12033,7 @@ Args[0] = Input; CallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.get(), ArgsArray, - ResultTy, VK, OpLoc, false); + ResultTy, VK, OpLoc, FPOptions()); if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl)) return ExprError(); @@ -12131,12 +12131,12 @@ if (Opc <= BO_Assign || Opc > BO_OrAssign) return new (Context) BinaryOperator( Args[0], Args[1], Opc, Context.DependentTy, VK_RValue, OK_Ordinary, - OpLoc, FPFeatures.fp_contract); + OpLoc, FPFeatures); return new (Context) CompoundAssignOperator( Args[0], Args[1], Opc, Context.DependentTy, VK_LValue, OK_Ordinary, Context.DependentTy, Context.DependentTy, OpLoc, - FPFeatures.fp_contract); + FPFeatures); } // FIXME: save results of ADL from here? @@ -12150,7 +12150,7 @@ Fns.begin(), Fns.end()); return new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args, Context.DependentTy, - VK_RValue, OpLoc, FPFeatures.fp_contract); + VK_RValue, OpLoc, FPFeatures); } // Always do placeholder-like conversions on the RHS. @@ -12265,7 +12265,7 @@ CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.get(), Args, ResultTy, VK, OpLoc, - FPFeatures.fp_contract); + FPFeatures); if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl)) @@ -12413,7 +12413,7 @@ return new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn, Args, - Context.DependentTy, VK_RValue, RLoc, false); + Context.DependentTy, VK_RValue, RLoc, FPOptions()); } // Handle placeholders on both operands. @@ -12489,7 +12489,7 @@ new (Context) CXXOperatorCallExpr(Context, OO_Subscript, FnExpr.get(), Args, ResultTy, VK, RLoc, - false); + FPOptions()); if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl)) return ExprError(); @@ -13052,7 +13052,7 @@ CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.get(), MethodArgs, ResultTy, - VK, RParenLoc, false); + VK, RParenLoc, FPOptions()); if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method)) return true; @@ -13232,7 +13232,7 @@ ResultTy = ResultTy.getNonLValueExprType(Context); CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.get(), - Base, ResultTy, VK, OpLoc, false); + Base, ResultTy, VK, OpLoc, FPOptions()); if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method)) return ExprError(); Index: lib/Sema/SemaPseudoObject.cpp =================================================================== --- lib/Sema/SemaPseudoObject.cpp +++ lib/Sema/SemaPseudoObject.cpp @@ -447,7 +447,8 @@ syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS, opcode, capturedRHS->getType(), capturedRHS->getValueKind(), - OK_Ordinary, opcLoc, false); + OK_Ordinary, opcLoc, + FPOptions()); } else { ExprResult opLHS = buildGet(); if (opLHS.isInvalid()) return ExprError(); @@ -465,7 +466,7 @@ OK_Ordinary, opLHS.get()->getType(), result.get()->getType(), - opcLoc, false); + opcLoc, FPOptions()); } // The result of the assignment, if not void, is the value set into @@ -1587,7 +1588,8 @@ // Do nothing if either argument is dependent. if (LHS->isTypeDependent() || RHS->isTypeDependent()) return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy, - VK_RValue, OK_Ordinary, opcLoc, false); + VK_RValue, OK_Ordinary, opcLoc, + FPOptions()); // Filter out non-overload placeholder types in the RHS. if (RHS->getType()->isNonOverloadPlaceholderType()) { @@ -1652,14 +1654,15 @@ cop->getObjectKind(), cop->getComputationLHSType(), cop->getComputationResultType(), - cop->getOperatorLoc(), false); + cop->getOperatorLoc(), + FPOptions()); } else if (BinaryOperator *bop = dyn_cast(syntax)) { Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); Expr *rhs = cast(bop->getRHS())->getSourceExpr(); return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(), bop->getType(), bop->getValueKind(), bop->getObjectKind(), - bop->getOperatorLoc(), false); + bop->getOperatorLoc(), FPOptions()); } else { assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject)); return stripOpaqueValuesFromPseudoObjectRef(*this, syntax); Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -9146,7 +9146,7 @@ return E; Sema::FPContractStateRAII FPContractState(getSema()); - getSema().FPFeatures.fp_contract = E->isFPContractable(); + getSema().FPFeatures = E->getFPFeatures(); return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(), LHS.get(), RHS.get()); @@ -9626,7 +9626,7 @@ return SemaRef.MaybeBindToTemporary(E); Sema::FPContractStateRAII FPContractState(getSema()); - getSema().FPFeatures.fp_contract = E->isFPContractable(); + getSema().FPFeatures = E->getFPFeatures(); return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(), E->getOperatorLoc(), Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -7215,7 +7215,7 @@ // FIXME: What happens if these are changed by a module import? if (!FPPragmaOptions.empty()) { assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS"); - SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0]; + SemaObj->FPFeatures = FPOptions(FPPragmaOptions[0]); } SemaObj->OpenCLFeatures.copy(OpenCLExtensions); Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -670,7 +670,7 @@ E->setRHS(Record.readSubExpr()); E->setOpcode((BinaryOperator::Opcode)Record.readInt()); E->setOperatorLoc(ReadSourceLocation()); - E->setFPContractable((bool)Record.readInt()); + E->setFPFeatures(FPOptions(Record.readInt())); } void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) { @@ -1225,7 +1225,7 @@ VisitCallExpr(E); E->Operator = (OverloadedOperatorKind)Record.readInt(); E->Range = Record.readSourceRange(); - E->setFPContractable((bool)Record.readInt()); + E->setFPFeatures(FPOptions(Record.readInt())); } void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { Index: lib/Serialization/ASTWriter.cpp =================================================================== --- lib/Serialization/ASTWriter.cpp +++ lib/Serialization/ASTWriter.cpp @@ -3975,7 +3975,7 @@ /// \brief Write an FP_PRAGMA_OPTIONS block for the given FPOptions. void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) { - RecordData::value_type Record[] = {Opts.fp_contract}; + RecordData::value_type Record[] = {Opts.getInt()}; Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record); } Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -650,7 +650,7 @@ Record.AddStmt(E->getRHS()); Record.push_back(E->getOpcode()); // FIXME: stable encoding Record.AddSourceLocation(E->getOperatorLoc()); - Record.push_back(E->isFPContractable()); + Record.push_back(E->getFPFeatures().getInt()); Code = serialization::EXPR_BINARY_OPERATOR; } @@ -1218,7 +1218,7 @@ VisitCallExpr(E); Record.push_back(E->getOperator()); Record.AddSourceRange(E->Range); - Record.push_back(E->isFPContractable()); + Record.push_back(E->getFPFeatures().getInt()); Code = serialization::EXPR_CXX_OPERATOR_CALL; }