mibintc created this revision.
mibintc added a reviewer: rjmccall.
Herald added subscribers: llvm-commits, dexonsmith.
Herald added projects: clang, LLVM.
mibintc marked an inline comment as done.
mibintc added a comment.
@rjmccall You suggested that the FPFeatures could be delta instead of absolute
settings, I think this is approximately what you mean. This is a rough patch
employing that idea, would welcome your early comments. There are 2 clang
tests that are failing with this patch, I need to dig into those.
Failed Tests (2):
Clang :: CodeGen/fp-floatcontrol-stack.cpp
Clang :: PCH/pragma-floatcontrol.c
================
Comment at: llvm/include/llvm/ADT/FloatingPointMode.h:43
// Special values.
+ Unset = 6, ///< Denotes an unset value, (for clang, must fit in 3 bits)
Dynamic = 7, ///< Denotes mode unknown at compile time.
----------------
I added "unset" enumerals to the 3 enumeration values. Note that I can't just
use the "invalid" enumeration since the clang field is only 3 bits wide so
Invalid would appear to equal Dynamic
(This patch is in development)
To solve https://bugs.llvm.org/show_bug.cgi?id=46166 where the floating point
settings in PCH files aren't compatible, rewrite FPFeatures to use a delta in
the settings rather than absolute settings
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D81869
Files:
clang/include/clang/AST/Expr.h
clang/include/clang/AST/ExprCXX.h
clang/include/clang/AST/Stmt.h
clang/include/clang/Basic/LangOptions.h
clang/include/clang/Sema/Sema.h
clang/include/clang/Serialization/ASTWriter.h
clang/lib/AST/Expr.cpp
clang/lib/AST/ExprCXX.cpp
clang/lib/Analysis/BodyFarm.cpp
clang/lib/Basic/LangOptions.cpp
clang/lib/CodeGen/BackendUtil.cpp
clang/lib/CodeGen/CGExprScalar.cpp
clang/lib/CodeGen/CGObjC.cpp
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
clang/lib/Frontend/Rewrite/RewriteObjC.cpp
clang/lib/Parse/ParsePragma.cpp
clang/lib/Sema/Sema.cpp
clang/lib/Sema/SemaAttr.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaExprObjC.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaPseudoObject.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriter.cpp
llvm/include/llvm/ADT/FloatingPointMode.h
Index: llvm/include/llvm/ADT/FloatingPointMode.h
===================================================================
--- llvm/include/llvm/ADT/FloatingPointMode.h
+++ llvm/include/llvm/ADT/FloatingPointMode.h
@@ -40,6 +40,7 @@
NearestTiesToAway = 4, ///< roundTiesToAway.
// Special values.
+ Unset = 6, ///< Denotes an unset value, (for clang, must fit in 3 bits)
Dynamic = 7, ///< Denotes mode unknown at compile time.
Invalid = -1 ///< Denotes invalid value.
};
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -3960,7 +3960,7 @@
}
/// Write an FP_PRAGMA_OPTIONS block for the given FPOptions.
-void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) {
+void ASTWriter::WriteFPPragmaOptions(const FPOptionsOverride &Opts) {
RecordData::value_type Record[] = {Opts.getAsOpaqueInt()};
Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record);
}
@@ -4790,7 +4790,7 @@
WriteReferencedSelectorsPool(SemaRef);
WriteLateParsedTemplates(SemaRef);
WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);
- WriteFPPragmaOptions(SemaRef.getCurFPFeatures());
+ WriteFPPragmaOptions(SemaRef.CurFPFeatureOverrides());
WriteOpenCLExtensions(SemaRef);
WriteOpenCLExtensionTypes(SemaRef);
WriteCUDAPragmas(SemaRef);
Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -689,7 +689,7 @@
E->setOperatorLoc(readSourceLocation());
E->setCanOverflow(Record.readInt());
if (hasFP_Features)
- E->setStoredFPFeatures(FPOptions(Record.readInt()));
+ E->setStoredFPFeatures(FPOptionsOverride(Record.readInt()));
}
void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
@@ -1072,7 +1072,7 @@
E->setRHS(Record.readSubExpr());
E->setOperatorLoc(readSourceLocation());
if (hasFP_Features)
- E->setStoredFPFeatures(FPOptions(Record.readInt()));
+ E->setStoredFPFeatures(FPOptionsOverride(Record.readInt()));
}
void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -7843,7 +7843,8 @@
// 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->CurFPFeatures = FPOptions(FPPragmaOptions[0]);
+ FPOptionsOverride NewOverrides(FPPragmaOptions[0]);
+ SemaObj->CurFPFeatures = NewOverrides.mergeOverrides(SemaObj->getLangOpts());
}
SemaObj->OpenCLFeatures.copy(OpenCLExtensions);
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -10563,8 +10563,9 @@
return getDerived().RebuildBinaryOperator(
E->getOperatorLoc(), E->getOpcode(), LHS.get(), RHS.get());
Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
- getSema().CurFPFeatures = E->getFPFeatures(getSema().getLangOpts());
-
+ FPOptionsOverride NewOverrides(E->getFPFeatures(getSema().getLangOpts()));
+ getSema().CurFPFeatures = NewOverrides.mergeOverrides(getSema().getLangOpts());
+ getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),
LHS.get(), RHS.get());
}
@@ -10618,7 +10619,9 @@
TreeTransform<Derived>::TransformCompoundAssignOperator(
CompoundAssignOperator *E) {
Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
- getSema().CurFPFeatures = E->getFPFeatures(getSema().getLangOpts());
+ FPOptionsOverride NewOverrides(E->getFPFeatures(getSema().getLangOpts()));
+ getSema().CurFPFeatures = NewOverrides.mergeOverrides(getSema().getLangOpts());
+ getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
return getDerived().TransformBinaryOperator(E);
}
@@ -11093,7 +11096,9 @@
return SemaRef.MaybeBindToTemporary(E);
Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
- getSema().CurFPFeatures = E->getFPFeatures();
+ FPOptionsOverride NewOverrides(E->getFPFeatures());
+ getSema().CurFPFeatures = NewOverrides.mergeOverrides(getSema().getLangOpts());
+ getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),
E->getOperatorLoc(),
Index: clang/lib/Sema/SemaPseudoObject.cpp
===================================================================
--- clang/lib/Sema/SemaPseudoObject.cpp
+++ clang/lib/Sema/SemaPseudoObject.cpp
@@ -130,7 +130,7 @@
return UnaryOperator::Create(
S.Context, e, uop->getOpcode(), uop->getType(), uop->getValueKind(),
uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow(),
- S.CurFPFeatures);
+ S.CurFPFeatureOverrides());
}
if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
@@ -448,7 +448,7 @@
result = semanticRHS;
syntactic = BinaryOperator::Create(
S.Context, syntacticLHS, capturedRHS, opcode, capturedRHS->getType(),
- capturedRHS->getValueKind(), OK_Ordinary, opcLoc, S.CurFPFeatures);
+ capturedRHS->getValueKind(), OK_Ordinary, opcLoc, S.CurFPFeatureOverrides());
} else {
ExprResult opLHS = buildGet();
@@ -462,7 +462,7 @@
syntactic = CompoundAssignOperator::Create(
S.Context, syntacticLHS, capturedRHS, opcode, result.get()->getType(),
- result.get()->getValueKind(), OK_Ordinary, opcLoc, S.CurFPFeatures,
+ result.get()->getValueKind(), OK_Ordinary, opcLoc, S.CurFPFeatureOverrides(),
opLHS.get()->getType(), result.get()->getType());
}
@@ -531,7 +531,7 @@
? S.Context.getTypeSize(resultType) >=
S.Context.getTypeSize(S.Context.IntTy)
: false,
- S.CurFPFeatures);
+ S.CurFPFeatureOverrides());
return complete(syntactic);
}
@@ -1553,7 +1553,7 @@
if (op->isTypeDependent())
return UnaryOperator::Create(Context, op, opcode, Context.DependentTy,
VK_RValue, OK_Ordinary, opcLoc, false,
- CurFPFeatures);
+ CurFPFeatureOverrides());
assert(UnaryOperator::isIncrementDecrementOp(opcode));
Expr *opaqueRef = op->IgnoreParens();
@@ -1584,7 +1584,7 @@
if (LHS->isTypeDependent() || RHS->isTypeDependent())
return BinaryOperator::Create(Context, LHS, RHS, opcode,
Context.DependentTy, VK_RValue, OK_Ordinary,
- opcLoc, CurFPFeatures);
+ opcLoc, CurFPFeatureOverrides());
// Filter out non-overload placeholder types in the RHS.
if (RHS->getType()->isNonOverloadPlaceholderType()) {
@@ -1640,7 +1640,7 @@
return UnaryOperator::Create(Context, op, uop->getOpcode(), uop->getType(),
uop->getValueKind(), uop->getObjectKind(),
uop->getOperatorLoc(), uop->canOverflow(),
- CurFPFeatures);
+ CurFPFeatureOverrides());
} else if (CompoundAssignOperator *cop
= dyn_cast<CompoundAssignOperator>(syntax)) {
Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
@@ -1648,7 +1648,7 @@
return CompoundAssignOperator::Create(
Context, lhs, rhs, cop->getOpcode(), cop->getType(),
cop->getValueKind(), cop->getObjectKind(), cop->getOperatorLoc(),
- CurFPFeatures, cop->getComputationLHSType(),
+ CurFPFeatureOverrides(), cop->getComputationLHSType(),
cop->getComputationResultType());
} else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
@@ -1657,7 +1657,7 @@
return BinaryOperator::Create(Context, lhs, rhs, bop->getOpcode(),
bop->getType(), bop->getValueKind(),
bop->getObjectKind(), bop->getOperatorLoc(),
- CurFPFeatures);
+ CurFPFeatureOverrides());
} else if (isa<CallExpr>(syntax)) {
return syntax;
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -13041,7 +13041,7 @@
if (Fns.empty())
return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy,
VK_RValue, OK_Ordinary, OpLoc, false,
- CurFPFeatures);
+ CurFPFeatureOverrides());
CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(
@@ -13049,7 +13049,7 @@
/*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end());
return CXXOperatorCallExpr::Create(Context, Op, Fn, ArgsArray,
Context.DependentTy, VK_RValue, OpLoc,
- CurFPFeatures);
+ CurFPFeatureOverrides());
}
// Build an empty overload set.
@@ -13123,7 +13123,7 @@
Args[0] = Input;
CallExpr *TheCall = CXXOperatorCallExpr::Create(
Context, Op, FnExpr.get(), ArgsArray, ResultTy, VK, OpLoc,
- CurFPFeatures, Best->IsADLCandidate);
+ CurFPFeatureOverrides(), Best->IsADLCandidate);
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl))
return ExprError();
@@ -13294,10 +13294,10 @@
if (Opc <= BO_Assign || Opc > BO_OrAssign)
return BinaryOperator::Create(Context, Args[0], Args[1], Opc,
Context.DependentTy, VK_RValue,
- OK_Ordinary, OpLoc, CurFPFeatures);
+ OK_Ordinary, OpLoc, CurFPFeatureOverrides());
return CompoundAssignOperator::Create(
Context, Args[0], Args[1], Opc, Context.DependentTy, VK_LValue,
- OK_Ordinary, OpLoc, CurFPFeatures, Context.DependentTy,
+ OK_Ordinary, OpLoc, CurFPFeatureOverrides(), Context.DependentTy,
Context.DependentTy);
}
@@ -13311,7 +13311,7 @@
/*ADL*/ PerformADL, IsOverloaded(Fns), Fns.begin(), Fns.end());
return CXXOperatorCallExpr::Create(Context, Op, Fn, Args,
Context.DependentTy, VK_RValue, OpLoc,
- CurFPFeatures);
+ CurFPFeatureOverrides());
}
// Always do placeholder-like conversions on the RHS.
@@ -13480,7 +13480,7 @@
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
Context, ChosenOp, FnExpr.get(), Args, ResultTy, VK, OpLoc,
- CurFPFeatures, Best->IsADLCandidate);
+ CurFPFeatureOverrides(), Best->IsADLCandidate);
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall,
FnDecl))
@@ -13748,7 +13748,7 @@
Expr *SyntacticForm = BinaryOperator::Create(
Context, OrigLHS, OrigRHS, BO_Cmp, Result.get()->getType(),
Result.get()->getValueKind(), Result.get()->getObjectKind(), OpLoc,
- CurFPFeatures);
+ CurFPFeatureOverrides());
Expr *SemanticForm[] = {LHS, RHS, Result.get()};
return PseudoObjectExpr::Create(Context, SyntacticForm, SemanticForm, 2);
}
@@ -13779,7 +13779,7 @@
return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args,
Context.DependentTy, VK_RValue, RLoc,
- CurFPFeatures);
+ CurFPFeatureOverrides());
}
// Handle placeholders on both operands.
@@ -13854,7 +13854,7 @@
CXXOperatorCallExpr *TheCall =
CXXOperatorCallExpr::Create(Context, OO_Subscript, FnExpr.get(),
- Args, ResultTy, VK, RLoc, CurFPFeatures);
+ Args, ResultTy, VK, RLoc, CurFPFeatureOverrides());
if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
return ExprError();
@@ -14478,7 +14478,7 @@
CXXOperatorCallExpr *TheCall =
CXXOperatorCallExpr::Create(Context, OO_Call, NewFn.get(), MethodArgs,
- ResultTy, VK, RParenLoc, CurFPFeatures);
+ ResultTy, VK, RParenLoc, CurFPFeatureOverrides());
if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
return true;
@@ -14595,7 +14595,7 @@
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
- Context, OO_Arrow, FnExpr.get(), Base, ResultTy, VK, OpLoc, CurFPFeatures);
+ Context, OO_Arrow, FnExpr.get(), Base, ResultTy, VK, OpLoc, CurFPFeatureOverrides());
if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method))
return ExprError();
@@ -14844,7 +14844,7 @@
return UnaryOperator::Create(
Context, SubExpr, UO_AddrOf, MemPtrType, VK_RValue, OK_Ordinary,
- UnOp->getOperatorLoc(), false, CurFPFeatures);
+ UnOp->getOperatorLoc(), false, CurFPFeatureOverrides());
}
}
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
@@ -14854,7 +14854,7 @@
return UnaryOperator::Create(
Context, SubExpr, UO_AddrOf, Context.getPointerType(SubExpr->getType()),
- VK_RValue, OK_Ordinary, UnOp->getOperatorLoc(), false, CurFPFeatures);
+ VK_RValue, OK_Ordinary, UnOp->getOperatorLoc(), false, CurFPFeatureOverrides());
}
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
Index: clang/lib/Sema/SemaExprObjC.cpp
===================================================================
--- clang/lib/Sema/SemaExprObjC.cpp
+++ clang/lib/Sema/SemaExprObjC.cpp
@@ -4487,7 +4487,7 @@
Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());
return UnaryOperator::Create(Context, sub, UO_Extension, sub->getType(),
sub->getValueKind(), sub->getObjectKind(),
- uo->getOperatorLoc(), false, CurFPFeatures);
+ uo->getOperatorLoc(), false, CurFPFeatureOverrides());
} else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
assert(!gse->isResultDependent());
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -13607,7 +13607,7 @@
BinaryOperatorKind Opc, QualType ResultTy,
ExprValueKind VK, ExprObjectKind OK,
bool IsCompAssign, SourceLocation OpLoc,
- FPOptions FPFeatures) {
+ FPOptionsOverride FPFeatures) {
auto &Context = S.getASTContext();
assert((isVector(ResultTy, Context.HalfTy) ||
isVector(ResultTy, Context.ShortTy)) &&
@@ -13928,9 +13928,9 @@
if (CompResultTy.isNull()) {
if (ConvertHalfVec)
return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, false,
- OpLoc, CurFPFeatures);
+ OpLoc, CurFPFeatureOverrides());
return BinaryOperator::Create(Context, LHS.get(), RHS.get(), Opc, ResultTy,
- VK, OK, OpLoc, CurFPFeatures);
+ VK, OK, OpLoc, CurFPFeatureOverrides());
}
// Handle compound assignments.
@@ -13948,10 +13948,10 @@
if (ConvertHalfVec)
return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, true,
- OpLoc, CurFPFeatures);
+ OpLoc, CurFPFeatureOverrides());
return CompoundAssignOperator::Create(Context, LHS.get(), RHS.get(), Opc,
- ResultTy, VK, OK, OpLoc, CurFPFeatures,
+ ResultTy, VK, OK, OpLoc, CurFPFeatureOverrides(),
CompLHSTy, CompResultTy);
}
@@ -14541,7 +14541,7 @@
CheckArrayAccess(Input.get());
auto *UO = UnaryOperator::Create(Context, Input.get(), Opc, resultType, VK,
- OK, OpLoc, CanOverflow, CurFPFeatures);
+ OK, OpLoc, CanOverflow, CurFPFeatureOverrides());
if (Opc == UO_Deref && UO->getType()->hasAttr(attr::NoDeref) &&
!isa<ArrayType>(UO->getType().getDesugaredType(Context)))
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -13494,11 +13494,11 @@
Expr *From = FromB.build(S, Loc);
From = UnaryOperator::Create(
S.Context, From, UO_AddrOf, S.Context.getPointerType(From->getType()),
- VK_RValue, OK_Ordinary, Loc, false, S.CurFPFeatures);
+ VK_RValue, OK_Ordinary, Loc, false, S.CurFPFeatureOverrides());
Expr *To = ToB.build(S, Loc);
To = UnaryOperator::Create(S.Context, To, UO_AddrOf,
S.Context.getPointerType(To->getType()), VK_RValue,
- OK_Ordinary, Loc, false, S.CurFPFeatures);
+ OK_Ordinary, Loc, false, S.CurFPFeatureOverrides());
const Type *E = T->getBaseElementTypeUnsafe();
bool NeedsCollectableMemCpy =
@@ -13735,14 +13735,14 @@
Expr *Comparison = BinaryOperator::Create(
S.Context, IterationVarRefRVal.build(S, Loc),
IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), BO_NE,
- S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc, S.CurFPFeatures);
+ S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc, S.CurFPFeatureOverrides());
// Create the pre-increment of the iteration variable. We can determine
// whether the increment will overflow based on the value of the array
// bound.
Expr *Increment = UnaryOperator::Create(
S.Context, IterationVarRef.build(S, Loc), UO_PreInc, SizeType, VK_LValue,
- OK_Ordinary, Loc, Upper.isMaxValue(), S.CurFPFeatures);
+ OK_Ordinary, Loc, Upper.isMaxValue(), S.CurFPFeatureOverrides());
// Construct the loop that copies all elements of this array.
return S.ActOnForStmt(
Index: clang/lib/Sema/SemaAttr.cpp
===================================================================
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -417,8 +417,9 @@
void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
PragmaMsStackAction Action,
PragmaFloatControlKind Value) {
- auto NewValue = FpPragmaStack.CurrentValue;
- FPOptions NewFPFeatures(NewValue);
+ unsigned NewValue = FpPragmaStack.hasValue() ?
+ FpPragmaStack.CurrentValue : CurFPFeatureOverrides().getAsOpaqueInt() ;
+ FPOptionsOverride NewFPFeatures(NewValue);
if ((Action == PSK_Push_Set || Action == PSK_Push || Action == PSK_Pop) &&
!(CurContext->isTranslationUnit()) && !CurContext->isNamespace()) {
// Push and pop can only occur at file or namespace scope.
@@ -429,8 +430,8 @@
default:
llvm_unreachable("invalid pragma float_control kind");
case PFC_Precise:
- CurFPFeatures.setFPPreciseEnabled(true);
- NewValue = CurFPFeatures.getAsOpaqueInt();
+ NewFPFeatures.setFPPreciseEnabled(true);
+ NewValue = NewFPFeatures.getAsOpaqueInt();
FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
break;
case PFC_NoPrecise:
@@ -439,27 +440,27 @@
else if (CurFPFeatures.allowFEnvAccess())
Diag(Loc, diag::err_pragma_fc_noprecise_requires_nofenv);
else
- CurFPFeatures.setFPPreciseEnabled(false);
- NewValue = CurFPFeatures.getAsOpaqueInt();
+ NewFPFeatures.setFPPreciseEnabled(false);
+ NewValue = NewFPFeatures.getAsOpaqueInt();
FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
break;
case PFC_Except:
if (!isPreciseFPEnabled())
Diag(Loc, diag::err_pragma_fc_except_requires_precise);
else
- CurFPFeatures.setExceptionMode(LangOptions::FPE_Strict);
- NewValue = CurFPFeatures.getAsOpaqueInt();
+ NewFPFeatures.setExceptionMode(LangOptions::FPE_Strict);
+ NewValue = NewFPFeatures.getAsOpaqueInt();
FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
break;
case PFC_NoExcept:
- CurFPFeatures.setExceptionMode(LangOptions::FPE_Ignore);
- NewValue = CurFPFeatures.getAsOpaqueInt();
+ NewFPFeatures.setExceptionMode(LangOptions::FPE_Ignore);
+ NewValue = NewFPFeatures.getAsOpaqueInt();
FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
break;
case PFC_Push:
if (FpPragmaStack.Stack.empty()) {
FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(),
- CurFPFeatures.getAsOpaqueInt());
+ NewFPFeatures.getAsOpaqueInt());
}
FpPragmaStack.Act(Loc, Sema::PSK_Push_Set, StringRef(),
NewFPFeatures.getAsOpaqueInt());
@@ -471,10 +472,12 @@
return;
}
FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures.getAsOpaqueInt());
+ assert(FpPragmaStack.hasValue());
NewValue = FpPragmaStack.CurrentValue;
- CurFPFeatures.getFromOpaqueInt(NewValue);
break;
}
+ FPOptionsOverride NewOverrides(NewValue);
+ CurFPFeatures = NewOverrides.mergeOverrides(getLangOpts());
}
void Sema::ActOnPragmaMSPointersToMembers(
@@ -1003,33 +1006,73 @@
}
}
-void Sema::ActOnPragmaFPContract(LangOptions::FPModeKind FPC) {
+void Sema::ActOnPragmaFPContract(SourceLocation Loc,
+ LangOptions::FPModeKind FPC) {
+ unsigned NewValue = FpPragmaStack.hasValue() ?
+ FpPragmaStack.CurrentValue : CurFPFeatureOverrides().getAsOpaqueInt() ;
+ FPOptionsOverride NewFPFeatures(NewValue);
switch (FPC) {
+ case LangOptions::FPM_Unset:
+ llvm_unreachable("invalid clang fp_contract kind");
case LangOptions::FPM_On:
- CurFPFeatures.setAllowFPContractWithinStatement();
+ NewFPFeatures.setAllowFPContractWithinStatement();
break;
case LangOptions::FPM_Fast:
- CurFPFeatures.setAllowFPContractAcrossStatement();
+ NewFPFeatures.setAllowFPContractAcrossStatement();
break;
case LangOptions::FPM_Off:
- CurFPFeatures.setDisallowFPContract();
+ NewFPFeatures.setDisallowFPContract();
break;
}
+ CurFPFeatures = NewFPFeatures.mergeOverrides(getLangOpts());
+ FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(),
+ NewFPFeatures.getAsOpaqueInt());
}
-void Sema::ActOnPragmaFPReassociate(bool IsEnabled) {
- CurFPFeatures.setAllowAssociativeMath(IsEnabled);
+void Sema::ActOnPragmaFPReassociate(SourceLocation Loc, bool IsEnabled) {
+ unsigned NewValue = FpPragmaStack.hasValue() ?
+ FpPragmaStack.CurrentValue : CurFPFeatureOverrides().getAsOpaqueInt() ;
+ FPOptionsOverride NewFPFeatures(NewValue);
+ if (IsEnabled) {
+ NewFPFeatures.setAllowAssociativeMathEnabled(true);
+ NewFPFeatures.setAllowAssociativeMathDisabled(false);
+ } else {
+ NewFPFeatures.setAllowAssociativeMathEnabled(false);
+ NewFPFeatures.setAllowAssociativeMathDisabled(true);
+ }
+ NewValue = NewFPFeatures.getAsOpaqueInt();
+ FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
+ FPOptionsOverride NewOverrides(NewValue);
+ CurFPFeatures = NewOverrides.mergeOverrides(getLangOpts());
}
-void Sema::setRoundingMode(llvm::RoundingMode FPR) {
- CurFPFeatures.setRoundingMode(FPR);
+void Sema::setRoundingMode(SourceLocation Loc, llvm::RoundingMode FPR) {
+ unsigned NewValue = FpPragmaStack.hasValue() ?
+ FpPragmaStack.CurrentValue : CurFPFeatureOverrides().getAsOpaqueInt() ;
+ FPOptionsOverride NewFPFeatures(NewValue);
+ NewFPFeatures.setRoundingMode(FPR);
+ NewValue = NewFPFeatures.getAsOpaqueInt();
+ FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
+ FPOptionsOverride NewOverrides(NewValue);
+ CurFPFeatures = NewOverrides.mergeOverrides(getLangOpts());
}
-void Sema::setExceptionMode(LangOptions::FPExceptionModeKind FPE) {
- CurFPFeatures.setExceptionMode(FPE);
+void Sema::setExceptionMode(SourceLocation Loc,
+ LangOptions::FPExceptionModeKind FPE) {
+ unsigned NewValue = FpPragmaStack.hasValue() ?
+ FpPragmaStack.CurrentValue : CurFPFeatureOverrides().getAsOpaqueInt() ;
+ FPOptionsOverride NewFPFeatures(NewValue);
+ NewFPFeatures.setExceptionMode(FPE);
+ NewValue = NewFPFeatures.getAsOpaqueInt();
+ FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
+ FPOptionsOverride NewOverrides(NewValue);
+ CurFPFeatures = NewOverrides.mergeOverrides(getLangOpts());
}
void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) {
+ unsigned NewValue = FpPragmaStack.hasValue() ?
+ FpPragmaStack.CurrentValue : CurFPFeatureOverrides().getAsOpaqueInt() ;
+ FPOptionsOverride NewFPFeatures(NewValue);
if (IsEnabled) {
// Verify Microsoft restriction:
// You can't enable fenv_access unless precise semantics are enabled.
@@ -1037,9 +1080,13 @@
// pragma, or by using the /fp:precise or /fp:strict compiler options
if (!isPreciseFPEnabled())
Diag(Loc, diag::err_pragma_fenv_requires_precise);
- CurFPFeatures.setAllowFEnvAccess();
+ NewFPFeatures.setAllowFEnvAccess();
} else
- CurFPFeatures.setDisallowFEnvAccess();
+ NewFPFeatures.setDisallowFEnvAccess();
+ NewValue = NewFPFeatures.getAsOpaqueInt();
+ FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
+ FPOptionsOverride NewOverrides(NewValue);
+ CurFPFeatures = NewOverrides.mergeOverrides(getLangOpts());
}
void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -159,7 +159,7 @@
LangOpts.getMSPointerToMemberRepresentationMethod()),
VtorDispStack(LangOpts.getVtorDispMode()), PackStack(0),
DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
- CodeSegStack(nullptr), FpPragmaStack(CurFPFeatures.getAsOpaqueInt()),
+ CodeSegStack(nullptr), FpPragmaStack(0xFFFFFFFF),
CurInitSeg(nullptr), VisContext(nullptr),
PragmaAttributeCurrentTargetDecl(nullptr),
IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr),
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -654,8 +654,8 @@
break;
}
- Actions.ActOnPragmaFPContract(FPC);
- ConsumeAnnotationToken();
+ SourceLocation PragmaLoc = ConsumeAnnotationToken();
+ Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
}
void Parser::HandlePragmaFloatControl() {
@@ -2935,8 +2935,8 @@
reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
if (AnnotValue->FlagKind == TokFPAnnotValue::Reassociate)
- Actions.ActOnPragmaFPReassociate(AnnotValue->FlagValue ==
- TokFPAnnotValue::On);
+ Actions.ActOnPragmaFPReassociate(Tok.getLocation(),
+ AnnotValue->FlagValue == TokFPAnnotValue::On);
else {
LangOptions::FPModeKind FPC;
switch (AnnotValue->FlagValue) {
@@ -2950,7 +2950,7 @@
FPC = LangOptions::FPM_Fast;
break;
}
- Actions.ActOnPragmaFPContract(FPC);
+ Actions.ActOnPragmaFPContract(Tok.getLocation(), FPC);
}
ConsumeAnnotationToken();
}
Index: clang/lib/Frontend/Rewrite/RewriteObjC.cpp
===================================================================
--- clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -2517,7 +2517,7 @@
Expr *Unop = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
// cast to NSConstantString *
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
CK_CPointerToObjCPointerCast, Unop);
@@ -2718,7 +2718,7 @@
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
CK_BitCast, SuperRep);
@@ -2736,7 +2736,7 @@
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
}
MsgExprs.push_back(SuperRep);
break;
@@ -2813,7 +2813,7 @@
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
CK_BitCast, SuperRep);
@@ -2999,7 +2999,7 @@
SourceLocation());
BinaryOperator *lessThanExpr = BinaryOperator::Create(
*Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_RValue,
- OK_Ordinary, SourceLocation(), FPOptions(Context->getLangOpts()));
+ OK_Ordinary, SourceLocation(), FPOptionsOverride());
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
ConditionalOperator *CondExpr =
new (Context) ConditionalOperator(lessThanExpr,
@@ -3052,7 +3052,7 @@
Expr *DerefExpr = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
CK_BitCast,
DerefExpr);
@@ -3880,7 +3880,7 @@
Expr *Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), DRE,
UO_Deref, DRE->getType(), VK_LValue,
OK_Ordinary, DRE->getLocation(), false,
- FPOptions(Context->getLangOpts()));
+ FPOptionsOverride());
// Need parens to enforce precedence.
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
Exp);
@@ -4440,7 +4440,7 @@
new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
VK_LValue, SourceLocation()),
UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue,
- OK_Ordinary, SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
InitExprs.push_back(DescRefExpr);
// Add initializers for any closure decl refs.
@@ -4460,7 +4460,7 @@
Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
UO_AddrOf, QT, VK_RValue, OK_Ordinary,
SourceLocation(), false,
- FPOptions(Context->getLangOpts()));
+ FPOptionsOverride());
}
} else if (isTopLevelBlockPointerType((*I)->getType())) {
FD = SynthBlockInitFunctionDecl((*I)->getName());
@@ -4478,7 +4478,7 @@
Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
UO_AddrOf, QT, VK_RValue, OK_Ordinary,
SourceLocation(), false,
- FPOptions(Context->getLangOpts()));
+ FPOptionsOverride());
}
}
InitExprs.push_back(Exp);
@@ -4518,7 +4518,7 @@
Exp = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
Context->getPointerType(Exp->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
InitExprs.push_back(Exp);
}
@@ -4537,7 +4537,7 @@
NewRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
NewRep);
BlockDeclRefs.clear();
Index: clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
===================================================================
--- clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -2590,7 +2590,7 @@
Expr *Unop = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
// cast to NSConstantString *
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
CK_CPointerToObjCPointerCast, Unop);
@@ -3287,7 +3287,7 @@
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
CK_BitCast, SuperRep);
@@ -3305,7 +3305,7 @@
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
}
MsgExprs.push_back(SuperRep);
break;
@@ -3382,7 +3382,7 @@
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
CK_BitCast, SuperRep);
@@ -4709,7 +4709,7 @@
Expr *Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), DRE,
UO_Deref, DRE->getType(), VK_LValue,
OK_Ordinary, DRE->getLocation(), false,
- FPOptions(Context->getLangOpts()));
+ FPOptionsOverride());
// Need parens to enforce precedence.
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
Exp);
@@ -5300,7 +5300,7 @@
new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
VK_LValue, SourceLocation()),
UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue,
- OK_Ordinary, SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
InitExprs.push_back(DescRefExpr);
// Add initializers for any closure decl refs.
@@ -5320,7 +5320,7 @@
Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
UO_AddrOf, QT, VK_RValue, OK_Ordinary,
SourceLocation(), false,
- FPOptions(Context->getLangOpts()));
+ FPOptionsOverride());
}
} else if (isTopLevelBlockPointerType((*I)->getType())) {
FD = SynthBlockInitFunctionDecl((*I)->getName());
@@ -5338,7 +5338,7 @@
Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
UO_AddrOf, QT, VK_RValue, OK_Ordinary,
SourceLocation(), false,
- FPOptions(Context->getLangOpts()));
+ FPOptionsOverride());
}
}
@@ -5379,7 +5379,7 @@
Exp = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
Context->getPointerType(Exp->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
InitExprs.push_back(Exp);
}
@@ -5406,7 +5406,7 @@
NewRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(Context->getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
NewRep);
// Put Paren around the call.
@@ -7494,7 +7494,7 @@
BinaryOperator *addExpr = BinaryOperator::Create(
*Context, castExpr, DRE, BO_Add,
Context->getPointerType(Context->CharTy), VK_RValue, OK_Ordinary,
- SourceLocation(), FPOptions(Context->getLangOpts()));
+ SourceLocation(), FPOptionsOverride());
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),
SourceLocation(),
@@ -7548,7 +7548,7 @@
Expr *Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context),
castExpr, UO_Deref, IvarT, VK_LValue,
OK_Ordinary, SourceLocation(), false,
- FPOptions(Context->getLangOpts()));
+ FPOptionsOverride());
PE = new (Context) ParenExpr(OldRange.getBegin(),
OldRange.getEnd(),
Exp);
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -97,6 +97,7 @@
clang::ToConstrainedExceptMD(LangOptions::FPExceptionModeKind Kind) {
switch (Kind) {
+ case LangOptions::FPE_Unset: break;
case LangOptions::FPE_Ignore: return llvm::fp::ebIgnore;
case LangOptions::FPE_MayTrap: return llvm::fp::ebMayTrap;
case LangOptions::FPE_Strict: return llvm::fp::ebStrict;
Index: clang/lib/CodeGen/CGStmtOpenMP.cpp
===================================================================
--- clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -3318,11 +3318,11 @@
// Generate condition for loop.
BinaryOperator *Cond = BinaryOperator::Create(
C, &IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue, OK_Ordinary,
- S.getBeginLoc(), FPOptions(C.getLangOpts()));
+ S.getBeginLoc(), FPOptionsOverride());
// Increment for loop counter.
UnaryOperator *Inc = UnaryOperator::Create(
C, &IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
- S.getBeginLoc(), true, FPOptions(C.getLangOpts()));
+ S.getBeginLoc(), true, FPOptionsOverride());
auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
// Iterate through all sections and emit a switch construct:
// switch (IV) {
Index: clang/lib/CodeGen/CGObjC.cpp
===================================================================
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -1494,7 +1494,7 @@
BinaryOperator *assign = BinaryOperator::Create(
getContext(), &ivarRef, finalArg, BO_Assign, ivarRef.getType(), VK_RValue,
OK_Ordinary, SourceLocation(),
- FPOptions(getContext().getLangOpts()));
+ FPOptionsOverride());
EmitStmt(assign);
}
@@ -3556,18 +3556,18 @@
DeclRefExpr DstExpr(C, &DstDecl, false, DestTy, VK_RValue, SourceLocation());
UnaryOperator *DST = UnaryOperator::Create(
C, &DstExpr, UO_Deref, DestTy->getPointeeType(), VK_LValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(C.getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
DeclRefExpr SrcExpr(C, &SrcDecl, false, SrcTy, VK_RValue, SourceLocation());
UnaryOperator *SRC = UnaryOperator::Create(
C, &SrcExpr, UO_Deref, SrcTy->getPointeeType(), VK_LValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(C.getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
Expr *Args[2] = {DST, SRC};
CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment());
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
C, OO_Equal, CalleeExp->getCallee(), Args, DestTy->getPointeeType(),
- VK_LValue, SourceLocation(), FPOptions(C.getLangOpts()));
+ VK_LValue, SourceLocation(), FPOptionsOverride());
EmitStmt(TheCall);
@@ -3641,7 +3641,7 @@
UnaryOperator *SRC = UnaryOperator::Create(
C, &SrcExpr, UO_Deref, SrcTy->getPointeeType(), VK_LValue, OK_Ordinary,
- SourceLocation(), false, FPOptions(C.getLangOpts()));
+ SourceLocation(), false, FPOptionsOverride());
CXXConstructExpr *CXXConstExpr =
cast<CXXConstructExpr>(PID->getGetterCXXConstructor());
Index: clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- clang/lib/CodeGen/CGExprScalar.cpp
+++ clang/lib/CodeGen/CGExprScalar.cpp
@@ -2383,7 +2383,7 @@
if (!E->canOverflow())
return Builder.CreateNSWAdd(InVal, Amount, Name);
return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
- E, InVal, IsInc, E->getFPFeatures(CGF.getLangOpts())));
+ E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts())));
}
llvm_unreachable("Unknown SignedOverflowBehaviorTy");
}
@@ -2530,7 +2530,7 @@
} else if (E->canOverflow() && type->isUnsignedIntegerType() &&
CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) {
value = EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
- E, value, isInc, E->getFPFeatures(CGF.getLangOpts())));
+ E, value, isInc, E->getFPFeaturesInEffect(CGF.getLangOpts())));
} else {
llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount, true);
value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec");
@@ -2730,7 +2730,7 @@
BinOp.LHS = llvm::Constant::getNullValue(BinOp.RHS->getType());
BinOp.Ty = E->getType();
BinOp.Opcode = BO_Sub;
- BinOp.FPFeatures = E->getFPFeatures(CGF.getLangOpts());
+ BinOp.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
BinOp.E = E;
return EmitSub(BinOp);
}
@@ -2751,7 +2751,7 @@
Value *Result;
if (Oper->getType()->isFPOrFPVectorTy()) {
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(
- CGF, E->getFPFeatures(CGF.getLangOpts()));
+ CGF, E->getFPFeaturesInEffect(CGF.getLangOpts()));
Result = Builder.CreateFCmp(llvm::CmpInst::FCMP_OEQ, Oper, Zero, "cmp");
} else
Result = Builder.CreateICmp(llvm::CmpInst::ICMP_EQ, Oper, Zero, "cmp");
@@ -2954,7 +2954,7 @@
Result.RHS = Visit(E->getRHS());
Result.Ty = E->getType();
Result.Opcode = E->getOpcode();
- Result.FPFeatures = E->getFPFeatures(CGF.getLangOpts());
+ Result.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
Result.E = E;
return Result;
}
@@ -2974,7 +2974,7 @@
OpInfo.RHS = Visit(E->getRHS());
OpInfo.Ty = E->getComputationResultType();
OpInfo.Opcode = E->getOpcode();
- OpInfo.FPFeatures = E->getFPFeatures(CGF.getLangOpts());
+ OpInfo.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
OpInfo.E = E;
// Load/convert the LHS.
LValue LHSLV = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store);
@@ -4208,7 +4208,7 @@
Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType());
if (LHS->getType()->isFPOrFPVectorTy()) {
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(
- CGF, E->getFPFeatures(CGF.getLangOpts()));
+ CGF, E->getFPFeaturesInEffect(CGF.getLangOpts()));
LHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, LHS, Zero, "cmp");
RHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, RHS, Zero, "cmp");
} else {
@@ -4294,7 +4294,7 @@
Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType());
if (LHS->getType()->isFPOrFPVectorTy()) {
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(
- CGF, E->getFPFeatures(CGF.getLangOpts()));
+ CGF, E->getFPFeaturesInEffect(CGF.getLangOpts()));
LHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, LHS, Zero, "cmp");
RHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, RHS, Zero, "cmp");
} else {
Index: clang/lib/CodeGen/BackendUtil.cpp
===================================================================
--- clang/lib/CodeGen/BackendUtil.cpp
+++ clang/lib/CodeGen/BackendUtil.cpp
@@ -449,6 +449,8 @@
// Set FP fusion mode.
switch (LangOpts.getDefaultFPContractMode()) {
+ case LangOptions::FPM_Unset:
+ llvm_unreachable("Invalid fp_contract mode!");
case LangOptions::FPM_Off:
// Preserve any contraction performed by the front-end. (Strict performs
// splitting of the muladd intrinsic in the backend.)
Index: clang/lib/Basic/LangOptions.cpp
===================================================================
--- clang/lib/Basic/LangOptions.cpp
+++ clang/lib/Basic/LangOptions.cpp
@@ -52,7 +52,3 @@
FPOptions result(LO);
return result;
}
-
-bool FPOptions::requiresTrailingStorage(const LangOptions &LO) {
- return getAsOpaqueInt() != defaultWithoutTrailingStorage(LO).getAsOpaqueInt();
-}
Index: clang/lib/Analysis/BodyFarm.cpp
===================================================================
--- clang/lib/Analysis/BodyFarm.cpp
+++ clang/lib/Analysis/BodyFarm.cpp
@@ -116,7 +116,7 @@
QualType Ty) {
return BinaryOperator::Create(
C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), BO_Assign, Ty,
- VK_RValue, OK_Ordinary, SourceLocation(), FPOptions(C.getLangOpts()));
+ VK_RValue, OK_Ordinary, SourceLocation(), FPOptionsOverride());
}
BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
@@ -127,7 +127,7 @@
const_cast<Expr *>(RHS), Op,
C.getLogicalOperationType(), VK_RValue,
OK_Ordinary, SourceLocation(),
- FPOptions(C.getLangOpts()));
+ FPOptionsOverride());
}
CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
@@ -149,7 +149,7 @@
return UnaryOperator::Create(C, const_cast<Expr *>(Arg), UO_Deref, Ty,
VK_LValue, OK_Ordinary, SourceLocation(),
/*CanOverflow*/ false,
- FPOptions(C.getLangOpts()));
+ FPOptionsOverride());
}
ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
@@ -297,7 +297,7 @@
/*QualType=*/C.VoidTy,
/*ExprValueType=*/VK_RValue,
/*SourceLocation=*/SourceLocation(),
- /*FPFeatures=*/FPOptions(C.getLangOpts()));
+ /*FPFeatures=*/FPOptionsOverride());
}
/// Create a fake body for std::call_once.
@@ -457,7 +457,7 @@
/* QualType=*/C.IntTy,
/* ExprValueKind=*/VK_RValue,
/* ExprObjectKind=*/OK_Ordinary, SourceLocation(),
- /* CanOverflow*/ false, FPOptions(C.getLangOpts()));
+ /* CanOverflow*/ false, FPOptionsOverride());
// Create assignment.
BinaryOperator *FlagAssignment = M.makeAssignment(
@@ -522,7 +522,7 @@
Expr *DoneValue =
UnaryOperator::Create(C, M.makeIntegerLiteral(0, C.LongTy), UO_Not,
C.LongTy, VK_RValue, OK_Ordinary, SourceLocation(),
- /*CanOverflow*/ false, FPOptions(C.getLangOpts()));
+ /*CanOverflow*/ false, FPOptionsOverride());
BinaryOperator *B =
M.makeAssignment(
Index: clang/lib/AST/ExprCXX.cpp
===================================================================
--- clang/lib/AST/ExprCXX.cpp
+++ clang/lib/AST/ExprCXX.cpp
@@ -525,7 +525,7 @@
Expr *Fn, ArrayRef<Expr *> Args,
QualType Ty, ExprValueKind VK,
SourceLocation OperatorLoc,
- FPOptions FPFeatures,
+ FPOptionsOverride FPFeatures,
ADLCallKind UsesADL)
: CallExpr(CXXOperatorCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
OperatorLoc, /*MinNumArgs=*/0, UsesADL) {
@@ -545,7 +545,7 @@
CXXOperatorCallExpr *CXXOperatorCallExpr::Create(
const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn,
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
- SourceLocation OperatorLoc, FPOptions FPFeatures, ADLCallKind UsesADL) {
+ SourceLocation OperatorLoc, FPOptionsOverride FPFeatures, ADLCallKind UsesADL) {
// Allocate storage for the trailing objects of CallExpr.
unsigned NumArgs = Args.size();
unsigned SizeOfTrailingObjects =
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -4461,7 +4461,7 @@
BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
Opcode opc, QualType ResTy, ExprValueKind VK,
ExprObjectKind OK, SourceLocation opLoc,
- FPOptions FPFeatures)
+ FPOptionsOverride FPFeatures)
: Expr(BinaryOperatorClass, ResTy, VK, OK) {
BinaryOperatorBits.Opc = opc;
assert(!isCompoundAssignmentOp() &&
@@ -4470,7 +4470,7 @@
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
BinaryOperatorBits.HasFPFeatures =
- FPFeatures.requiresTrailingStorage(Ctx.getLangOpts());
+ FPFeatures.requiresTrailingStorage();
if (BinaryOperatorBits.HasFPFeatures)
*getTrailingFPFeatures() = FPFeatures;
setDependence(computeDependence(this));
@@ -4479,7 +4479,7 @@
BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
Opcode opc, QualType ResTy, ExprValueKind VK,
ExprObjectKind OK, SourceLocation opLoc,
- FPOptions FPFeatures, bool dead2)
+ FPOptionsOverride FPFeatures, bool dead2)
: Expr(CompoundAssignOperatorClass, ResTy, VK, OK) {
BinaryOperatorBits.Opc = opc;
assert(isCompoundAssignmentOp() &&
@@ -4488,7 +4488,7 @@
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
BinaryOperatorBits.HasFPFeatures =
- FPFeatures.requiresTrailingStorage(Ctx.getLangOpts());
+ FPFeatures.requiresTrailingStorage();
if (BinaryOperatorBits.HasFPFeatures)
*getTrailingFPFeatures() = FPFeatures;
setDependence(computeDependence(this));
@@ -4506,8 +4506,8 @@
Expr *rhs, Opcode opc, QualType ResTy,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation opLoc,
- FPOptions FPFeatures) {
- bool HasFPFeatures = FPFeatures.requiresTrailingStorage(C.getLangOpts());
+ FPOptionsOverride FPFeatures) {
+ bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
void *Mem =
C.Allocate(sizeof(BinaryOperator) + Extra, alignof(BinaryOperator));
@@ -4526,8 +4526,8 @@
CompoundAssignOperator *CompoundAssignOperator::Create(
const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc,
- FPOptions FPFeatures, QualType CompLHSType, QualType CompResultType) {
- bool HasFPFeatures = FPFeatures.requiresTrailingStorage(C.getLangOpts());
+ FPOptionsOverride FPFeatures, QualType CompLHSType, QualType CompResultType) {
+ bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
void *Mem = C.Allocate(sizeof(CompoundAssignOperator) + Extra,
alignof(CompoundAssignOperator));
@@ -4538,7 +4538,7 @@
UnaryOperator *UnaryOperator::CreateEmpty(const ASTContext &C,
bool hasFPFeatures) {
- void *Mem = C.Allocate(totalSizeToAlloc<FPOptions>(hasFPFeatures),
+ void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(hasFPFeatures),
alignof(UnaryOperator));
return new (Mem) UnaryOperator(hasFPFeatures, EmptyShell());
}
@@ -4546,13 +4546,13 @@
UnaryOperator::UnaryOperator(const ASTContext &Ctx, Expr *input, Opcode opc,
QualType type, ExprValueKind VK, ExprObjectKind OK,
SourceLocation l, bool CanOverflow,
- FPOptions FPFeatures)
+ FPOptionsOverride FPFeatures)
: Expr(UnaryOperatorClass, type, VK, OK), Val(input) {
UnaryOperatorBits.Opc = opc;
UnaryOperatorBits.CanOverflow = CanOverflow;
UnaryOperatorBits.Loc = l;
UnaryOperatorBits.HasFPFeatures =
- FPFeatures.requiresTrailingStorage(Ctx.getLangOpts());
+ FPFeatures.requiresTrailingStorage();
setDependence(computeDependence(this));
}
@@ -4560,9 +4560,9 @@
Opcode opc, QualType type,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation l, bool CanOverflow,
- FPOptions FPFeatures) {
- bool HasFPFeatures = FPFeatures.requiresTrailingStorage(C.getLangOpts());
- unsigned Size = totalSizeToAlloc<FPOptions>(HasFPFeatures);
+ FPOptionsOverride FPFeatures) {
+ bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
+ unsigned Size = totalSizeToAlloc<FPOptionsOverride>(HasFPFeatures);
void *Mem = C.Allocate(Size, alignof(UnaryOperator));
return new (Mem)
UnaryOperator(C, input, opc, type, VK, OK, l, CanOverflow, FPFeatures);
Index: clang/include/clang/Serialization/ASTWriter.h
===================================================================
--- clang/include/clang/Serialization/ASTWriter.h
+++ clang/include/clang/Serialization/ASTWriter.h
@@ -506,7 +506,7 @@
bool IsModule);
void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord);
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
- void WriteFPPragmaOptions(const FPOptions &Opts);
+ void WriteFPPragmaOptions(const FPOptionsOverride &Opts);
void WriteOpenCLExtensions(Sema &SemaRef);
void WriteOpenCLExtensionTypes(Sema &SemaRef);
void WriteOpenCLExtensionDecls(Sema &SemaRef);
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -557,6 +557,11 @@
// This stack tracks the current state of Sema.CurFPFeatures.
PragmaStack<unsigned> FpPragmaStack;
+ FPOptionsOverride CurFPFeatureOverrides() {
+ if (!FpPragmaStack.hasValue())
+ return FPOptionsOverride();
+ return FPOptionsOverride(FpPragmaStack.CurrentValue);
+ }
// RAII object to push / pop sentinel slots for all MS #pragma stacks.
// Actions should be performed only if we enter / exit a C++ method body.
@@ -1357,12 +1362,19 @@
/// statements.
class FPFeaturesStateRAII {
public:
- FPFeaturesStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.CurFPFeatures) {}
- ~FPFeaturesStateRAII() { S.CurFPFeatures = OldFPFeaturesState; }
+ FPFeaturesStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.CurFPFeatures) {
+ OldOverrides = S.FpPragmaStack.CurrentValue;
+ }
+ ~FPFeaturesStateRAII() {
+ S.CurFPFeatures = OldFPFeaturesState;
+ S.FpPragmaStack.CurrentValue = OldOverrides;
+ }
+ unsigned getOverrides(){ return OldOverrides; }
private:
Sema& S;
FPOptions OldFPFeaturesState;
+ unsigned OldOverrides;
};
void addImplicitTypedef(StringRef Name, QualType T);
@@ -9635,21 +9647,21 @@
/// ActOnPragmaFPContract - Called on well formed
/// \#pragma {STDC,OPENCL} FP_CONTRACT and
/// \#pragma clang fp contract
- void ActOnPragmaFPContract(LangOptions::FPModeKind FPC);
+ void ActOnPragmaFPContract(SourceLocation Loc, LangOptions::FPModeKind FPC);
/// Called on well formed
/// \#pragma clang fp reassociate
- void ActOnPragmaFPReassociate(bool IsEnabled);
+ void ActOnPragmaFPReassociate(SourceLocation Loc, bool IsEnabled);
/// ActOnPragmaFenvAccess - Called on well formed
/// \#pragma STDC FENV_ACCESS
void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled);
/// Called to set rounding mode for floating point operations.
- void setRoundingMode(llvm::RoundingMode);
+ void setRoundingMode(SourceLocation Loc, llvm::RoundingMode);
/// Called to set exception behavior for floating point operations.
- void setExceptionMode(LangOptions::FPExceptionModeKind);
+ void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind);
/// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
/// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -182,7 +182,10 @@
FPM_On,
// Aggressively fuse FP ops (E.g. FMA).
- FPM_Fast
+ FPM_Fast,
+
+ /// The exception mode override is not provided
+ FPM_Unset
};
/// Alias for RoundingMode::NearestTiesToEven.
@@ -196,7 +199,9 @@
/// Transformations do not cause new exceptions but may hide some.
FPE_MayTrap,
/// Strictly preserve the floating-point exception semantics.
- FPE_Strict
+ FPE_Strict,
+ /// The exception mode override is not provided
+ FPE_Unset
};
enum class LaxVectorConversionKind {
@@ -366,6 +371,7 @@
};
/// Floating point control options
+class FPOptionsOverride;
class FPOptions {
using RoundingMode = llvm::RoundingMode;
@@ -390,18 +396,10 @@
approx_func(LangOpts.ApproxFunc) {}
// FIXME: Use getDefaultFEnvAccessMode() when available.
- void setFastMath(bool B = true) {
- allow_reassoc = no_nans = no_infs = no_signed_zeros = approx_func =
- allow_reciprocal = B;
- }
-
/// Return the default value of FPOptions that's used when trailing
/// storage isn't required.
static FPOptions defaultWithoutTrailingStorage(const LangOptions &LO);
- /// Does this FPOptions require trailing storage when stored in various
- /// AST nodes, or can it be recreated using `defaultWithoutTrailingStorage`?
- bool requiresTrailingStorage(const LangOptions &LO);
bool allowFPContractWithinStatement() const {
return fp_contract == LangOptions::FPM_On;
@@ -411,50 +409,16 @@
return fp_contract == LangOptions::FPM_Fast;
}
- void setAllowFPContractWithinStatement() {
- fp_contract = LangOptions::FPM_On;
- }
-
- void setAllowFPContractAcrossStatement() {
- fp_contract = LangOptions::FPM_Fast;
- }
-
- void setDisallowFPContract() { fp_contract = LangOptions::FPM_Off; }
-
bool allowFEnvAccess() const { return fenv_access == LangOptions::FPM_On; }
- void setAllowFEnvAccess() { fenv_access = LangOptions::FPM_On; }
-
- void setFPPreciseEnabled(bool Value) {
- if (Value) {
- /* Precise mode implies fp_contract=on and disables ffast-math */
- setFastMath(false);
- setAllowFPContractWithinStatement();
- } else {
- /* Precise mode implies fp_contract=fast and enables ffast-math */
- setFastMath(true);
- setAllowFPContractAcrossStatement();
- }
- }
-
- void setDisallowFEnvAccess() { fenv_access = LangOptions::FPM_Off; }
-
RoundingMode getRoundingMode() const {
return static_cast<RoundingMode>(rounding);
}
- void setRoundingMode(RoundingMode RM) {
- rounding = static_cast<unsigned>(RM);
- }
-
LangOptions::FPExceptionModeKind getExceptionMode() const {
return static_cast<LangOptions::FPExceptionModeKind>(exceptions);
}
- void setExceptionMode(LangOptions::FPExceptionModeKind EM) {
- exceptions = EM;
- }
-
/// FMF Flag queries
bool allowAssociativeMath() const { return allow_reassoc; }
bool noHonorNaNs() const { return no_nans; }
@@ -527,6 +491,271 @@
/// Approximate functions - Allow substitution of approximate calculations
/// for functions (sin, log, sqrt, etc).
unsigned approx_func : 1;
+ friend class FPOptionsOverride;
+};
+
+/// Override global Floating point control options with
+/// settings from floating point pragmas.
+class FPOptionsOverride {
+ using RoundingMode = llvm::RoundingMode;
+
+public:
+ FPOptionsOverride()
+ : fp_contract(LangOptions::FPM_Unset),
+ rounding(static_cast<unsigned>( llvm::RoundingMode::Unset)),
+ exceptions(LangOptions::FPE_Unset),
+ fenv_access_enabled(0),
+ fenv_access_disabled(0),
+ allow_reassoc_enabled(0),
+ no_nans_enabled(0),
+ no_infs_enabled(0),
+ no_signed_zeros_enabled(0),
+ allow_reciprocal_enabled(0),
+ approx_func_enabled(0),
+ allow_reassoc_disabled(0),
+ no_nans_disabled(0),
+ no_infs_disabled(0),
+ no_signed_zeros_disabled(0),
+ allow_reciprocal_disabled(0),
+ approx_func_disabled(0) {}
+
+ // Used for serializing.
+ explicit FPOptionsOverride(unsigned I) { getFromOpaqueInt(I); }
+
+ void setFastMathEnabled(bool B = true) {
+ allow_reassoc_enabled = no_nans_enabled = no_infs_enabled =
+ no_signed_zeros_enabled = approx_func_enabled =
+ allow_reciprocal_enabled = B;
+ }
+
+ void setFastMathDisabled(bool B = true) {
+ allow_reassoc_disabled = no_nans_disabled = no_infs_disabled =
+ no_signed_zeros_disabled = approx_func_disabled =
+ allow_reciprocal_disabled = B;
+ }
+
+ bool allowFPContractWithinStatement() const {
+ return fp_contract == LangOptions::FPM_On;
+ }
+
+ bool allowFPContractAcrossStatement() const {
+ return fp_contract == LangOptions::FPM_Fast;
+ }
+
+ void setAllowFPContractWithinStatement() {
+ fp_contract = LangOptions::FPM_On;
+ }
+
+ void setAllowFPContractAcrossStatement() {
+ fp_contract = LangOptions::FPM_Fast;
+ }
+
+ void setDisallowFPContract() { fp_contract = LangOptions::FPM_Off; }
+
+ void setAllowFEnvAccess() {
+ fenv_access_enabled = true;
+ fenv_access_disabled = false;
+ }
+ void setDisallowFEnvAccess() {
+ fenv_access_enabled = false;
+ fenv_access_disabled = true;
+ }
+
+ void setFPPreciseEnabled(bool Value) {
+ if (Value) {
+ /* Precise mode implies fp_contract=on and disables ffast-math */
+ setFastMathEnabled(false);
+ setFastMathDisabled(true);
+ setAllowFPContractWithinStatement();
+ } else {
+ /* Precise mode implies fp_contract=fast and enables ffast-math */
+ setFastMathEnabled(true);
+ setFastMathDisabled(false);
+ setAllowFPContractAcrossStatement();
+ }
+ }
+
+ RoundingMode getRoundingMode() const {
+ return static_cast<RoundingMode>(rounding);
+ }
+
+ void setRoundingMode(RoundingMode RM) {
+ rounding = static_cast<unsigned>(RM);
+ }
+
+ LangOptions::FPExceptionModeKind getExceptionMode() const {
+ return static_cast<LangOptions::FPExceptionModeKind>(exceptions);
+ }
+
+ void setExceptionMode(LangOptions::FPExceptionModeKind EM) {
+ exceptions = EM;
+ }
+
+ /// FMF Flag queries
+ bool allowAssociativeMathEnabled() const { return allow_reassoc_enabled; }
+ bool noHonorNaNsEnabled() const { return no_nans_enabled; }
+ bool noHonorInfsEnabled() const { return no_infs_enabled; }
+ bool noSignedZerosEnabled() const { return no_signed_zeros_enabled; }
+ bool allowReciprocalMathEnabled() const { return allow_reciprocal_enabled; }
+ bool allowApproximateFunctionsEnabled() const { return approx_func_enabled; }
+
+ /// Flag setters
+ void setAllowAssociativeMathEnabled(bool B = true) { allow_reassoc_enabled = B; }
+ void setNoHonorNaNsEnabled(bool B = true) { no_nans_enabled = B; }
+ void setNoHonorInfsEnabled(bool B = true) { no_infs_enabled = B; }
+ void setNoSignedZerosEnabled(bool B = true) { no_signed_zeros_enabled = B; }
+ void setAllowReciprocalMathEnabled(bool B = true) { allow_reciprocal_enabled = B; }
+ void setAllowApproximateFunctionsEnabled(bool B = true) { approx_func_enabled = B; }
+ /// FMF Flag queries
+ bool allowAssociativeMathDisabled() const { return allow_reassoc_disabled; }
+ bool noHonorNaNsDisabled() const { return no_nans_disabled; }
+ bool noHonorInfsDisabled() const { return no_infs_disabled; }
+ bool noSignedZerosDisabled() const { return no_signed_zeros_disabled; }
+ bool allowReciprocalMathDisabled() const { return allow_reciprocal_disabled; }
+ bool allowApproximateFunctionsDisabled() const { return approx_func_disabled; }
+
+ /// Flag setters
+ void setAllowAssociativeMathDisabled(bool B = true) { allow_reassoc_disabled = B; }
+ void setNoHonorNaNsDisabled(bool B = true) { no_nans_disabled = B; }
+ void setNoHonorInfsDisabled(bool B = true) { no_infs_disabled = B; }
+ void setNoSignedZerosDisabled(bool B = true) { no_signed_zeros_disabled = B; }
+ void setAllowReciprocalMathDisabled(bool B = true) { allow_reciprocal_disabled = B; }
+ void setAllowApproximateFunctionsDisabled(bool B = true) { approx_func_disabled = B; }
+
+
+ /// Used to serialize.
+ unsigned getAsOpaqueInt() const {
+ assert( !(fenv_access_enabled & fenv_access_disabled));
+ assert( !(allow_reassoc_enabled & allow_reassoc_disabled));
+ assert( !(no_nans_enabled & no_nans_disabled));
+ assert( !(no_infs_enabled & no_infs_disabled));
+ assert( !(no_signed_zeros_enabled & no_signed_zeros_disabled));
+ assert( !(allow_reciprocal_enabled & allow_reciprocal_disabled));
+ assert( !(approx_func_enabled & approx_func_disabled));
+ return fp_contract | (rounding << 2) | (exceptions << 5) |
+ fenv_access_enabled << 7 | fenv_access_disabled << 8 |
+ allow_reassoc_enabled << 9 | allow_reassoc_disabled << 10 |
+ no_nans_enabled << 11 | no_nans_disabled << 12 |
+ no_infs_enabled << 13 | no_infs_disabled << 14 |
+ no_signed_zeros_enabled << 15 | no_signed_zeros_disabled << 16 |
+ allow_reciprocal_enabled << 17 | allow_reciprocal_disabled << 18 |
+ approx_func_enabled << 19 | approx_func_disabled << 20;
+ }
+ void getFromOpaqueInt(unsigned I) {
+ if (I == 0xffffffff) {
+ // This is the "unset" value from FP Pragma Stack
+ fp_contract = LangOptions::FPM_Unset;
+ rounding = static_cast<unsigned>(llvm::RoundingMode::Unset);
+ exceptions = LangOptions::FPE_Unset;
+ fenv_access_enabled = 0;
+ fenv_access_disabled = 0;
+ allow_reassoc_enabled = 0;
+ no_nans_enabled = 0;
+ no_infs_enabled = 0;
+ no_signed_zeros_enabled = 0;
+ allow_reciprocal_enabled = 0;
+ approx_func_enabled = 0;
+ allow_reassoc_disabled = 0;
+ no_nans_disabled = 0;
+ no_infs_disabled = 0;
+ no_signed_zeros_disabled = 0;
+ allow_reciprocal_disabled = 0;
+ approx_func_disabled = 0;
+ } else {
+ fp_contract = (static_cast<LangOptions::FPModeKind>(I & 3));
+ rounding = static_cast<unsigned>(static_cast<RoundingMode>((I >> 2) & 7));
+ exceptions = (static_cast<LangOptions::FPExceptionModeKind>((I >> 5) & 3));
+ fenv_access_enabled = I >> 7 & 1;
+ fenv_access_disabled = I >> 8 & 1;
+ allow_reassoc_enabled = I >> 9 & 1;
+ allow_reassoc_disabled = I >> 10 & 1;
+ no_nans_enabled = I >> 11 & 1;
+ no_nans_disabled = I >> 12 & 1;
+ no_infs_enabled = I >> 13 & 1;
+ no_infs_disabled = I >> 14 & 1;
+ no_signed_zeros_enabled = I >> 15 & 1;
+ no_signed_zeros_disabled = I >> 16 & 1;
+ allow_reciprocal_enabled = I >> 17 & 1;
+ allow_reciprocal_disabled = I >> 18 & 1;
+ approx_func_enabled = I >> 19 & 1;
+ approx_func_disabled = I >> 20 & 1;
+ assert( !(fenv_access_enabled & fenv_access_disabled));
+ assert( !(allow_reassoc_enabled & allow_reassoc_disabled));
+ assert( !(no_nans_enabled & no_nans_disabled));
+ assert( !(no_infs_enabled & no_infs_disabled));
+ assert( !(no_signed_zeros_enabled & no_signed_zeros_disabled));
+ assert( !(allow_reciprocal_enabled & allow_reciprocal_disabled));
+ assert( !(approx_func_enabled & approx_func_disabled));
+ }
+ }
+
+ FPOptions mergeOverrides(const LangOptions &LO) {
+ FPOptions Result(LO);
+ if (fp_contract != LangOptions::FPM_Unset)
+ Result.fp_contract = fp_contract;
+ if (static_cast<RoundingMode>(rounding) != llvm::RoundingMode::Unset)
+ Result.rounding = rounding;
+ if (exceptions != LangOptions::FPE_Unset)
+ Result.exceptions = exceptions;
+
+ assert( !(fenv_access_enabled & fenv_access_disabled));
+ if (fenv_access_enabled) Result.fenv_access = 1;
+ if (fenv_access_disabled) Result.fenv_access = 0;
+
+ assert( !(allow_reassoc_enabled & allow_reassoc_disabled));
+ if (allow_reassoc_enabled) Result.allow_reassoc = 1;
+ if (allow_reassoc_disabled) Result.allow_reassoc = 0;
+
+ assert( !(no_nans_enabled & no_nans_disabled));
+ if (no_nans_enabled) Result.no_nans = 1;
+ if (no_nans_disabled) Result.no_nans = 0;
+
+ assert( !(no_infs_enabled & no_infs_disabled));
+ if (no_infs_enabled) Result.no_infs = 1;
+ if (no_infs_disabled) Result.no_infs = 0;
+
+ assert( !(no_signed_zeros_enabled & no_signed_zeros_disabled));
+ if (no_signed_zeros_enabled) Result.no_signed_zeros = 1;
+ if (no_signed_zeros_disabled) Result.no_signed_zeros = 0;
+
+ assert( !(allow_reciprocal_enabled & allow_reciprocal_disabled));
+ if (allow_reciprocal_enabled) Result.allow_reciprocal = 1;
+ if (allow_reciprocal_disabled) Result.allow_reciprocal = 0;
+
+ assert( !(approx_func_enabled & approx_func_disabled));
+ if (approx_func_enabled) Result.approx_func = 1;
+ if (approx_func_disabled) Result.approx_func = 0;
+ return Result;
+ }
+
+ /// Does this FPOptions require trailing storage when stored in various
+ /// AST nodes, or can it be recreated using `defaultWithoutTrailingStorage`?
+ bool requiresTrailingStorage() {
+ FPOptionsOverride noValue;
+ return getAsOpaqueInt() != noValue.getAsOpaqueInt();
+ }
+
+private:
+ /// Adjust BinaryOperatorBitfields::FPFeatures and
+ /// CXXOperatorCallExprBitfields::FPFeatures to match the total bit-field size
+ /// of these fields.
+ unsigned fp_contract : 2;
+ unsigned rounding : 3;
+ unsigned exceptions : 2;
+ unsigned fenv_access_enabled : 1;
+ unsigned fenv_access_disabled : 1;
+ unsigned allow_reassoc_enabled : 1;
+ unsigned no_nans_enabled : 1;
+ unsigned no_infs_enabled : 1;
+ unsigned no_signed_zeros_enabled : 1;
+ unsigned allow_reciprocal_enabled : 1;
+ unsigned approx_func_enabled : 1;
+ unsigned allow_reassoc_disabled : 1;
+ unsigned no_nans_disabled : 1;
+ unsigned no_infs_disabled : 1;
+ unsigned no_signed_zeros_disabled : 1;
+ unsigned allow_reciprocal_disabled : 1;
+ unsigned approx_func_disabled : 1;
};
inline bool operator==(FPOptions LHS, FPOptions RHS) {
Index: clang/include/clang/AST/Stmt.h
===================================================================
--- clang/include/clang/AST/Stmt.h
+++ clang/include/clang/AST/Stmt.h
@@ -616,7 +616,7 @@
unsigned OperatorKind : 6;
// Only meaningful for floating point types.
- unsigned FPFeatures : 14;
+ unsigned FPFeatures : 21;
};
class CXXRewrittenBinaryOperatorBitfields {
Index: clang/include/clang/AST/ExprCXX.h
===================================================================
--- clang/include/clang/AST/ExprCXX.h
+++ clang/include/clang/AST/ExprCXX.h
@@ -91,7 +91,7 @@
CXXOperatorCallExpr(OverloadedOperatorKind OpKind, Expr *Fn,
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
- SourceLocation OperatorLoc, FPOptions FPFeatures,
+ SourceLocation OperatorLoc, FPOptionsOverride FPFeatures,
ADLCallKind UsesADL);
CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty);
@@ -100,7 +100,7 @@
static CXXOperatorCallExpr *
Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn,
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
- SourceLocation OperatorLoc, FPOptions FPFeatures,
+ SourceLocation OperatorLoc, FPOptionsOverride FPFeatures,
ADLCallKind UsesADL = NotADL);
static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx,
@@ -165,17 +165,18 @@
// Set the FP contractability status of this operator. Only meaningful for
// operations on floating point types.
- void setFPFeatures(FPOptions F) {
+ void setFPFeatures(FPOptionsOverride F) {
CXXOperatorCallExprBits.FPFeatures = F.getAsOpaqueInt();
}
- FPOptions getFPFeatures() const {
- return FPOptions(CXXOperatorCallExprBits.FPFeatures);
+ FPOptionsOverride getFPFeatures() const {
+ return FPOptionsOverride(CXXOperatorCallExprBits.FPFeatures);
}
+ FPOptions getFPFeaturesInEffect() const;
// Get the FP contractability status of this operator. Only meaningful for
// operations on floating point types.
bool isFPContractableWithinStatement() const {
- return getFPFeatures().allowFPContractWithinStatement();
+ return getFPFeaturesInEffect().allowFPContractWithinStatement();
}
};
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -2119,21 +2119,21 @@
///
class UnaryOperator final
: public Expr,
- private llvm::TrailingObjects<UnaryOperator, FPOptions> {
+ private llvm::TrailingObjects<UnaryOperator, FPOptionsOverride> {
Stmt *Val;
- size_t numTrailingObjects(OverloadToken<FPOptions>) const {
+ size_t numTrailingObjects(OverloadToken<FPOptionsOverride>) const {
return UnaryOperatorBits.HasFPFeatures ? 1 : 0;
}
- FPOptions &getTrailingFPFeatures() {
+ FPOptionsOverride &getTrailingFPFeatures() {
assert(UnaryOperatorBits.HasFPFeatures);
- return *getTrailingObjects<FPOptions>();
+ return *getTrailingObjects<FPOptionsOverride>();
}
- const FPOptions &getTrailingFPFeatures() const {
+ const FPOptionsOverride &getTrailingFPFeatures() const {
assert(UnaryOperatorBits.HasFPFeatures);
- return *getTrailingObjects<FPOptions>();
+ return *getTrailingObjects<FPOptionsOverride>();
}
public:
@@ -2142,7 +2142,7 @@
protected:
UnaryOperator(const ASTContext &Ctx, Expr *input, Opcode opc, QualType type,
ExprValueKind VK, ExprObjectKind OK, SourceLocation l,
- bool CanOverflow, FPOptions FPFeatures);
+ bool CanOverflow, FPOptionsOverride FPFeatures);
/// Build an empty unary operator.
explicit UnaryOperator(bool HasFPFeatures, EmptyShell Empty)
@@ -2157,7 +2157,7 @@
static UnaryOperator *Create(const ASTContext &C, Expr *input, Opcode opc,
QualType type, ExprValueKind VK,
ExprObjectKind OK, SourceLocation l,
- bool CanOverflow, FPOptions FPFeatures);
+ bool CanOverflow, FPOptionsOverride FPFeatures);
Opcode getOpcode() const {
return static_cast<Opcode>(UnaryOperatorBits.Opc);
@@ -2183,13 +2183,13 @@
// Get the FP contractability status of this operator. Only meaningful for
// operations on floating point types.
bool isFPContractableWithinStatement(const LangOptions &LO) const {
- return getFPFeatures(LO).allowFPContractWithinStatement();
+ return getFPFeaturesInEffect(LO).allowFPContractWithinStatement();
}
// Get the FENV_ACCESS status of this operator. Only meaningful for
// operations on floating point types.
bool isFEnvAccessOn(const LangOptions &LO) const {
- return getFPFeatures(LO).allowFEnvAccess();
+ return getFPFeaturesInEffect(LO).allowFEnvAccess();
}
/// isPostfix - Return true if this is a postfix operation, like x++.
@@ -2264,19 +2264,24 @@
protected:
/// Get FPFeatures from trailing storage
- FPOptions getStoredFPFeatures() const { return getTrailingFPFeatures(); }
+ FPOptionsOverride getStoredFPFeatures() const { return getTrailingFPFeatures(); }
/// Set FPFeatures in trailing storage, used only by Serialization
- void setStoredFPFeatures(FPOptions F) { getTrailingFPFeatures() = F; }
+ void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; }
public:
// Get the FP features status of this operator. Only meaningful for
// operations on floating point types.
- FPOptions getFPFeatures(const LangOptions &LO) const {
+ FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
if (UnaryOperatorBits.HasFPFeatures)
- return getStoredFPFeatures();
+ return getStoredFPFeatures().mergeOverrides(LO);
return FPOptions::defaultWithoutTrailingStorage(LO);
}
+ FPOptionsOverride getFPFeatures(const LangOptions &LO) const {
+ if (UnaryOperatorBits.HasFPFeatures)
+ return getStoredFPFeatures();
+ return FPOptionsOverride();
+ }
friend TrailingObjects;
friend class ASTReader;
@@ -3634,14 +3639,14 @@
size_t offsetOfTrailingStorage() const;
/// Return a pointer to the trailing FPOptions
- FPOptions *getTrailingFPFeatures() {
+ FPOptionsOverride *getTrailingFPFeatures() {
assert(BinaryOperatorBits.HasFPFeatures);
- return reinterpret_cast<FPOptions *>(reinterpret_cast<char *>(this) +
+ return reinterpret_cast<FPOptionsOverride *>(reinterpret_cast<char *>(this) +
offsetOfTrailingStorage());
}
- const FPOptions *getTrailingFPFeatures() const {
+ const FPOptionsOverride *getTrailingFPFeatures() const {
assert(BinaryOperatorBits.HasFPFeatures);
- return reinterpret_cast<const FPOptions *>(
+ return reinterpret_cast<const FPOptionsOverride *>(
reinterpret_cast<const char *>(this) + offsetOfTrailingStorage());
}
@@ -3649,7 +3654,7 @@
/// allocated for the trailing objects when needed.
BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, Opcode opc,
QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
- SourceLocation opLoc, FPOptions FPFeatures);
+ SourceLocation opLoc, FPOptionsOverride FPFeatures);
/// Construct an empty binary operator.
explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty) {
@@ -3662,7 +3667,7 @@
static BinaryOperator *Create(const ASTContext &C, Expr *lhs, Expr *rhs,
Opcode opc, QualType ResTy, ExprValueKind VK,
ExprObjectKind OK, SourceLocation opLoc,
- FPOptions FPFeatures);
+ FPOptionsOverride FPFeatures);
SourceLocation getExprLoc() const { return getOperatorLoc(); }
SourceLocation getOperatorLoc() const { return BinaryOperatorBits.OpLoc; }
void setOperatorLoc(SourceLocation L) { BinaryOperatorBits.OpLoc = L; }
@@ -3809,40 +3814,47 @@
bool hasStoredFPFeatures() const { return BinaryOperatorBits.HasFPFeatures; }
/// Get FPFeatures from trailing storage
- FPOptions getStoredFPFeatures() const {
+ FPOptionsOverride getStoredFPFeatures() const {
assert(hasStoredFPFeatures());
return *getTrailingFPFeatures();
}
/// Set FPFeatures in trailing storage, used only by Serialization
- void setStoredFPFeatures(FPOptions F) {
+ void setStoredFPFeatures(FPOptionsOverride F) {
assert(BinaryOperatorBits.HasFPFeatures);
*getTrailingFPFeatures() = F;
}
// Get the FP features status of this operator. Only meaningful for
// operations on floating point types.
- FPOptions getFPFeatures(const LangOptions &LO) const {
+ FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
if (BinaryOperatorBits.HasFPFeatures)
- return getStoredFPFeatures();
+ return getStoredFPFeatures().mergeOverrides(LO);
return FPOptions::defaultWithoutTrailingStorage(LO);
}
+ // This is used in ASTImporter
+ FPOptionsOverride getFPFeatures(const LangOptions &LO) const {
+ if (BinaryOperatorBits.HasFPFeatures)
+ return getStoredFPFeatures();
+ return FPOptionsOverride();
+ }
+
// Get the FP contractability status of this operator. Only meaningful for
// operations on floating point types.
bool isFPContractableWithinStatement(const LangOptions &LO) const {
- return getFPFeatures(LO).allowFPContractWithinStatement();
+ return getFPFeaturesInEffect(LO).allowFPContractWithinStatement();
}
// Get the FENV_ACCESS status of this operator. Only meaningful for
// operations on floating point types.
bool isFEnvAccessOn(const LangOptions &LO) const {
- return getFPFeatures(LO).allowFEnvAccess();
+ return getFPFeaturesInEffect(LO).allowFEnvAccess();
}
protected:
BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, Opcode opc,
QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
- SourceLocation opLoc, FPOptions FPFeatures, bool dead2);
+ SourceLocation opLoc, FPOptionsOverride FPFeatures, bool dead2);
/// Construct an empty BinaryOperator, SC is CompoundAssignOperator.
BinaryOperator(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {
@@ -3852,7 +3864,7 @@
/// Return the size in bytes needed for the trailing objects.
/// Used to allocate the right amount of storage.
static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
- return HasFPFeatures * sizeof(FPOptions);
+ return HasFPFeatures * sizeof(FPOptionsOverride);
}
};
@@ -3874,7 +3886,7 @@
protected:
CompoundAssignOperator(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc,
QualType ResType, ExprValueKind VK, ExprObjectKind OK,
- SourceLocation OpLoc, FPOptions FPFeatures,
+ SourceLocation OpLoc, FPOptionsOverride FPFeatures,
QualType CompLHSType, QualType CompResultType)
: BinaryOperator(C, lhs, rhs, opc, ResType, VK, OK, OpLoc, FPFeatures,
true),
@@ -3890,7 +3902,7 @@
static CompoundAssignOperator *
Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc,
- FPOptions FPFeatures, QualType CompLHSType = QualType(),
+ FPOptionsOverride FPFeatures, QualType CompLHSType = QualType(),
QualType CompResultType = QualType());
// The two computation types are the type the LHS is converted
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits