From eec6cbfc8d18f8777ba9478f65d4ad5291180d38 Mon Sep 17 00:00:00 2001 From: Adam Nemet Date: Mon, 27 Mar 2017 19:17:25 +0000 Subject: Encapsulate FPOptions and use it consistently Sema holds the current FPOptions which is adjusted by 'pragma STDC FP_CONTRACT'. This then gets propagated into expression nodes as they are built. This encapsulates FPOptions so that this propagation happens opaquely rather than directly with the fp_contractable on/off bit. This allows controlled transitioning of fp_contractable to a ternary value (off, on, fast). It will also allow adding more fast-math flags later. This is toward moving fp-contraction=fast from an LLVM TargetOption to a FastMathFlag in order to fix PR25721. Differential Revision: https://reviews.llvm.org/D31166 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@298877 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 28 +++++++++++++++------------- include/clang/AST/ExprCXX.h | 16 ++++++++-------- include/clang/Basic/LangOptions.h | 18 ++++++++++++++---- include/clang/Sema/Sema.h | 10 ++++------ lib/AST/ASTImporter.cpp | 4 ++-- lib/Analysis/BodyFarm.cpp | 4 ++-- lib/CodeGen/CGExprScalar.cpp | 12 ++++++------ lib/CodeGen/CGObjC.cpp | 4 ++-- lib/CodeGen/CGStmtOpenMP.cpp | 3 +-- lib/Frontend/Rewrite/RewriteModernObjC.cpp | 2 +- lib/Frontend/Rewrite/RewriteObjC.cpp | 2 +- lib/Sema/SemaAttr.cpp | 6 +++--- lib/Sema/SemaDeclCXX.cpp | 2 +- lib/Sema/SemaExpr.cpp | 4 ++-- lib/Sema/SemaExprCXX.cpp | 2 +- lib/Sema/SemaOverload.cpp | 20 ++++++++++---------- lib/Sema/SemaPseudoObject.cpp | 13 ++++++++----- lib/Sema/TreeTransform.h | 4 ++-- lib/Serialization/ASTReader.cpp | 2 +- lib/Serialization/ASTReaderStmt.cpp | 4 ++-- lib/Serialization/ASTWriter.cpp | 2 +- lib/Serialization/ASTWriterStmt.cpp | 4 ++-- 22 files changed, 89 insertions(+), 77 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index a7ca03ff9e..efeeffcef2 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -2918,11 +2918,9 @@ public: 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 }; @@ -2931,7 +2929,7 @@ public: 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(), @@ -2939,7 +2937,7 @@ public: 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() && @@ -3074,16 +3072,20 @@ public: // 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(), @@ -3091,7 +3093,7 @@ protected: 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; } @@ -3113,8 +3115,8 @@ public: 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) { diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index f4ff5bb982..c284918585 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -54,18 +54,16 @@ class CXXOperatorCallExpr : public CallExpr { 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 - // set to false. - unsigned FPContractable : 1; + // Only meaningful for floating point types. + 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 +111,13 @@ public: // 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; diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 10635b1122..3f2c4a1649 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -175,12 +175,22 @@ public: /// \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(unsigned I) : fp_contract(I) {} + + explicit 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. + unsigned 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. diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 2d8040a20b..e0a8fa8a9b 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1065,14 +1065,12 @@ public: /// 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); diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index ed405b5c90..c0cbde2ea8 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -6074,7 +6074,7 @@ Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { T, E->getValueKind(), E->getObjectKind(), Importer.Import(E->getOperatorLoc()), - E->isFPContractable()); + E->getFPFeatures()); } Expr *ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) { @@ -6224,7 +6224,7 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { E->getObjectKind(), CompLHSType, CompResultType, Importer.Import(E->getOperatorLoc()), - E->isFPContractable()); + E->getFPFeatures()); } bool ASTNodeImporter::ImportCastPath(CastExpr *CE, CXXCastPath &Path) { diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp index 56c812c34c..5912724610 100644 --- a/lib/Analysis/BodyFarm.cpp +++ b/lib/Analysis/BodyFarm.cpp @@ -87,7 +87,7 @@ BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS, 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 @@ BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS, Op, C.getLogicalOperationType(), VK_RValue, - OK_Ordinary, SourceLocation(), false); + OK_Ordinary, SourceLocation(), FPOptions()); } CompoundStmt *ASTMaker::makeCompound(ArrayRef Stmts) { diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 4e17f360a2..9eb21b8086 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -49,7 +49,7 @@ struct BinOpInfo { 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. }; @@ -1718,7 +1718,7 @@ static BinOpInfo createBinOpInfoFromIncDec(const UnaryOperator *E, 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; } @@ -1984,7 +1984,7 @@ Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) { 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); } @@ -2205,7 +2205,7 @@ BinOpInfo ScalarExprEmitter::EmitBinOps(const BinaryOperator *E) { 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; } @@ -2225,7 +2225,7 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue( 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); @@ -2672,7 +2672,7 @@ static Value* tryEmitFMulAdd(const BinOpInfo &op, "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 diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 4af5af9324..929bda9099 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -1316,7 +1316,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, BinaryOperator assign(&ivarRef, finalArg, BO_Assign, ivarRef.getType(), VK_RValue, OK_Ordinary, - SourceLocation(), false); + SourceLocation(), FPOptions()); EmitStmt(&assign); } @@ -3263,7 +3263,7 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( 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); diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index 2f64da2912..71d8ea2714 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -2346,8 +2346,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) { 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()); diff --git a/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/lib/Frontend/Rewrite/RewriteModernObjC.cpp index e6469f53d4..8871bb7e83 100644 --- a/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -7500,7 +7500,7 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { 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(), diff --git a/lib/Frontend/Rewrite/RewriteObjC.cpp b/lib/Frontend/Rewrite/RewriteObjC.cpp index 934d6aa34a..7e210717fa 100644 --- a/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -2992,7 +2992,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 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, diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index bad9e70242..992eac9019 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -450,13 +450,13 @@ void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType, 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; } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 668d4b2de3..4a9120be2f 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -11111,7 +11111,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, = 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 diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c5b2e1b3a2..410c8b3484 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -11261,7 +11261,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, 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; @@ -11269,7 +11269,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, } 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 diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 45f969c26a..7bfe838ea2 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -6159,7 +6159,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { 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()); } } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7f94bf26d8..82834057ee 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -11963,7 +11963,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, 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 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, 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 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, 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 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, 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 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, 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 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, 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 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, 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 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, 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 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, 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(); diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index 8e53fda846..b740540dca 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -447,7 +447,8 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, 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 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, 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 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, // 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 @@ Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) { 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); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 7a89c9dea1..1203150112 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -9146,7 +9146,7 @@ TreeTransform::TransformBinaryOperator(BinaryOperator *E) { 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 @@ TreeTransform::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { 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(), diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 9f50e0541d..20a27607ac 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -7378,7 +7378,7 @@ void ASTReader::InitializeSema(Sema &S) { // 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); diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 6a4482ba53..a12fb8cf95 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -670,7 +670,7 @@ void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) { 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 @@ void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { 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) { diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index e4474a8417..d2907bebba 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -4015,7 +4015,7 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { /// \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); } diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index bade553425..1a2edac658 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -650,7 +650,7 @@ void ASTStmtWriter::VisitBinaryOperator(BinaryOperator *E) { 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 @@ void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { 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; } -- cgit v1.2.3