summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Nemet <anemet@apple.com>2017-03-27 19:17:25 +0000
committerAdam Nemet <anemet@apple.com>2017-03-27 19:17:25 +0000
commiteec6cbfc8d18f8777ba9478f65d4ad5291180d38 (patch)
tree75c92e735cb6b308c98a79d17928125e103eadbb
parent75f794b36977628281921472eaf4bc63d9cb336c (diff)
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
-rw-r--r--include/clang/AST/Expr.h28
-rw-r--r--include/clang/AST/ExprCXX.h16
-rw-r--r--include/clang/Basic/LangOptions.h18
-rw-r--r--include/clang/Sema/Sema.h10
-rw-r--r--lib/AST/ASTImporter.cpp4
-rw-r--r--lib/Analysis/BodyFarm.cpp4
-rw-r--r--lib/CodeGen/CGExprScalar.cpp12
-rw-r--r--lib/CodeGen/CGObjC.cpp4
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp3
-rw-r--r--lib/Frontend/Rewrite/RewriteModernObjC.cpp2
-rw-r--r--lib/Frontend/Rewrite/RewriteObjC.cpp2
-rw-r--r--lib/Sema/SemaAttr.cpp6
-rw-r--r--lib/Sema/SemaDeclCXX.cpp2
-rw-r--r--lib/Sema/SemaExpr.cpp4
-rw-r--r--lib/Sema/SemaExprCXX.cpp2
-rw-r--r--lib/Sema/SemaOverload.cpp20
-rw-r--r--lib/Sema/SemaPseudoObject.cpp13
-rw-r--r--lib/Sema/TreeTransform.h4
-rw-r--r--lib/Serialization/ASTReader.cpp2
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp4
-rw-r--r--lib/Serialization/ASTWriter.cpp2
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp4
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<Expr*> 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<Expr*>(LHS), const_cast<Expr*>(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<Stmt *> 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<CallExpr>(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<BinaryOperator>(syntax)) {
Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());
Expr *rhs = cast<OpaqueValueExpr>(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<Derived>::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<Derived>::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;
}