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));
}
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; }
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
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
}
};
+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 {
// 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);
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;
};
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 {
{}
// 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;
}
}
/// 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:
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) {
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>
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();
: 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();
}
void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects,
alignof(CUDAKernelCallExpr));
return new (Mem) CUDAKernelCallExpr(NumArgs, Empty);
-}
\ No newline at end of file
+}
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) {
/*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.
//===----------------------------------------------------------------------===//
#include "clang/Basic/LangOptions.h"
+#include "clang/AST/ASTContext.h"
using namespace clang;
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();
+}
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;
}
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);
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.
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);
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.
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);
// 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) {
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(),
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,
// 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
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);
}
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.
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
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()));
}
}
/*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.
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();
// 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?
// 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);
}
return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args,
Context.DependentTy, VK_RValue, RLoc,
- FPOptions());
+ FPFeatures);
}
// Handle placeholders on both operands.
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();
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;
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();
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();
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
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()) {
= 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 {
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());
ExprResult
TreeTransform<Derived>::TransformCompoundAssignOperator(
CompoundAssignOperator *E) {
+ Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
+ getSema().FPFeatures = E->getFPFeatures(getSema().getASTContext());
return getDerived().TransformBinaryOperator(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) {
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:
/// 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);
}
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;
}
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;
}