diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -3475,17 +3475,36 @@ 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(reinterpret_cast(this) + + offsetOfTrailingStorage()); + } + const FPOptions *getTrailingFPFeatures() const { + assert(BinaryOperatorBits.HasFPFeatures); + return reinterpret_cast( + reinterpret_cast(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 @@ 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 @@ 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 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 @@ } }; +inline size_t BinaryOperator::offsetOfTrailingStorage() const { + assert(BinaryOperatorBits.HasFPFeatures); + return isa(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 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -166,7 +166,7 @@ // 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 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -525,8 +525,9 @@ 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 --- 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 @@ {} // 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 @@ } /// 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 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6703,9 +6703,10 @@ 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 @@ 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 diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -4347,6 +4347,48 @@ 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(e)) e = ewc->getSubExpr(); diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -530,11 +530,11 @@ : 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(OpKind)) && "OperatorKind overflow!"); - assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getInt()) && + assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getAsOpaqueInt()) && "FPFeatures overflow!"); Range = getSourceRangeImpl(); } @@ -1639,4 +1639,4 @@ 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 --- a/clang/lib/Analysis/BodyFarm.cpp +++ b/clang/lib/Analysis/BodyFarm.cpp @@ -114,21 +114,20 @@ BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty) { - return new (C) BinaryOperator(const_cast(LHS), const_cast(RHS), - BO_Assign, Ty, VK_RValue, - OK_Ordinary, SourceLocation(), FPOptions()); + return BinaryOperator::Create( + C, const_cast(LHS), const_cast(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(LHS), - const_cast(RHS), - Op, - C.getLogicalOperationType(), - VK_RValue, - OK_Ordinary, SourceLocation(), FPOptions()); + return BinaryOperator::Create(C, const_cast(LHS), + const_cast(RHS), Op, + C.getLogicalOperationType(), VK_RValue, + OK_Ordinary, SourceLocation(), + FPOptions(C.getLangOpts())); } CompoundStmt *ASTMaker::makeCompound(ArrayRef Stmts) { @@ -296,7 +295,8 @@ /*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 --- 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 @@ 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 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2929,7 +2929,7 @@ 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 @@ 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 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -1491,11 +1491,11 @@ 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 @@ CallExpr *CalleeExp = cast(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 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -2908,7 +2908,7 @@ 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 @@ 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 @@ // 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 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -7484,10 +7484,10 @@ 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 --- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -2995,10 +2995,9 @@ 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 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -13695,11 +13695,10 @@ // 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 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -13366,13 +13366,13 @@ 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()->getElementType(), S); } @@ -13694,8 +13694,8 @@ 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 @@ 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 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6991,9 +6991,10 @@ 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 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -12975,7 +12975,7 @@ /*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 @@ 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 @@ // 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 @@ // 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 @@ return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args, Context.DependentTy, VK_RValue, RLoc, - FPOptions()); + FPFeatures); } // Handle placeholders on both operands. @@ -13781,8 +13780,7 @@ 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 @@ 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 @@ 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 --- a/clang/lib/Sema/SemaPseudoObject.cpp +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -448,11 +448,10 @@ 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 @@ 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 @@ 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 @@ = dyn_cast(syntax)) { Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS()); Expr *rhs = cast(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(syntax)) { Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); Expr *rhs = cast(bop->getRHS())->getSourceExpr(); - return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(), - bop->getType(), bop->getValueKind(), - bop->getObjectKind(), - bop->getOperatorLoc(), FPOptions()); + return BinaryOperator::Create(Context, lhs, rhs, bop->getOpcode(), + bop->getType(), bop->getValueKind(), + bop->getObjectKind(), bop->getOperatorLoc(), + FPFeatures); + } else if (isa(syntax)) { return syntax; } else { diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -10262,8 +10262,12 @@ 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 @@ ExprResult TreeTransform::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 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1051,12 +1051,16 @@ } 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 @@ 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 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -3906,7 +3906,7 @@ /// 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 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -919,11 +919,16 @@ 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::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; }