[clang] 2ba4e3a - Move BinaryOperators.FPOptions to trailing storage
Melanie Blower via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 15 12:57:52 PDT 2020
Author: Melanie Blower
Date: 2020-04-15T12:57:31-07:00
New Revision: 2ba4e3a4598b165245c581c506a813cd4a7dce33
URL: https://github.com/llvm/llvm-project/commit/2ba4e3a4598b165245c581c506a813cd4a7dce33
DIFF: https://github.com/llvm/llvm-project/commit/2ba4e3a4598b165245c581c506a813cd4a7dce33.diff
LOG: Move BinaryOperators.FPOptions to trailing storage
Reviewers: rjmccall
Differential Revision: https://reviews.llvm.org/D76384
Added:
Modified:
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/lib/AST/ASTImporter.cpp
clang/lib/AST/Expr.cpp
clang/lib/AST/ExprCXX.cpp
clang/lib/Analysis/BodyFarm.cpp
clang/lib/Basic/LangOptions.cpp
clang/lib/CodeGen/CGExprScalar.cpp
clang/lib/CodeGen/CGObjC.cpp
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
clang/lib/Frontend/Rewrite/RewriteObjC.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaPseudoObject.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index c1ef6ed09ce8..1fdfe926eb71 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3475,17 +3475,36 @@ class BinaryOperator : public Expr {
public:
typedef BinaryOperatorKind Opcode;
- BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
- ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc,
- FPOptions FPFeatures)
+protected:
+ size_t offsetOfTrailingStorage() const;
+
+ /// Return a pointer to the trailing FPOptions
+ FPOptions *getTrailingFPFeatures() {
+ assert(BinaryOperatorBits.HasFPFeatures);
+ return reinterpret_cast<FPOptions *>(reinterpret_cast<char *>(this) +
+ offsetOfTrailingStorage());
+ }
+ const FPOptions *getTrailingFPFeatures() const {
+ assert(BinaryOperatorBits.HasFPFeatures);
+ return reinterpret_cast<const FPOptions *>(
+ reinterpret_cast<const char *>(this) + offsetOfTrailingStorage());
+ }
+
+ /// Build a binary operator, assuming that appropriate storage has been
+ /// 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)
: Expr(BinaryOperatorClass, ResTy, VK, OK) {
BinaryOperatorBits.Opc = opc;
- BinaryOperatorBits.FPFeatures = FPFeatures.getInt();
+ assert(!isCompoundAssignmentOp() &&
+ "Use CompoundAssignOperator for compound assignments");
BinaryOperatorBits.OpLoc = opLoc;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
- assert(!isCompoundAssignmentOp() &&
- "Use CompoundAssignOperator for compound assignments");
+ BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage(Ctx);
+ if (BinaryOperatorBits.HasFPFeatures)
+ *getTrailingFPFeatures() = FPFeatures;
setDependence(computeDependence(this));
}
@@ -3494,6 +3513,13 @@ class BinaryOperator : public Expr {
BinaryOperatorBits.Opc = BO_Comma;
}
+public:
+ static BinaryOperator *CreateEmpty(const ASTContext &C, bool hasFPFeatures);
+
+ static BinaryOperator *Create(const ASTContext &C, Expr *lhs, Expr *rhs,
+ Opcode opc, QualType ResTy, ExprValueKind VK,
+ ExprObjectKind OK, SourceLocation opLoc,
+ FPOptions FPFeatures);
SourceLocation getExprLoc() const { return getOperatorLoc(); }
SourceLocation getOperatorLoc() const { return BinaryOperatorBits.OpLoc; }
void setOperatorLoc(SourceLocation L) { BinaryOperatorBits.OpLoc = L; }
@@ -3634,42 +3660,69 @@ class BinaryOperator : public Expr {
return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR);
}
- // Set the FP contractability status of this operator. Only meaningful for
- // operations on floating point types.
- void setFPFeatures(FPOptions F) {
- BinaryOperatorBits.FPFeatures = F.getInt();
+ /// Set and fetch the bit that shows whether FPFeatures needs to be
+ /// allocated in Trailing Storage
+ void setHasStoredFPFeatures(bool B) { BinaryOperatorBits.HasFPFeatures = B; }
+ bool hasStoredFPFeatures() const { return BinaryOperatorBits.HasFPFeatures; }
+
+ /// Get FPFeatures from trailing storage
+ FPOptions getStoredFPFeatures() const {
+ assert(hasStoredFPFeatures());
+ return *getTrailingFPFeatures();
+ }
+ /// Set FPFeatures in trailing storage, used only by Serialization
+ void setStoredFPFeatures(FPOptions F) {
+ assert(BinaryOperatorBits.HasFPFeatures);
+ *getTrailingFPFeatures() = F;
}
- FPOptions getFPFeatures() const {
- return FPOptions(BinaryOperatorBits.FPFeatures);
+ // Get the FP features status of this operator. Only meaningful for
+ // operations on floating point types.
+ FPOptions getFPFeatures(const ASTContext &C) const {
+ if (BinaryOperatorBits.HasFPFeatures)
+ return getStoredFPFeatures();
+ return FPOptions::defaultWithoutTrailingStorage(C);
}
// Get the FP contractability status of this operator. Only meaningful for
// operations on floating point types.
- bool isFPContractableWithinStatement() const {
- return getFPFeatures().allowFPContractWithinStatement();
+ bool isFPContractableWithinStatement(const ASTContext &C) const {
+ return getFPFeatures(C).allowFPContractWithinStatement();
}
// Get the FENV_ACCESS status of this operator. Only meaningful for
// operations on floating point types.
- bool isFEnvAccessOn() const { return getFPFeatures().allowFEnvAccess(); }
+ bool isFEnvAccessOn(const ASTContext &C) const {
+ return getFPFeatures(C).allowFEnvAccess();
+ }
protected:
- BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
- ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc,
- FPOptions FPFeatures, bool dead2)
+ BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, Opcode opc,
+ QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation opLoc, FPOptions FPFeatures, bool dead2)
: Expr(CompoundAssignOperatorClass, ResTy, VK, OK) {
BinaryOperatorBits.Opc = opc;
- BinaryOperatorBits.FPFeatures = FPFeatures.getInt();
+ assert(isCompoundAssignmentOp() &&
+ "Use CompoundAssignOperator for compound assignments");
BinaryOperatorBits.OpLoc = opLoc;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
+ BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage(Ctx);
+ if (BinaryOperatorBits.HasFPFeatures)
+ *getTrailingFPFeatures() = FPFeatures;
setDependence(computeDependence(this));
}
+ /// Construct an empty BinaryOperator, SC is CompoundAssignOperator.
BinaryOperator(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {
BinaryOperatorBits.Opc = BO_MulAssign;
}
+
+ /// 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);
+ }
};
/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
@@ -3681,22 +3734,33 @@ class BinaryOperator : public Expr {
class CompoundAssignOperator : public BinaryOperator {
QualType ComputationLHSType;
QualType ComputationResultType;
-public:
- CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType,
- ExprValueKind VK, ExprObjectKind OK,
- QualType CompLHSType, QualType CompResultType,
- SourceLocation OpLoc, FPOptions FPFeatures)
- : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, FPFeatures,
- true),
- ComputationLHSType(CompLHSType),
- ComputationResultType(CompResultType) {
+
+ /// Construct an empty CompoundAssignOperator.
+ explicit CompoundAssignOperator(const ASTContext &C, EmptyShell Empty,
+ bool hasFPFeatures)
+ : BinaryOperator(CompoundAssignOperatorClass, Empty) {}
+
+protected:
+ CompoundAssignOperator(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc,
+ QualType ResType, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation OpLoc, FPOptions FPFeatures,
+ QualType CompLHSType, QualType CompResultType)
+ : BinaryOperator(C, lhs, rhs, opc, ResType, VK, OK, OpLoc, FPFeatures,
+ true),
+ ComputationLHSType(CompLHSType), ComputationResultType(CompResultType) {
assert(isCompoundAssignmentOp() &&
"Only should be used for compound assignments");
}
- /// Build an empty compound assignment operator expression.
- explicit CompoundAssignOperator(EmptyShell Empty)
- : BinaryOperator(CompoundAssignOperatorClass, Empty) { }
+public:
+ static CompoundAssignOperator *CreateEmpty(const ASTContext &C,
+ bool hasFPFeatures);
+
+ 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(),
+ QualType CompResultType = QualType());
// The two computation types are the type the LHS is converted
// to for the computation and the type of the result; the two are
@@ -3712,6 +3776,12 @@ class CompoundAssignOperator : public BinaryOperator {
}
};
+inline size_t BinaryOperator::offsetOfTrailingStorage() const {
+ assert(BinaryOperatorBits.HasFPFeatures);
+ return isa<CompoundAssignOperator>(this) ? sizeof(CompoundAssignOperator)
+ : sizeof(BinaryOperator);
+}
+
/// AbstractConditionalOperator - An abstract base class for
/// ConditionalOperator and BinaryConditionalOperator.
class AbstractConditionalOperator : public Expr {
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index bb2be62ec824..9ce9dcee740d 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -166,7 +166,7 @@ class CXXOperatorCallExpr final : public CallExpr {
// Set the FP contractability status of this operator. Only meaningful for
// operations on floating point types.
void setFPFeatures(FPOptions F) {
- CXXOperatorCallExprBits.FPFeatures = F.getInt();
+ CXXOperatorCallExprBits.FPFeatures = F.getAsOpaqueInt();
}
FPOptions getFPFeatures() const {
return FPOptions(CXXOperatorCallExprBits.FPFeatures);
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 8c7f0ecad3ef..58c03291c1ed 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -525,8 +525,9 @@ class alignas(void *) Stmt {
unsigned Opc : 6;
/// This is only meaningful for operations on floating point
- /// types and 0 otherwise.
- unsigned FPFeatures : 8;
+ /// types when additional values need to be in trailing storage.
+ /// It is 0 otherwise.
+ unsigned HasFPFeatures : 1;
SourceLocation OpLoc;
};
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 95b435ba9f34..c33f8bf8c8ef 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -27,6 +27,8 @@
namespace clang {
+class ASTContext;
+
/// Bitfields of LangOptions, split out from LangOptions in order to ensure that
/// this large collection of bitfields is a trivial class type.
class LangOptionsBase {
@@ -399,6 +401,14 @@ class FPOptions {
{}
// FIXME: Use getDefaultFEnvAccessMode() when available.
+ /// Return the default value of FPOptions that's used when trailing
+ /// storage isn't required.
+ static FPOptions defaultWithoutTrailingStorage(const ASTContext &C);
+
+ /// Does this FPOptions require trailing storage when stored in various
+ /// AST nodes, or can it be recreated using `defaultWithoutTrailingStorage`?
+ bool requiresTrailingStorage(const ASTContext &C);
+
bool allowFPContractWithinStatement() const {
return fp_contract == LangOptions::FPC_On;
}
@@ -450,9 +460,9 @@ class FPOptions {
}
/// Used to serialize this.
- unsigned getInt() const {
- return fp_contract | (fenv_access << 2) | (rounding << 3)
- | (exceptions << 6);
+ unsigned getAsOpaqueInt() const {
+ return fp_contract | (fenv_access << 2) | (rounding << 3) |
+ (exceptions << 6);
}
private:
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 3a499c7f0dff..e303701cf5d3 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -6703,9 +6703,10 @@ ExpectedStmt ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) {
if (Err)
return std::move(Err);
- return new (Importer.getToContext()) BinaryOperator(
- ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(),
- E->getObjectKind(), ToOperatorLoc, E->getFPFeatures());
+ return BinaryOperator::Create(Importer.getToContext(), ToLHS, ToRHS,
+ E->getOpcode(), ToType, E->getValueKind(),
+ E->getObjectKind(), ToOperatorLoc,
+ E->getFPFeatures(Importer.getFromContext()));
}
ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) {
@@ -6813,10 +6814,12 @@ ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
if (Err)
return std::move(Err);
- return new (Importer.getToContext()) CompoundAssignOperator(
- ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(),
- E->getObjectKind(), ToComputationLHSType, ToComputationResultType,
- ToOperatorLoc, E->getFPFeatures());
+ return CompoundAssignOperator::Create(
+ Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType,
+ E->getValueKind(), E->getObjectKind(), ToOperatorLoc,
+ E->getFPFeatures(Importer.getFromContext()),
+ importChecked(Err, ToComputationLHSType),
+ importChecked(Err, ToComputationResultType));
}
Expected<CXXCastPath>
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 46ecba29ef19..a5c634e298de 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -4347,6 +4347,48 @@ ParenListExpr *ParenListExpr::CreateEmpty(const ASTContext &Ctx,
return new (Mem) ParenListExpr(EmptyShell(), NumExprs);
}
+BinaryOperator *BinaryOperator::CreateEmpty(const ASTContext &C,
+ bool HasFPFeatures) {
+ unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
+ void *Mem =
+ C.Allocate(sizeof(BinaryOperator) + Extra, alignof(BinaryOperator));
+ return new (Mem) BinaryOperator(EmptyShell());
+}
+
+BinaryOperator *BinaryOperator::Create(const ASTContext &C, Expr *lhs,
+ Expr *rhs, Opcode opc, QualType ResTy,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation opLoc,
+ FPOptions FPFeatures) {
+ bool HasFPFeatures = FPFeatures.requiresTrailingStorage(C);
+ unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
+ void *Mem =
+ C.Allocate(sizeof(BinaryOperator) + Extra, alignof(BinaryOperator));
+ return new (Mem)
+ BinaryOperator(C, lhs, rhs, opc, ResTy, VK, OK, opLoc, FPFeatures);
+}
+
+CompoundAssignOperator *
+CompoundAssignOperator::CreateEmpty(const ASTContext &C, bool HasFPFeatures) {
+ unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
+ void *Mem = C.Allocate(sizeof(CompoundAssignOperator) + Extra,
+ alignof(CompoundAssignOperator));
+ return new (Mem) CompoundAssignOperator(C, EmptyShell(), HasFPFeatures);
+}
+
+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);
+ unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
+ void *Mem = C.Allocate(sizeof(CompoundAssignOperator) + Extra,
+ alignof(CompoundAssignOperator));
+ return new (Mem)
+ CompoundAssignOperator(C, lhs, rhs, opc, ResTy, VK, OK, opLoc, FPFeatures,
+ CompLHSType, CompResultType);
+}
+
const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) {
if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e))
e = ewc->getSubExpr();
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index cc53b663cf4e..b1e0eb5a610b 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -530,11 +530,11 @@ CXXOperatorCallExpr::CXXOperatorCallExpr(OverloadedOperatorKind OpKind,
: CallExpr(CXXOperatorCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
OperatorLoc, /*MinNumArgs=*/0, UsesADL) {
CXXOperatorCallExprBits.OperatorKind = OpKind;
- CXXOperatorCallExprBits.FPFeatures = FPFeatures.getInt();
+ CXXOperatorCallExprBits.FPFeatures = FPFeatures.getAsOpaqueInt();
assert(
(CXXOperatorCallExprBits.OperatorKind == static_cast<unsigned>(OpKind)) &&
"OperatorKind overflow!");
- assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getInt()) &&
+ assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getAsOpaqueInt()) &&
"FPFeatures overflow!");
Range = getSourceRangeImpl();
}
@@ -1639,4 +1639,4 @@ CUDAKernelCallExpr *CUDAKernelCallExpr::CreateEmpty(const ASTContext &Ctx,
void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects,
alignof(CUDAKernelCallExpr));
return new (Mem) CUDAKernelCallExpr(NumArgs, Empty);
-}
\ No newline at end of file
+}
diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp
index 1a7891550542..c78096a20be6 100644
--- a/clang/lib/Analysis/BodyFarm.cpp
+++ b/clang/lib/Analysis/BodyFarm.cpp
@@ -114,21 +114,20 @@ class ASTMaker {
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(), FPOptions());
+ return BinaryOperator::Create(
+ C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), BO_Assign, Ty,
+ VK_RValue, OK_Ordinary, SourceLocation(), FPOptions(C.getLangOpts()));
}
BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
BinaryOperator::Opcode Op) {
assert(BinaryOperator::isLogicalOp(Op) ||
BinaryOperator::isComparisonOp(Op));
- return new (C) BinaryOperator(const_cast<Expr*>(LHS),
- const_cast<Expr*>(RHS),
- Op,
- C.getLogicalOperationType(),
- VK_RValue,
- OK_Ordinary, SourceLocation(), FPOptions());
+ return BinaryOperator::Create(C, const_cast<Expr *>(LHS),
+ const_cast<Expr *>(RHS), Op,
+ C.getLogicalOperationType(), VK_RValue,
+ OK_Ordinary, SourceLocation(),
+ FPOptions(C.getLangOpts()));
}
CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
@@ -296,7 +295,8 @@ static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
/*Args=*/CallArgs,
/*QualType=*/C.VoidTy,
/*ExprValueType=*/VK_RValue,
- /*SourceLocation=*/SourceLocation(), FPOptions());
+ /*SourceLocation=*/SourceLocation(),
+ /*FPFeatures=*/FPOptions(C.getLangOpts()));
}
/// Create a fake body for std::call_once.
diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp
index 516b1ff1b7e2..6e12bda65a42 100644
--- a/clang/lib/Basic/LangOptions.cpp
+++ b/clang/lib/Basic/LangOptions.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/LangOptions.h"
+#include "clang/AST/ASTContext.h"
using namespace clang;
@@ -47,3 +48,12 @@ VersionTuple LangOptions::getOpenCLVersionTuple() const {
const int Ver = OpenCLCPlusPlus ? OpenCLCPlusPlusVersion : OpenCLVersion;
return VersionTuple(Ver / 100, (Ver % 100) / 10);
}
+
+FPOptions FPOptions::defaultWithoutTrailingStorage(const ASTContext &C) {
+ FPOptions result(C.getLangOpts());
+ return result;
+}
+
+bool FPOptions::requiresTrailingStorage(const ASTContext &C) {
+ return getAsOpaqueInt() != defaultWithoutTrailingStorage(C).getAsOpaqueInt();
+}
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index c4f1faad4258..75be18e23e2f 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -2929,7 +2929,7 @@ BinOpInfo ScalarExprEmitter::EmitBinOps(const BinaryOperator *E) {
Result.RHS = Visit(E->getRHS());
Result.Ty = E->getType();
Result.Opcode = E->getOpcode();
- Result.FPFeatures = E->getFPFeatures();
+ Result.FPFeatures = E->getFPFeatures(CGF.getContext());
Result.E = E;
return Result;
}
@@ -2949,7 +2949,7 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
OpInfo.RHS = Visit(E->getRHS());
OpInfo.Ty = E->getComputationResultType();
OpInfo.Opcode = E->getOpcode();
- OpInfo.FPFeatures = E->getFPFeatures();
+ OpInfo.FPFeatures = E->getFPFeatures(CGF.getContext());
OpInfo.E = E;
// Load/convert the LHS.
LValue LHSLV = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store);
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index 90fca2836d99..2324f78f622e 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -1491,11 +1491,11 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
argLoad.getType()))
finalArg = &argCast;
-
- BinaryOperator assign(&ivarRef, finalArg, BO_Assign,
- ivarRef.getType(), VK_RValue, OK_Ordinary,
- SourceLocation(), FPOptions());
- EmitStmt(&assign);
+ BinaryOperator *assign = BinaryOperator::Create(
+ getContext(), &ivarRef, finalArg, BO_Assign, ivarRef.getType(), VK_RValue,
+ OK_Ordinary, SourceLocation(),
+ FPOptions(getContext().getLangOpts()));
+ EmitStmt(assign);
}
/// Generate an Objective-C property setter function.
@@ -3569,7 +3569,7 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment());
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
C, OO_Equal, CalleeExp->getCallee(), Args, DestTy->getPointeeType(),
- VK_LValue, SourceLocation(), FPOptions());
+ VK_LValue, SourceLocation(), FPOptions(C.getLangOpts()));
EmitStmt(TheCall);
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 449f12724254..8366bbe73b5a 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -2908,7 +2908,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
bool HasLastprivates = false;
auto &&CodeGen = [&S, CapturedStmt, CS,
&HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
- ASTContext &C = CGF.getContext();
+ const ASTContext &C = CGF.getContext();
QualType KmpInt32Ty =
C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
// Emit helper vars inits.
@@ -2930,8 +2930,9 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
// Generate condition for loop.
- BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue,
- OK_Ordinary, S.getBeginLoc(), FPOptions());
+ BinaryOperator *Cond = BinaryOperator::Create(
+ C, &IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue, OK_Ordinary,
+ S.getBeginLoc(), FPOptions(C.getLangOpts()));
// Increment for loop counter.
UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
S.getBeginLoc(), true);
@@ -3004,7 +3005,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
// IV = LB;
CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getBeginLoc()), IV);
// while (idx <= UB) { BODY; ++idx; }
- CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen,
+ CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, Cond, &Inc, BodyGen,
[](CodeGenFunction &) {});
// Tell the runtime we are done.
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index fff4a45c5330..e0e3420fa3b2 100644
--- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -7484,10 +7484,10 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
DeclRefExpr *DRE = new (Context)
DeclRefExpr(*Context, NewVD, false, Context->UnsignedLongTy,
VK_LValue, SourceLocation());
- BinaryOperator *addExpr =
- new (Context) BinaryOperator(castExpr, DRE, BO_Add,
- Context->getPointerType(Context->CharTy),
- VK_RValue, OK_Ordinary, SourceLocation(), FPOptions());
+ BinaryOperator *addExpr = BinaryOperator::Create(
+ *Context, castExpr, DRE, BO_Add,
+ Context->getPointerType(Context->CharTy), VK_RValue, OK_Ordinary,
+ SourceLocation(), FPOptions(Context->getLangOpts()));
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),
SourceLocation(),
diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
index 0302156b0226..32fc80fc8979 100644
--- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -2995,10 +2995,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
llvm::APInt(IntSize, 8),
Context->IntTy,
SourceLocation());
- BinaryOperator *lessThanExpr =
- new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy,
- VK_RValue, OK_Ordinary, SourceLocation(),
- FPOptions());
+ BinaryOperator *lessThanExpr = BinaryOperator::Create(
+ *Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_RValue,
+ OK_Ordinary, SourceLocation(), FPOptions(Context->getLangOpts()));
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
ConditionalOperator *CondExpr =
new (Context) ConditionalOperator(lessThanExpr,
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index aeaf9dcfc79c..381db055afae 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -13695,11 +13695,10 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// Create the comparison against the array bound.
llvm::APInt Upper
= ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType));
- Expr *Comparison
- = 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, FPOptions());
+ 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.FPFeatures);
// Create the pre-increment of the iteration variable. We can determine
// whether the increment will overflow based on the value of the array
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index ac477ca7ca55..141c4b1fea1d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13366,13 +13366,13 @@ static ExprResult convertHalfVecBinOp(Sema &S, ExprResult LHS, ExprResult RHS,
BinOpResTy = S.GetSignedVectorType(BinOpResTy);
if (IsCompAssign)
- return new (Context) CompoundAssignOperator(
- LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, BinOpResTy, BinOpResTy,
- OpLoc, FPFeatures);
+ return CompoundAssignOperator::Create(Context, LHS.get(), RHS.get(), Opc,
+ ResultTy, VK, OK, OpLoc, FPFeatures,
+ BinOpResTy, BinOpResTy);
LHS = convertVector(LHS.get(), Context.FloatTy, S);
- auto *BO = new (Context) BinaryOperator(LHS.get(), RHS.get(), Opc, BinOpResTy,
- VK, OK, OpLoc, FPFeatures);
+ auto *BO = BinaryOperator::Create(Context, LHS.get(), RHS.get(), Opc,
+ BinOpResTy, VK, OK, OpLoc, FPFeatures);
return convertVector(BO, ResultTy->castAs<VectorType>()->getElementType(), S);
}
@@ -13694,8 +13694,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
if (ConvertHalfVec)
return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, false,
OpLoc, FPFeatures);
- return new (Context) BinaryOperator(LHS.get(), RHS.get(), Opc, ResultTy, VK,
- OK, OpLoc, FPFeatures);
+ return BinaryOperator::Create(Context, LHS.get(), RHS.get(), Opc, ResultTy,
+ VK, OK, OpLoc, FPFeatures);
}
// Handle compound assignments.
@@ -13709,9 +13709,9 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, true,
OpLoc, FPFeatures);
- return new (Context) CompoundAssignOperator(
- LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, CompLHSTy, CompResultTy,
- OpLoc, FPFeatures);
+ return CompoundAssignOperator::Create(Context, LHS.get(), RHS.get(), Opc,
+ ResultTy, VK, OK, OpLoc, FPFeatures,
+ CompLHSTy, CompResultTy);
}
/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 9c18fe9bd800..1fe1515bed10 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -6991,9 +6991,10 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
return ExprError();
if (RHS.get() == BO->getRHS())
return E;
- return new (Context) BinaryOperator(
- BO->getLHS(), RHS.get(), BO_Comma, BO->getType(), BO->getValueKind(),
- BO->getObjectKind(), BO->getOperatorLoc(), BO->getFPFeatures());
+ return BinaryOperator::Create(Context, BO->getLHS(), RHS.get(), BO_Comma,
+ BO->getType(), BO->getValueKind(),
+ BO->getObjectKind(), BO->getOperatorLoc(),
+ BO->getFPFeatures(getASTContext()));
}
}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index b048c5a8d8cf..805bf667e861 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -12975,7 +12975,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
/*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end());
return CXXOperatorCallExpr::Create(Context, Op, Fn, ArgsArray,
Context.DependentTy, VK_RValue, OpLoc,
- FPOptions());
+ FPFeatures);
}
// Build an empty overload set.
@@ -13048,8 +13048,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
Args[0] = Input;
CallExpr *TheCall = CXXOperatorCallExpr::Create(
- Context, Op, FnExpr.get(), ArgsArray, ResultTy, VK, OpLoc,
- FPOptions(), Best->IsADLCandidate);
+ Context, Op, FnExpr.get(), ArgsArray, ResultTy, VK, OpLoc, FPFeatures,
+ Best->IsADLCandidate);
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl))
return ExprError();
@@ -13218,14 +13218,13 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// If there are no functions to store, just build a dependent
// BinaryOperator or CompoundAssignment.
if (Opc <= BO_Assign || Opc > BO_OrAssign)
- return new (Context) BinaryOperator(
- Args[0], Args[1], Opc, Context.DependentTy, VK_RValue, OK_Ordinary,
- OpLoc, FPFeatures);
-
- return new (Context) CompoundAssignOperator(
- Args[0], Args[1], Opc, Context.DependentTy, VK_LValue, OK_Ordinary,
- Context.DependentTy, Context.DependentTy, OpLoc,
- FPFeatures);
+ return BinaryOperator::Create(Context, Args[0], Args[1], Opc,
+ Context.DependentTy, VK_RValue,
+ OK_Ordinary, OpLoc, FPFeatures);
+ return CompoundAssignOperator::Create(
+ Context, Args[0], Args[1], Opc, Context.DependentTy, VK_LValue,
+ OK_Ordinary, OpLoc, FPFeatures, Context.DependentTy,
+ Context.DependentTy);
}
// FIXME: save results of ADL from here?
@@ -13672,10 +13671,10 @@ ExprResult Sema::BuildSynthesizedThreeWayComparison(
// Build a PseudoObjectExpr to model the rewriting of an <=> operator, and to
// bind the OpaqueValueExprs before they're (repeatedly) used.
- Expr *SyntacticForm = new (Context)
- BinaryOperator(OrigLHS, OrigRHS, BO_Cmp, Result.get()->getType(),
- Result.get()->getValueKind(),
- Result.get()->getObjectKind(), OpLoc, FPFeatures);
+ Expr *SyntacticForm = BinaryOperator::Create(
+ Context, OrigLHS, OrigRHS, BO_Cmp, Result.get()->getType(),
+ Result.get()->getValueKind(), Result.get()->getObjectKind(), OpLoc,
+ FPFeatures);
Expr *SemanticForm[] = {LHS, RHS, Result.get()};
return PseudoObjectExpr::Create(Context, SyntacticForm, SemanticForm, 2);
}
@@ -13706,7 +13705,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args,
Context.DependentTy, VK_RValue, RLoc,
- FPOptions());
+ FPFeatures);
}
// Handle placeholders on both operands.
@@ -13781,8 +13780,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
CXXOperatorCallExpr *TheCall =
CXXOperatorCallExpr::Create(Context, OO_Subscript, FnExpr.get(),
- Args, ResultTy, VK, RLoc, FPOptions());
-
+ Args, ResultTy, VK, RLoc, FPFeatures);
if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
return ExprError();
@@ -14405,7 +14403,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
CXXOperatorCallExpr *TheCall =
CXXOperatorCallExpr::Create(Context, OO_Call, NewFn.get(), MethodArgs,
- ResultTy, VK, RParenLoc, FPOptions());
+ ResultTy, VK, RParenLoc, FPFeatures);
if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
return true;
@@ -14522,7 +14520,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
- Context, OO_Arrow, FnExpr.get(), Base, ResultTy, VK, OpLoc, FPOptions());
+ Context, OO_Arrow, FnExpr.get(), Base, ResultTy, VK, OpLoc, FPFeatures);
if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method))
return ExprError();
diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp
index 6a541f9693ec..74077b33f945 100644
--- a/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/clang/lib/Sema/SemaPseudoObject.cpp
@@ -448,11 +448,10 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
ExprResult result;
if (opcode == BO_Assign) {
result = semanticRHS;
- syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
- opcode, capturedRHS->getType(),
- capturedRHS->getValueKind(),
- OK_Ordinary, opcLoc,
- FPOptions());
+ syntactic = BinaryOperator::Create(
+ S.Context, syntacticLHS, capturedRHS, opcode, capturedRHS->getType(),
+ capturedRHS->getValueKind(), OK_Ordinary, opcLoc, S.FPFeatures);
+
} else {
ExprResult opLHS = buildGet();
if (opLHS.isInvalid()) return ExprError();
@@ -463,14 +462,10 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
result = S.BuildBinOp(Sc, opcLoc, nonCompound, opLHS.get(), semanticRHS);
if (result.isInvalid()) return ExprError();
- syntactic =
- new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode,
- result.get()->getType(),
- result.get()->getValueKind(),
- OK_Ordinary,
- opLHS.get()->getType(),
- result.get()->getType(),
- opcLoc, FPOptions());
+ syntactic = CompoundAssignOperator::Create(
+ S.Context, syntacticLHS, capturedRHS, opcode, result.get()->getType(),
+ result.get()->getValueKind(), OK_Ordinary, opcLoc, S.FPFeatures,
+ opLHS.get()->getType(), result.get()->getType());
}
// The result of the assignment, if not void, is the value set into
@@ -1586,9 +1581,9 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
Expr *LHS, Expr *RHS) {
// 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,
- FPOptions());
+ return BinaryOperator::Create(Context, LHS, RHS, opcode,
+ Context.DependentTy, VK_RValue, OK_Ordinary,
+ opcLoc, FPFeatures);
// Filter out non-overload placeholder types in the RHS.
if (RHS->getType()->isNonOverloadPlaceholderType()) {
@@ -1648,21 +1643,20 @@ Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
= dyn_cast<CompoundAssignOperator>(syntax)) {
Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();
- return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(),
- cop->getType(),
- cop->getValueKind(),
- cop->getObjectKind(),
- cop->getComputationLHSType(),
- cop->getComputationResultType(),
- cop->getOperatorLoc(),
- FPOptions());
+ return CompoundAssignOperator::Create(
+ Context, lhs, rhs, cop->getOpcode(), cop->getType(),
+ cop->getValueKind(), cop->getObjectKind(), cop->getOperatorLoc(),
+ FPFeatures, cop->getComputationLHSType(),
+ cop->getComputationResultType());
+
} 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(), FPOptions());
+ return BinaryOperator::Create(Context, lhs, rhs, bop->getOpcode(),
+ bop->getType(), bop->getValueKind(),
+ bop->getObjectKind(), bop->getOperatorLoc(),
+ FPFeatures);
+
} else if (isa<CallExpr>(syntax)) {
return syntax;
} else {
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 7bfdb12a38c6..de7892f64257 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -10262,8 +10262,12 @@ TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) {
RHS.get() == E->getRHS())
return E;
+ if (E->isCompoundAssignmentOp())
+ // FPFeatures has already been established from trailing storage
+ return getDerived().RebuildBinaryOperator(
+ E->getOperatorLoc(), E->getOpcode(), LHS.get(), RHS.get());
Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
- getSema().FPFeatures = E->getFPFeatures();
+ getSema().FPFeatures = E->getFPFeatures(getSema().getASTContext());
return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),
LHS.get(), RHS.get());
@@ -10317,6 +10321,8 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCompoundAssignOperator(
CompoundAssignOperator *E) {
+ Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
+ getSema().FPFeatures = E->getFPFeatures(getSema().getASTContext());
return getDerived().TransformBinaryOperator(E);
}
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index e34556a74982..71d862c82d7c 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1051,12 +1051,16 @@ void ASTStmtReader::VisitCastExpr(CastExpr *E) {
}
void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) {
+ bool hasFP_Features;
+ BinaryOperator::Opcode opc;
VisitExpr(E);
+ E->setHasStoredFPFeatures(hasFP_Features = Record.readInt());
+ E->setOpcode(opc = (BinaryOperator::Opcode)Record.readInt());
E->setLHS(Record.readSubExpr());
E->setRHS(Record.readSubExpr());
- E->setOpcode((BinaryOperator::Opcode)Record.readInt());
E->setOperatorLoc(readSourceLocation());
- E->setFPFeatures(FPOptions(Record.readInt()));
+ if (hasFP_Features)
+ E->setStoredFPFeatures(FPOptions(Record.readInt()));
}
void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
@@ -2933,11 +2937,13 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_BINARY_OPERATOR:
- S = new (Context) BinaryOperator(Empty);
+ S = BinaryOperator::CreateEmpty(Context,
+ Record[ASTStmtReader::NumExprFields]);
break;
case EXPR_COMPOUND_ASSIGN_OPERATOR:
- S = new (Context) CompoundAssignOperator(Empty);
+ S = CompoundAssignOperator::CreateEmpty(
+ Context, Record[ASTStmtReader::NumExprFields]);
break;
case EXPR_CONDITIONAL_OPERATOR:
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 8bb253fbf16d..7f59a2e8695b 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -3906,7 +3906,7 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
/// Write an FP_PRAGMA_OPTIONS block for the given FPOptions.
void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) {
- RecordData::value_type Record[] = {Opts.getInt()};
+ RecordData::value_type Record[] = {Opts.getAsOpaqueInt()};
Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record);
}
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 82a74c1c4e7c..b7e46bc40c77 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -919,11 +919,16 @@ void ASTStmtWriter::VisitCastExpr(CastExpr *E) {
void ASTStmtWriter::VisitBinaryOperator(BinaryOperator *E) {
VisitExpr(E);
+ bool HasFPFeatures = E->hasStoredFPFeatures();
+ // Write this first for easy access when deserializing, as they affect the
+ // size of the UnaryOperator.
+ Record.push_back(HasFPFeatures);
+ Record.push_back(E->getOpcode()); // FIXME: stable encoding
Record.AddStmt(E->getLHS());
Record.AddStmt(E->getRHS());
- Record.push_back(E->getOpcode()); // FIXME: stable encoding
Record.AddSourceLocation(E->getOperatorLoc());
- Record.push_back(E->getFPFeatures().getInt());
+ if (HasFPFeatures)
+ Record.push_back(E->getStoredFPFeatures().getAsOpaqueInt());
Code = serialization::EXPR_BINARY_OPERATOR;
}
@@ -1514,7 +1519,7 @@ void ASTStmtWriter::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) {
void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
VisitCallExpr(E);
Record.push_back(E->getOperator());
- Record.push_back(E->getFPFeatures().getInt());
+ Record.push_back(E->getFPFeatures().getAsOpaqueInt());
Record.AddSourceRange(E->Range);
Code = serialization::EXPR_CXX_OPERATOR_CALL;
}
More information about the cfe-commits
mailing list