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 @@ -3462,32 +3462,54 @@ /// value-dependent). If either x or y is type-dependent, or if the /// "+" resolves to an overloaded operator, CXXOperatorCallExpr will /// be used to express the computation. -class BinaryOperator : public Expr { +class BinaryOperator final + : public Expr, + private llvm::TrailingObjects { enum { LHS, RHS, END_EXPR }; Stmt *SubExprs[END_EXPR]; + /// Return the size in bytes needed for the trailing objects. + /// Used by the derived classes to allocate the right amount of storage. + static unsigned sizeOfTrailingObjects(bool hasFP, bool isCompound) { + return (hasFP ? 1 : 0) * sizeof(unsigned) + + (isCompound ? 2 : 0) * sizeof(QualType); + } + unsigned numTrailingObjects(OverloadToken) const { + return hasFPFeatures() ? 1 : 0; + } + unsigned numTrailingObjects(OverloadToken) const { + auto opc = static_cast(BinaryOperatorBits.Opc); + return isCompoundAssignmentOp(opc) ? 2 : 0; + } + public: typedef BinaryOperatorKind Opcode; BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, - ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, - FPOptions FPFeatures) + ExprValueKind VK, ExprObjectKind OK, + SourceLocation opLoc, FPOptions FPFeatures, + QualType CompLHSType = QualType(), + QualType CompResultType = QualType()) : Expr(BinaryOperatorClass, ResTy, VK, OK) { BinaryOperatorBits.Opc = opc; - BinaryOperatorBits.FPFeatures = FPFeatures.getInt(); BinaryOperatorBits.OpLoc = opLoc; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; - assert(!isCompoundAssignmentOp() && - "Use CompoundAssignOperator for compound assignments"); + assert(((isCompoundAssignmentOp() && CompLHSType != QualType() && + CompResultType != QualType()) || + (!isCompoundAssignmentOp() && CompLHSType == QualType() && + CompResultType == QualType())) && + "Expected binaryoperator opcode"); + BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage(); + if (BinaryOperatorBits.HasFPFeatures) + *getTrailingObjects() = FPFeatures; + if (isCompoundAssignmentOp()) { + setComputationLHSType(CompLHSType); + setComputationResultType(CompResultType); + } setDependence(computeDependence(this)); } - /// Construct an empty binary operator. - explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty) { - BinaryOperatorBits.Opc = BO_Comma; - } - SourceLocation getExprLoc() const { return getOperatorLoc(); } SourceLocation getOperatorLoc() const { return BinaryOperatorBits.OpLoc; } void setOperatorLoc(SourceLocation L) { BinaryOperatorBits.OpLoc = L; } @@ -3616,8 +3638,7 @@ Expr *LHS, Expr *RHS); static bool classof(const Stmt *S) { - return S->getStmtClass() >= firstBinaryOperatorConstant && - S->getStmtClass() <= lastBinaryOperatorConstant; + return S->getStmtClass() == BinaryOperatorClass; } // Iterators @@ -3631,11 +3652,36 @@ // Set the FP contractability status of this operator. Only meaningful for // operations on floating point types. void setFPFeatures(FPOptions F) { - BinaryOperatorBits.FPFeatures = F.getInt(); + assert(hasFPFeatures()); + *getTrailingObjects() = FPOptions(F.getAsOpaqueInt()); } + static BinaryOperator * + CreateEmpty(const ASTContext &C, unsigned hasFPFeatures, unsigned isCompound); + + static BinaryOperator *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()); + + bool isCompoundAssign() const { + auto opc = static_cast(BinaryOperatorBits.Opc); + return isCompoundAssignmentOp(opc); + } + + void setHasFPFeatures(bool B) { BinaryOperatorBits.HasFPFeatures = B; } + bool hasFPFeatures() const { return BinaryOperatorBits.HasFPFeatures; } FPOptions getFPFeatures() const { - return FPOptions(BinaryOperatorBits.FPFeatures); + assert(hasFPFeatures()); + return *getTrailingObjects(); + } + FPOptions getFPFeatures(const ASTContext &C) const { + if (hasFPFeatures()) + return *getTrailingObjects(); + else + return FPOptions::defaultWithoutTrailingStorage(C); } // Get the FP contractability status of this operator. Only meaningful for @@ -3648,62 +3694,56 @@ // operations on floating point types. bool isFEnvAccessOn() const { return getFPFeatures().allowFEnvAccess(); } + /// For compound assignments (e.g. +=), we keep + /// track of the type the operation is performed in. Due to the semantics of + /// these operators, the operands are promoted, the arithmetic performed, an + /// implicit conversion back to the result type done, then the assignment + /// takes place. This captures the intermediate type which the computation + /// is done in. + /// The two computation types are the type the LHS is converted + /// to for the computation and the type of the result; the two are + /// distinct in a few cases (specifically, int+=ptr and ptr-=ptr). + QualType getComputationLHSType() const { + assert(isCompoundAssignmentOp() && + "Expected compound assignment operator"); + return getTrailingObjects()[0]; + } + void setComputationLHSType(QualType T) { + assert(isCompoundAssignmentOp() && + "Expected compound assignment operator"); + getTrailingObjects()[0] = T; + } + QualType getComputationResultType() const { + assert(isCompoundAssignmentOp() && + "Expected compound assignment operator"); + return getTrailingObjects()[1]; + } + void setComputationResultType(QualType T) { + assert(isCompoundAssignmentOp() && + "Expected compound assignment operator"); + getTrailingObjects()[1] = T; + } + protected: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptions FPFeatures, bool dead2) - : Expr(CompoundAssignOperatorClass, ResTy, VK, OK) { + : Expr(BinaryOperatorClass, ResTy, VK, OK) { BinaryOperatorBits.Opc = opc; - BinaryOperatorBits.FPFeatures = FPFeatures.getInt(); BinaryOperatorBits.OpLoc = opLoc; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; setDependence(computeDependence(this)); } - BinaryOperator(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { - BinaryOperatorBits.Opc = BO_MulAssign; - } -}; - -/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep -/// track of the type the operation is performed in. Due to the semantics of -/// these operators, the operands are promoted, the arithmetic performed, an -/// implicit conversion back to the result type done, then the assignment takes -/// place. This captures the intermediate type which the computation is done -/// in. -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) { - assert(isCompoundAssignmentOp() && - "Only should be used for compound assignments"); - } - - /// Build an empty compound assignment operator expression. - explicit CompoundAssignOperator(EmptyShell Empty) - : BinaryOperator(CompoundAssignOperatorClass, Empty) { } - - // The two computation types are the type the LHS is converted - // to for the computation and the type of the result; the two are - // distinct in a few cases (specifically, int+=ptr and ptr-=ptr). - QualType getComputationLHSType() const { return ComputationLHSType; } - void setComputationLHSType(QualType T) { ComputationLHSType = T; } - - QualType getComputationResultType() const { return ComputationResultType; } - void setComputationResultType(QualType T) { ComputationResultType = T; } - - static bool classof(const Stmt *S) { - return S->getStmtClass() == CompoundAssignOperatorClass; + BinaryOperator(EmptyShell Empty, unsigned hasFPFeatures, unsigned isCompound) + : Expr(BinaryOperatorClass, Empty) { + if (isCompound) + BinaryOperatorBits.Opc = BO_MulAssign; + else + BinaryOperatorBits.Opc = BO_Mul; } + friend TrailingObjects; }; /// AbstractConditionalOperator - An abstract base class for 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/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h --- a/clang/include/clang/AST/JSONNodeDumper.h +++ b/clang/include/clang/AST/JSONNodeDumper.h @@ -262,7 +262,7 @@ void VisitPredefinedExpr(const PredefinedExpr *PE); void VisitUnaryOperator(const UnaryOperator *UO); void VisitBinaryOperator(const BinaryOperator *BO); - void VisitCompoundAssignOperator(const CompoundAssignOperator *CAO); + void VisitCompoundAssignOperator(const BinaryOperator *CAO); void VisitMemberExpr(const MemberExpr *ME); void VisitCXXNewExpr(const CXXNewExpr *NE); void VisitCXXDeleteExpr(const CXXDeleteExpr *DE); diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -424,10 +424,10 @@ // assignment methods. Compound assignment operators are not // classes in themselves (they're all opcodes in // CompoundAssignOperator) but do have visitors. -#define OPERATOR(NAME) \ - GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator) +#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME##Assign, BinaryOperator) CAO_LIST() + #undef OPERATOR #undef GENERAL_BINOP_FALLBACK @@ -567,7 +567,7 @@ #define OPERATOR(NAME) \ case BO_##NAME##Assign: \ - DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S); + DISPATCH_STMT(Bin##NAME##Assign, BinaryOperator, S); CAO_LIST() #undef OPERATOR @@ -2678,7 +2678,6 @@ DEF_TRAVERSE_STMT(ConditionalOperator, {}) DEF_TRAVERSE_STMT(UnaryOperator, {}) DEF_TRAVERSE_STMT(BinaryOperator, {}) -DEF_TRAVERSE_STMT(CompoundAssignOperator, {}) DEF_TRAVERSE_STMT(CXXNoexceptExpr, {}) DEF_TRAVERSE_STMT(PackExpansionExpr, {}) DEF_TRAVERSE_STMT(SizeOfPackExpr, {}) 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 @@ -524,9 +524,7 @@ unsigned Opc : 6; - /// This is only meaningful for operations on floating point - /// types and 0 otherwise. - unsigned FPFeatures : 8; + unsigned HasFPFeatures : 1; SourceLocation OpLoc; }; diff --git a/clang/include/clang/AST/StmtVisitor.h b/clang/include/clang/AST/StmtVisitor.h --- a/clang/include/clang/AST/StmtVisitor.h +++ b/clang/include/clang/AST/StmtVisitor.h @@ -70,16 +70,16 @@ case BO_LAnd: DISPATCH(BinLAnd, BinaryOperator); case BO_LOr : DISPATCH(BinLOr, BinaryOperator); case BO_Assign: DISPATCH(BinAssign, BinaryOperator); - case BO_MulAssign: DISPATCH(BinMulAssign, CompoundAssignOperator); - case BO_DivAssign: DISPATCH(BinDivAssign, CompoundAssignOperator); - case BO_RemAssign: DISPATCH(BinRemAssign, CompoundAssignOperator); - case BO_AddAssign: DISPATCH(BinAddAssign, CompoundAssignOperator); - case BO_SubAssign: DISPATCH(BinSubAssign, CompoundAssignOperator); - case BO_ShlAssign: DISPATCH(BinShlAssign, CompoundAssignOperator); - case BO_ShrAssign: DISPATCH(BinShrAssign, CompoundAssignOperator); - case BO_AndAssign: DISPATCH(BinAndAssign, CompoundAssignOperator); - case BO_OrAssign: DISPATCH(BinOrAssign, CompoundAssignOperator); - case BO_XorAssign: DISPATCH(BinXorAssign, CompoundAssignOperator); + case BO_MulAssign: DISPATCH(BinMulAssign, BinaryOperator); + case BO_DivAssign: DISPATCH(BinDivAssign, BinaryOperator); + case BO_RemAssign: DISPATCH(BinRemAssign, BinaryOperator); + case BO_AddAssign: DISPATCH(BinAddAssign, BinaryOperator); + case BO_SubAssign: DISPATCH(BinSubAssign, BinaryOperator); + case BO_ShlAssign: DISPATCH(BinShlAssign, BinaryOperator); + case BO_ShrAssign: DISPATCH(BinShrAssign, BinaryOperator); + case BO_AndAssign: DISPATCH(BinAndAssign, BinaryOperator); + case BO_OrAssign: DISPATCH(BinOrAssign, BinaryOperator); + case BO_XorAssign: DISPATCH(BinXorAssign, BinaryOperator); case BO_Comma: DISPATCH(BinComma, BinaryOperator); } } else if (PTR(UnaryOperator) UnOp = dyn_cast(S)) { @@ -141,9 +141,9 @@ // If the implementation doesn't implement compound assignment operator // methods, fall back on VisitCompoundAssignOperator. -#define CAO_FALLBACK(NAME) \ - RetTy VisitBin ## NAME(PTR(CompoundAssignOperator) S, ParamTys... P) { \ - DISPATCH(CompoundAssignOperator, CompoundAssignOperator); \ +#define CAO_FALLBACK(NAME) \ + RetTy VisitBin##NAME(PTR(BinaryOperator) S, ParamTys... P) { \ + DISPATCH(BinAssign, BinaryOperator); \ } CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign) CAO_FALLBACK(AddAssign) CAO_FALLBACK(SubAssign) CAO_FALLBACK(ShlAssign) diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -247,7 +247,6 @@ void VisitMemberExpr(const MemberExpr *Node); void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node); void VisitBinaryOperator(const BinaryOperator *Node); - void VisitCompoundAssignOperator(const CompoundAssignOperator *Node); void VisitAddrLabelExpr(const AddrLabelExpr *Node); void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node); void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node); 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 @@ -26,6 +26,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 { @@ -356,11 +358,10 @@ /// Floating point control options class FPOptions { public: - FPOptions() : fp_contract(LangOptions::FPC_Off), - fenv_access(LangOptions::FEA_Off), - rounding(LangOptions::FPR_ToNearest), - exceptions(LangOptions::FPE_Ignore) - {} + FPOptions() + : fp_contract(LangOptions::FPC_Off), fenv_access(LangOptions::FEA_Off), + rounding(LangOptions::FPR_ToNearest), + exceptions(LangOptions::FPE_Ignore) {} // Used for serializing. explicit FPOptions(unsigned I) @@ -372,12 +373,26 @@ explicit FPOptions(const LangOptions &LangOpts) : fp_contract(LangOpts.getDefaultFPContractMode()), - fenv_access(LangOptions::FEA_Off), - rounding(LangOptions::FPR_ToNearest), - exceptions(LangOptions::FPE_Ignore) - {} + fenv_access(LangOptions::FEA_Off), rounding(LangOptions::FPR_ToNearest), + exceptions(LangOptions::FPE_Ignore) {} // 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); + static FPOptions defaultWithoutTrailingStorage() { + FPOptions result; + return result; + } + // 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 requiresTrailingStorage() { + // For the time being, always return true. + return true; + } + bool allowFPContractWithinStatement() const { return fp_contract == LangOptions::FPC_On; } @@ -429,9 +444,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/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -74,7 +74,6 @@ def MemberExpr : StmtNode; def CastExpr : StmtNode; def BinaryOperator : StmtNode; -def CompoundAssignOperator : StmtNode; def AbstractConditionalOperator : StmtNode; def ConditionalOperator : StmtNode; def BinaryConditionalOperator : StmtNode; diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1562,7 +1562,7 @@ /// A BinaryOperator record. EXPR_BINARY_OPERATOR, - /// A CompoundAssignOperator record. + /// Defunct: CompoundAssignOperator is part of BinaryOperator EXPR_COMPOUND_ASSIGN_OPERATOR, /// A ConditionOperator record. 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 @@ -606,7 +606,6 @@ ExpectedStmt VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); ExpectedStmt VisitExpressionTraitExpr(ExpressionTraitExpr *E); ExpectedStmt VisitArraySubscriptExpr(ArraySubscriptExpr *E); - ExpectedStmt VisitCompoundAssignOperator(CompoundAssignOperator *E); ExpectedStmt VisitImplicitCastExpr(ImplicitCastExpr *E); ExpectedStmt VisitExplicitCastExpr(ExplicitCastExpr *E); ExpectedStmt VisitOffsetOfExpr(OffsetOfExpr *OE); @@ -6688,9 +6687,20 @@ if (Err) return std::move(Err); - return new (Importer.getToContext()) BinaryOperator( - ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(), - E->getObjectKind(), ToOperatorLoc, E->getFPFeatures()); + if (E->isCompoundAssign()) { + if (Err) + return std::move(Err); + return BinaryOperator::Create( + Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType, + E->getValueKind(), E->getObjectKind(), + ToOperatorLoc, E->getFPFeatures(Importer.getToContext()), + importChecked(Err, E->getComputationLHSType()), + importChecked(Err, E->getComputationResultType())); + } + return BinaryOperator::Create( + Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType, + E->getValueKind(), E->getObjectKind(), ToOperatorLoc, + E->getFPFeatures(Importer.getToContext())); } ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) { @@ -6785,25 +6795,6 @@ ToRBracketLoc); } -ExpectedStmt -ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { - Error Err = Error::success(); - auto ToLHS = importChecked(Err, E->getLHS()); - auto ToRHS = importChecked(Err, E->getRHS()); - auto ToType = importChecked(Err, E->getType()); - auto ToComputationLHSType = importChecked(Err, E->getComputationLHSType()); - auto ToComputationResultType = - importChecked(Err, E->getComputationResultType()); - auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); - 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()); -} - Expected ASTNodeImporter::ImportCastPath(CastExpr *CE) { CXXCastPath Path; 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 @@ -1352,8 +1352,9 @@ ADLCallKind UsesADL) { assert(!(reinterpret_cast(Mem) % alignof(CallExpr)) && "Misaligned memory in CallExpr::CreateTemporary!"); - return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, /*Args=*/{}, Ty, - VK, RParenLoc, /*MinNumArgs=*/0, UsesADL); + return new (Mem) + CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, /*Args=*/{}, Ty, VK, + RParenLoc, /*MinNumArgs=*/0, UsesADL); } CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, @@ -2358,7 +2359,6 @@ R2 = BO->getRHS()->getSourceRange(); return true; } - case CompoundAssignOperatorClass: case VAArgExprClass: case AtomicExprClass: return false; @@ -3370,7 +3370,6 @@ case MSPropertyRefExprClass: case MSPropertySubscriptExprClass: - case CompoundAssignOperatorClass: case VAArgExprClass: case AtomicExprClass: case CXXThrowExprClass: @@ -4341,6 +4340,31 @@ return new (Mem) ParenListExpr(EmptyShell(), NumExprs); } +BinaryOperator *BinaryOperator::CreateEmpty(const ASTContext &C, + unsigned hasFPFeatures, + unsigned isCompound) { + unsigned SizeOfTrailingObjects = + BinaryOperator::sizeOfTrailingObjects(hasFPFeatures, isCompound); + void *Mem = C.Allocate(sizeof(BinaryOperator) + SizeOfTrailingObjects, + alignof(BinaryOperator)); + return new (Mem) BinaryOperator(EmptyShell(), hasFPFeatures, isCompound); +} + +BinaryOperator * +BinaryOperator::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(); + unsigned SizeOfTrailingObjects = + BinaryOperator::sizeOfTrailingObjects(hasFPFeatures, + isCompoundAssignmentOp(opc)); + void *Mem = C.Allocate(sizeof(BinaryOperator) + SizeOfTrailingObjects, + alignof(BinaryOperator)); + return new (Mem) BinaryOperator(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,12 +530,12 @@ : CallExpr(CXXOperatorCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, OperatorLoc, /*MinNumArgs=*/0, UsesADL) { CXXOperatorCallExprBits.OperatorKind = OpKind; - CXXOperatorCallExprBits.FPFeatures = FPFeatures.getInt(); + CXXOperatorCallExprBits.FPFeatures = FPFeatures.getAsOpaqueInt(); + assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getAsOpaqueInt()) && + "FPFeatures overflow!"); assert( (CXXOperatorCallExprBits.OperatorKind == static_cast(OpKind)) && "OperatorKind overflow!"); - assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getInt()) && - "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/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -297,7 +297,6 @@ return ClassifyInternal(Ctx,cast(E)->getResultExpr()); case Expr::BinaryOperatorClass: - case Expr::CompoundAssignOperatorClass: // C doesn't have any binary expressions that are lvalues. if (Lang.CPlusPlus) return ClassifyBinaryOp(Ctx, cast(E)); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -7485,7 +7485,6 @@ return VisitUnaryPreIncDec(UO); } bool VisitBinAssign(const BinaryOperator *BO); - bool VisitCompoundAssignOperator(const CompoundAssignOperator *CAO); bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { @@ -7786,32 +7785,28 @@ UO->isIncrementOp(), nullptr); } -bool LValueExprEvaluator::VisitCompoundAssignOperator( - const CompoundAssignOperator *CAO) { +bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) - return Error(CAO); - - APValue RHS; + return Error(E); - // The overall lvalue result is the result of evaluating the LHS. - if (!this->Visit(CAO->getLHS())) { - if (Info.noteFailure()) - Evaluate(RHS, this->Info, CAO->getRHS()); - return false; - } + if (E->isCompoundAssignmentOp()) { + APValue RHS; - if (!Evaluate(RHS, this->Info, CAO->getRHS())) - return false; + // The overall lvalue result is the result of evaluating the LHS. + if (!this->Visit(E->getLHS())) { + if (Info.noteFailure()) + Evaluate(RHS, this->Info, E->getRHS()); + return false; + } - return handleCompoundAssignment( - this->Info, CAO, - Result, CAO->getLHS()->getType(), CAO->getComputationLHSType(), - CAO->getOpForCompoundAssignment(CAO->getOpcode()), RHS); -} + if (!Evaluate(RHS, this->Info, E->getRHS())) + return false; -bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { - if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) - return Error(E); + return handleCompoundAssignment( + this->Info, E, Result, E->getLHS()->getType(), + E->getComputationLHSType(), + E->getOpForCompoundAssignment(E->getOpcode()), RHS); + } APValue NewVal; @@ -14182,7 +14177,6 @@ case Expr::OMPArraySectionExprClass: case Expr::OMPArrayShapingExprClass: case Expr::MemberExprClass: - case Expr::CompoundAssignOperatorClass: case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: case Expr::DesignatedInitExprClass: diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -4168,7 +4168,6 @@ break; } - case Expr::CompoundAssignOperatorClass: // fallthrough case Expr::BinaryOperatorClass: { const BinaryOperator *BO = cast(E); if (BO->getOpcode() == BO_PtrMemD) diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -1162,14 +1162,12 @@ void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) { JOS.attribute("opcode", BinaryOperator::getOpcodeStr(BO->getOpcode())); -} - -void JSONNodeDumper::VisitCompoundAssignOperator( - const CompoundAssignOperator *CAO) { - VisitBinaryOperator(CAO); - JOS.attribute("computeLHSType", createQualType(CAO->getComputationLHSType())); - JOS.attribute("computeResultType", - createQualType(CAO->getComputationResultType())); + if (BO->isCompoundAssignmentOp()) { + JOS.attribute("computeLHSType", + createQualType(BO->getComputationLHSType())); + JOS.attribute("computeResultType", + createQualType(BO->getComputationResultType())); + } } void JSONNodeDumper::VisitMemberExpr(const MemberExpr *ME) { diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1448,12 +1448,6 @@ PrintExpr(Node->getRHS()); } -void StmtPrinter::VisitCompoundAssignOperator(CompoundAssignOperator *Node) { - PrintExpr(Node->getLHS()); - OS << " " << BinaryOperator::getOpcodeStr(Node->getOpcode()) << " "; - PrintExpr(Node->getRHS()); -} - void StmtPrinter::VisitConditionalOperator(ConditionalOperator *Node) { PrintExpr(Node->getCond()); OS << " ? "; diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -1238,11 +1238,6 @@ ID.AddInteger(S->getOpcode()); } -void -StmtProfiler::VisitCompoundAssignOperator(const CompoundAssignOperator *S) { - VisitBinaryOperator(S); -} - void StmtProfiler::VisitConditionalOperator(const ConditionalOperator *S) { VisitExpr(S); } @@ -1511,35 +1506,35 @@ case OO_PlusEqual: BinaryOp = BO_AddAssign; - return Stmt::CompoundAssignOperatorClass; + return Stmt::BinaryOperatorClass; case OO_MinusEqual: BinaryOp = BO_SubAssign; - return Stmt::CompoundAssignOperatorClass; + return Stmt::BinaryOperatorClass; case OO_StarEqual: BinaryOp = BO_MulAssign; - return Stmt::CompoundAssignOperatorClass; + return Stmt::BinaryOperatorClass; case OO_SlashEqual: BinaryOp = BO_DivAssign; - return Stmt::CompoundAssignOperatorClass; + return Stmt::BinaryOperatorClass; case OO_PercentEqual: BinaryOp = BO_RemAssign; - return Stmt::CompoundAssignOperatorClass; + return Stmt::BinaryOperatorClass; case OO_CaretEqual: BinaryOp = BO_XorAssign; - return Stmt::CompoundAssignOperatorClass; + return Stmt::BinaryOperatorClass; case OO_AmpEqual: BinaryOp = BO_AndAssign; - return Stmt::CompoundAssignOperatorClass; + return Stmt::BinaryOperatorClass; case OO_PipeEqual: BinaryOp = BO_OrAssign; - return Stmt::CompoundAssignOperatorClass; + return Stmt::BinaryOperatorClass; case OO_LessLess: BinaryOp = BO_Shl; @@ -1551,11 +1546,11 @@ case OO_LessLessEqual: BinaryOp = BO_ShlAssign; - return Stmt::CompoundAssignOperatorClass; + return Stmt::BinaryOperatorClass; case OO_GreaterGreaterEqual: BinaryOp = BO_ShrAssign; - return Stmt::CompoundAssignOperatorClass; + return Stmt::BinaryOperatorClass; case OO_EqualEqual: BinaryOp = BO_EQ; @@ -1642,8 +1637,7 @@ Visit(S->getArg(I)); if (SC == Stmt::UnaryOperatorClass) ID.AddInteger(UnaryOp); - else if (SC == Stmt::BinaryOperatorClass || - SC == Stmt::CompoundAssignOperatorClass) + else if (SC == Stmt::BinaryOperatorClass) ID.AddInteger(BinaryOp); else assert(SC == Stmt::ArraySubscriptExprClass); diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -869,15 +869,12 @@ void TextNodeDumper::VisitBinaryOperator(const BinaryOperator *Node) { OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; -} - -void TextNodeDumper::VisitCompoundAssignOperator( - const CompoundAssignOperator *Node) { - OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) - << "' ComputeLHSTy="; - dumpBareType(Node->getComputationLHSType()); - OS << " ComputeResultTy="; - dumpBareType(Node->getComputationResultType()); + if (Node->isCompoundAssignmentOp()) { + OS << " ComputeLHSTy="; + dumpBareType(Node->getComputationLHSType()); + OS << " ComputeResultTy="; + dumpBareType(Node->getComputationResultType()); + } } void TextNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) { 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,21 @@ 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::defaultWithoutTrailingStorage()); } 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::defaultWithoutTrailingStorage()); } CompoundStmt *ASTMaker::makeCompound(ArrayRef Stmts) { @@ -296,7 +296,8 @@ /*Args=*/CallArgs, /*QualType=*/C.VoidTy, /*ExprValueType=*/VK_RValue, - /*SourceLocation=*/SourceLocation(), FPOptions()); + /*SourceLocation=*/SourceLocation(), + /*FPFeatures=*/FPOptions::defaultWithoutTrailingStorage()); } /// Create a fake body for std::call_once. @@ -578,8 +579,8 @@ ASTMaker M(C); DeclRefExpr *DR = M.makeDeclRefExpr(PV); ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty); - CallExpr *CE = - CallExpr::Create(C, ICE, None, C.VoidTy, VK_RValue, SourceLocation()); + CallExpr *CE = CallExpr::Create(C, ICE, None, C.VoidTy, VK_RValue, + SourceLocation()); return CE; } diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -2150,8 +2150,12 @@ case Stmt::BinaryConditionalOperatorClass: return VisitConditionalOperator(cast(S), asc); - case Stmt::BinaryOperatorClass: + case Stmt::BinaryOperatorClass: { + auto BO = dyn_cast(S); + if (BO->isCompoundAssignmentOp()) + return VisitStmt(S, asc); return VisitBinaryOperator(cast(S), asc); + } case Stmt::BlockExprClass: return VisitBlockExpr(cast(S), asc); diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp --- a/clang/lib/Analysis/ReachableCode.cpp +++ b/clang/lib/Analysis/ReachableCode.cpp @@ -561,12 +561,6 @@ R1 = UO->getSubExpr()->getSourceRange(); return UO->getOperatorLoc(); } - case Expr::CompoundAssignOperatorClass: { - const CompoundAssignOperator *CAO = cast(S); - R1 = CAO->getLHS()->getSourceRange(); - R2 = CAO->getRHS()->getSourceRange(); - return CAO->getOperatorLoc(); - } case Expr::BinaryConditionalOperatorClass: case Expr::ConditionalOperatorClass: { const AbstractConditionalOperator *CO = diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp --- a/clang/lib/Analysis/ThreadSafetyCommon.cpp +++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp @@ -222,7 +222,6 @@ case Stmt::UnaryOperatorClass: return translateUnaryOperator(cast(S), Ctx); case Stmt::BinaryOperatorClass: - case Stmt::CompoundAssignOperatorClass: return translateBinaryOperator(cast(S), Ctx); case Stmt::ArraySubscriptExprClass: 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 @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/ASTContext.h" #include "clang/Basic/LangOptions.h" using namespace clang; @@ -47,3 +48,13 @@ 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) { + // For the time being, always return true. + return true; +} diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1271,15 +1271,17 @@ return EmitObjCSelectorLValue(cast(E)); case Expr::ObjCIsaExprClass: return EmitObjCIsaExpr(cast(E)); - case Expr::BinaryOperatorClass: - return EmitBinaryOperatorLValue(cast(E)); - case Expr::CompoundAssignOperatorClass: { - QualType Ty = E->getType(); - if (const AtomicType *AT = Ty->getAs()) - Ty = AT->getValueType(); - if (!Ty->isAnyComplexType()) - return EmitCompoundAssignmentLValue(cast(E)); - return EmitComplexCompoundAssignmentLValue(cast(E)); + case Expr::BinaryOperatorClass: { + const auto *const BO = cast(E); + if (BO->isCompoundAssignmentOp()) { + QualType Ty = BO->getType(); + if (const AtomicType *AT = Ty->getAs()) + Ty = AT->getValueType(); + if (!Ty->isAnyComplexType()) + return EmitCompoundAssignmentLValue(BO); + return EmitComplexCompoundAssignmentLValue(BO); + } + return EmitBinaryOperatorLValue(BO); } case Expr::CallExprClass: case Expr::CXXMemberCallExprClass: diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -251,13 +251,13 @@ }; BinOpInfo EmitBinOps(const BinaryOperator *E); - LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E, - ComplexPairTy (ComplexExprEmitter::*Func) - (const BinOpInfo &), - RValue &Val); - ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E, - ComplexPairTy (ComplexExprEmitter::*Func) - (const BinOpInfo &)); + LValue EmitCompoundAssignLValue( + const BinaryOperator *E, + ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo &), + RValue &Val); + ComplexPairTy EmitCompoundAssign( + const BinaryOperator *E, + ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo &)); ComplexPairTy EmitBinAdd(const BinOpInfo &Op); ComplexPairTy EmitBinSub(const BinOpInfo &Op); @@ -285,16 +285,16 @@ } // Compound assignments. - ComplexPairTy VisitBinAddAssign(const CompoundAssignOperator *E) { + ComplexPairTy VisitBinAddAssign(const BinaryOperator *E) { return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinAdd); } - ComplexPairTy VisitBinSubAssign(const CompoundAssignOperator *E) { + ComplexPairTy VisitBinSubAssign(const BinaryOperator *E) { return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinSub); } - ComplexPairTy VisitBinMulAssign(const CompoundAssignOperator *E) { + ComplexPairTy VisitBinMulAssign(const BinaryOperator *E) { return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinMul); } - ComplexPairTy VisitBinDivAssign(const CompoundAssignOperator *E) { + ComplexPairTy VisitBinDivAssign(const BinaryOperator *E) { return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinDiv); } @@ -884,11 +884,9 @@ return Ops; } - -LValue ComplexExprEmitter:: -EmitCompoundAssignLValue(const CompoundAssignOperator *E, - ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&), - RValue &Val) { +LValue ComplexExprEmitter::EmitCompoundAssignLValue( + const BinaryOperator *E, + ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo &), RValue &Val) { TestAndClearIgnoreReal(); TestAndClearIgnoreImag(); QualType LHSTy = E->getLHS()->getType(); @@ -955,9 +953,9 @@ } // Compound assignments. -ComplexPairTy ComplexExprEmitter:: -EmitCompoundAssign(const CompoundAssignOperator *E, - ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){ +ComplexPairTy ComplexExprEmitter::EmitCompoundAssign( + const BinaryOperator *E, + ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo &)) { RValue Val; LValue LV = EmitCompoundAssignLValue(E, Func, Val); @@ -1160,16 +1158,16 @@ } } -LValue CodeGenFunction:: -EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) { +LValue +CodeGenFunction::EmitComplexCompoundAssignmentLValue(const BinaryOperator *E) { CompoundFunc Op = getComplexOp(E->getOpcode()); RValue Val; return ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val); } -LValue CodeGenFunction:: -EmitScalarCompoundAssignWithComplex(const CompoundAssignOperator *E, - llvm::Value *&Result) { +LValue +CodeGenFunction::EmitScalarCompoundAssignWithComplex(const BinaryOperator *E, + llvm::Value *&Result) { CompoundFunc Op = getComplexOp(E->getOpcode()); RValue Val; LValue Ret = ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val); 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 @@ -777,20 +777,21 @@ Value *EmitFixedPointBinOp(const BinOpInfo &Ops); BinOpInfo EmitBinOps(const BinaryOperator *E); - LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E, - Value *(ScalarExprEmitter::*F)(const BinOpInfo &), - Value *&Result); + LValue + EmitCompoundAssignLValue(const BinaryOperator *E, + Value *(ScalarExprEmitter::*F)(const BinOpInfo &), + Value *&Result); - Value *EmitCompoundAssign(const CompoundAssignOperator *E, + Value *EmitCompoundAssign(const BinaryOperator *E, Value *(ScalarExprEmitter::*F)(const BinOpInfo &)); // Binary operators and binary compound assignment operators. -#define HANDLEBINOP(OP) \ - Value *VisitBin ## OP(const BinaryOperator *E) { \ - return Emit ## OP(EmitBinOps(E)); \ - } \ - Value *VisitBin ## OP ## Assign(const CompoundAssignOperator *E) { \ - return EmitCompoundAssign(E, &ScalarExprEmitter::Emit ## OP); \ +#define HANDLEBINOP(OP) \ + Value *VisitBin##OP(const BinaryOperator *E) { \ + return Emit##OP(EmitBinOps(E)); \ + } \ + Value *VisitBin##OP##Assign(const BinaryOperator *E) { \ + return EmitCompoundAssign(E, &ScalarExprEmitter::Emit##OP); \ } HANDLEBINOP(Mul) HANDLEBINOP(Div) @@ -2897,15 +2898,14 @@ 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; } LValue ScalarExprEmitter::EmitCompoundAssignLValue( - const CompoundAssignOperator *E, - Value *(ScalarExprEmitter::*Func)(const BinOpInfo &), - Value *&Result) { + const BinaryOperator *E, + Value *(ScalarExprEmitter::*Func)(const BinOpInfo &), Value *&Result) { QualType LHSTy = E->getLHS()->getType(); BinOpInfo OpInfo; @@ -2917,7 +2917,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); @@ -3032,8 +3032,9 @@ return LHSLV; } -Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, - Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) { +Value *ScalarExprEmitter::EmitCompoundAssign( + const BinaryOperator *E, + Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) { bool Ignore = TestAndClearIgnoreResultAssign(); Value *RHS = nullptr; LValue LHS = EmitCompoundAssignLValue(E, Func, RHS); @@ -4623,9 +4624,7 @@ return MakeAddrLValue(Addr, E->getType()); } - -LValue CodeGenFunction::EmitCompoundAssignmentLValue( - const CompoundAssignOperator *E) { +LValue CodeGenFunction::EmitCompoundAssignmentLValue(const BinaryOperator *E) { ScalarExprEmitter Scalar(*this); Value *Result = nullptr; switch (E->getOpcode()) { 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 @@ -1492,10 +1492,12 @@ finalArg = &argCast; - BinaryOperator assign(&ivarRef, finalArg, BO_Assign, + BinaryOperator *assign = BinaryOperator::Create(getContext(), + &ivarRef, finalArg, BO_Assign, ivarRef.getType(), VK_RValue, OK_Ordinary, - SourceLocation(), FPOptions()); - EmitStmt(&assign); + SourceLocation(), + FPOptions::defaultWithoutTrailingStorage()); + EmitStmt(assign); } /// Generate an Objective-C property setter function. @@ -3569,7 +3571,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::defaultWithoutTrailingStorage()); 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 @@ -2931,7 +2931,8 @@ 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()); + OK_Ordinary, S.getBeginLoc(), + FPOptions::defaultWithoutTrailingStorage()); // Increment for loop counter. UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary, S.getBeginLoc(), true); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3613,13 +3613,13 @@ /// Emit an l-value for an assignment (simple or compound) of complex type. LValue EmitComplexAssignmentLValue(const BinaryOperator *E); - LValue EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E); - LValue EmitScalarCompoundAssignWithComplex(const CompoundAssignOperator *E, + LValue EmitComplexCompoundAssignmentLValue(const BinaryOperator *E); + LValue EmitScalarCompoundAssignWithComplex(const BinaryOperator *E, llvm::Value *&Result); // Note: only available for agg return types LValue EmitBinaryOperatorLValue(const BinaryOperator *E); - LValue EmitCompoundAssignmentLValue(const CompoundAssignOperator *E); + LValue EmitCompoundAssignmentLValue(const BinaryOperator *E); // Note: only available for agg return types LValue EmitCallExprLValue(const CallExpr *E); // Note: only available for agg return types 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 @@ -2108,8 +2108,9 @@ DRE, nullptr, VK_RValue); const auto *FT = msgSendType->castAs(); - CallExpr *Exp = CallExpr::Create( - *Context, ICE, Args, FT->getCallResultType(*Context), VK_RValue, EndLoc); + CallExpr *Exp = + CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context), + VK_RValue, EndLoc); return Exp; } @@ -2877,8 +2878,9 @@ CK_BitCast, DictLiteralValueME); // (const id [])keys - Expr *NSKeyCallExpr = CallExpr::Create( - *Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue, SourceLocation()); + Expr *NSKeyCallExpr = + CallExpr::Create(*Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue, + SourceLocation()); MemberExpr *DictLiteralKeyME = MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD, @@ -7486,8 +7488,9 @@ VK_LValue, SourceLocation()); BinaryOperator *addExpr = new (Context) BinaryOperator(castExpr, DRE, BO_Add, - Context->getPointerType(Context->CharTy), - VK_RValue, OK_Ordinary, SourceLocation(), FPOptions()); + Context->getPointerType(Context->CharTy), + VK_RValue, OK_Ordinary, SourceLocation(), + FPOptions::defaultWithoutTrailingStorage()); // 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 @@ -2026,8 +2026,9 @@ const auto *FT = msgSendType->castAs(); - CallExpr *Exp = CallExpr::Create( - *Context, ICE, Args, FT->getCallResultType(*Context), VK_RValue, EndLoc); + CallExpr *Exp = + CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context), + VK_RValue, EndLoc); return Exp; } @@ -2998,7 +2999,7 @@ BinaryOperator *lessThanExpr = new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy, VK_RValue, OK_Ordinary, SourceLocation(), - FPOptions()); + FPOptions::defaultWithoutTrailingStorage()); // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) ConditionalOperator *CondExpr = new (Context) ConditionalOperator(lessThanExpr, diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp --- a/clang/lib/Index/IndexBody.cpp +++ b/clang/lib/Index/IndexBody.cpp @@ -75,6 +75,11 @@ if (auto BO = dyn_cast(Parent)) { if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E) Roles |= (unsigned)SymbolRole::Write; + if (BO->isCompoundAssignmentOp() && + BO->getLHS()->IgnoreParenCasts() == E) { + Roles |= (unsigned)SymbolRole::Read; + Roles |= (unsigned)SymbolRole::Write; + } } else if (auto UO = dyn_cast(Parent)) { if (UO->isIncrementDecrementOp()) { @@ -84,12 +89,6 @@ Roles |= (unsigned)SymbolRole::AddressOf; } - } else if (auto CA = dyn_cast(Parent)) { - if (CA->getLHS()->IgnoreParenCasts() == E) { - Roles |= (unsigned)SymbolRole::Read; - Roles |= (unsigned)SymbolRole::Write; - } - } else if (auto CE = dyn_cast(Parent)) { if (CE->getCallee()->IgnoreParenCasts() == E) { addCallRole(Roles, Relations); diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2075,7 +2075,6 @@ else { AC.getCFGBuildOptions() .setAlwaysAdd(Stmt::BinaryOperatorClass) - .setAlwaysAdd(Stmt::CompoundAssignOperatorClass) .setAlwaysAdd(Stmt::BlockExprClass) .setAlwaysAdd(Stmt::CStyleCastExprClass) .setAlwaysAdd(Stmt::DeclRefExprClass) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -10858,7 +10858,8 @@ /// Analyze the given compound assignment for the possible losing of /// floating-point precision. static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) { - assert(isa(E) && + + assert(E->isCompoundAssignmentOp() && "Must be compound assignment operation"); // Recurse on the LHS and RHS in here AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); @@ -10869,9 +10870,7 @@ // Now check the outermost expression const auto *ResultBT = E->getLHS()->getType()->getAs(); - const auto *RBT = cast(E) - ->getComputationResultType() - ->getAs(); + const auto *RBT = E->getComputationResultType()->getAs(); // The below checks assume source is floating point. if (!ResultBT || !RBT || !RBT->isFloatingPoint()) return; @@ -11727,7 +11726,7 @@ if (BO->getOpcode() == BO_Assign) return AnalyzeAssignment(S, BO); // And with compound assignments. - if (BO->isAssignmentOp()) + if (BO->isAssignmentOp() || BO->isCompoundAssignmentOp()) return AnalyzeCompoundAssignment(S, BO); } @@ -12534,7 +12533,7 @@ Region = LHSRegion; Visit(BO->getLHS()); - if (O && isa(BO)) + if (O && BO->isCompoundAssignmentOp()) notePostUse(O, BO); } else { @@ -12542,7 +12541,7 @@ Region = LHSRegion; Visit(BO->getLHS()); - if (O && isa(BO)) + if (O && BO->isCompoundAssignmentOp()) notePostUse(O, BO); Region = RHSRegion; @@ -12564,10 +12563,6 @@ } } - void VisitCompoundAssignOperator(const CompoundAssignOperator *CAO) { - VisitBinAssign(CAO); - } - void VisitUnaryPreInc(const UnaryOperator *UO) { VisitUnaryPreIncDec(UO); } void VisitUnaryPreDec(const UnaryOperator *UO) { VisitUnaryPreIncDec(UO); } void VisitUnaryPreIncDec(const UnaryOperator *UO) { 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 @@ -13665,8 +13665,9 @@ 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()); + BO_NE, S.Context.BoolTy, + VK_RValue, OK_Ordinary, Loc, + FPOptions::defaultWithoutTrailingStorage()); // 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/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1302,7 +1302,6 @@ case Expr::OMPArrayShapingExprClass: case Expr::BinaryOperatorClass: case Expr::DependentCoawaitExprClass: - case Expr::CompoundAssignOperatorClass: case Expr::CStyleCastExprClass: case Expr::CXXStaticCastExprClass: case Expr::CXXFunctionalCastExprClass: 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 @@ -13065,13 +13065,13 @@ BinOpResTy = S.GetSignedVectorType(BinOpResTy); if (IsCompAssign) - return new (Context) CompoundAssignOperator( - LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, BinOpResTy, BinOpResTy, - OpLoc, FPFeatures); + return BinaryOperator::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); } @@ -13385,8 +13385,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. @@ -13400,9 +13400,12 @@ 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); + if (!BinaryOperator::isCompoundAssignmentOp(Opc)) + return BinaryOperator::Create(Context, LHS.get(), RHS.get(), Opc, ResultTy, + VK, OK, OpLoc, FPFeatures); + return BinaryOperator::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 @@ -7001,9 +7001,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/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -9187,20 +9187,18 @@ AtomicBody = AtomicBody->IgnoreParenImpCasts(); if (AtomicBody->getType()->isScalarType() || AtomicBody->isInstantiationDependent()) { - if (const auto *AtomicCompAssignOp = dyn_cast( - AtomicBody->IgnoreParenImpCasts())) { - // Check for Compound Assignment Operation - Op = BinaryOperator::getOpForCompoundAssignment( - AtomicCompAssignOp->getOpcode()); - OpLoc = AtomicCompAssignOp->getOperatorLoc(); - E = AtomicCompAssignOp->getRHS(); - X = AtomicCompAssignOp->getLHS()->IgnoreParens(); - IsXLHSInRHSPart = true; - } else if (auto *AtomicBinOp = dyn_cast( - AtomicBody->IgnoreParenImpCasts())) { - // Check for Binary Operation - if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId)) + if (auto *AtomicBinOp = + dyn_cast(AtomicBody->IgnoreParenImpCasts())) { + if (AtomicBinOp->isCompoundAssignmentOp()) { + Op = BinaryOperator::getOpForCompoundAssignment( + AtomicBinOp->getOpcode()); + OpLoc = AtomicBinOp->getOperatorLoc(); + E = AtomicBinOp->getRHS(); + X = AtomicBinOp->getLHS()->IgnoreParens(); + IsXLHSInRHSPart = true; + } else if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId)) return true; + // Check for Binary Operation } else if (const auto *AtomicUnaryOp = dyn_cast( AtomicBody->IgnoreParenImpCasts())) { // Check for Unary Operation @@ -14801,8 +14799,8 @@ ELoc, Context.getPointerType(FnTy), VK_RValue, OK_Ordinary, S.DefaultLvalueConversion(DeclareReductionRef.get()).get()); Expr *Args[] = {LHS.get(), RHS.get()}; - ReductionOp = - CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc); + ReductionOp = CallExpr::Create(Context, OVE, Args, Context.VoidTy, + VK_RValue, ELoc); } else { ReductionOp = S.BuildBinOp( Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, LHSDRE, RHSDRE); 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 @@ -12974,8 +12974,8 @@ Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo, /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); return CXXOperatorCallExpr::Create(Context, Op, Fn, ArgsArray, - Context.DependentTy, VK_RValue, OpLoc, - FPOptions()); + Context.DependentTy, VK_RValue, OpLoc, + FPOptions::defaultWithoutTrailingStorage()); } // 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,14 @@ // 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 BinaryOperator::Create(Context, 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_LValue, OK_Ordinary, + OpLoc, FPFeatures, + Context.DependentTy, Context.DependentTy); } // FIXME: save results of ADL from here? @@ -13705,8 +13705,8 @@ // Can't add any actual overloads yet return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args, - Context.DependentTy, VK_RValue, RLoc, - FPOptions()); + Context.DependentTy, VK_RValue, RLoc, + FPOptions::defaultWithoutTrailingStorage()); } // Handle placeholders on both operands. @@ -13781,7 +13781,8 @@ CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(Context, OO_Subscript, FnExpr.get(), - Args, ResultTy, VK, RLoc, FPOptions()); + Args, ResultTy, VK, RLoc, + FPOptions::defaultWithoutTrailingStorage()); if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl)) return ExprError(); @@ -14405,7 +14406,8 @@ CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(Context, OO_Call, NewFn.get(), MethodArgs, - ResultTy, VK, RParenLoc, FPOptions()); + ResultTy, VK, RParenLoc, + FPOptions::defaultWithoutTrailingStorage()); if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method)) return true; @@ -14522,7 +14524,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, + FPOptions::defaultWithoutTrailingStorage()); } else { ExprResult opLHS = buildGet(); if (opLHS.isInvalid()) return ExprError(); @@ -463,14 +462,12 @@ 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 = BinaryOperator::Create( + S.Context, syntacticLHS, capturedRHS, opcode, result.get()->getType(), + result.get()->getValueKind(), OK_Ordinary, opcLoc, + FPOptions::defaultWithoutTrailingStorage(), + opLHS.get()->getType(), + result.get()->getType()); } // The result of the assignment, if not void, is the value set into @@ -1586,9 +1583,10 @@ 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, + FPOptions::defaultWithoutTrailingStorage()); // Filter out non-overload placeholder types in the RHS. if (RHS->getType()->isNonOverloadPlaceholderType()) { @@ -1639,30 +1637,31 @@ /// operations. Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) { Expr *syntax = E->getSyntacticForm(); + BinaryOperator *bop = dyn_cast(syntax); if (UnaryOperator *uop = dyn_cast(syntax)) { Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr()); return new (Context) UnaryOperator( op, uop->getOpcode(), uop->getType(), uop->getValueKind(), uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow()); - } else if (CompoundAssignOperator *cop - = 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()); - } else if (BinaryOperator *bop = dyn_cast(syntax)) { + } else if (bop && bop->isCompoundAssignmentOp()) { 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()); + bop->getType(), + bop->getValueKind(), + bop->getObjectKind(), + bop->getOperatorLoc(), + FPOptions::defaultWithoutTrailingStorage(), + bop->getComputationLHSType(), + bop->getComputationResultType()); + } else if (bop) { + 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::defaultWithoutTrailingStorage()); } 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 @@ -10184,7 +10184,7 @@ return E; 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()); @@ -10234,13 +10234,6 @@ E->getOperatorLoc(), Decomp.Opcode, UnqualLookups, LHS.get(), RHS.get()); } -template -ExprResult -TreeTransform::TransformCompoundAssignOperator( - CompoundAssignOperator *E) { - return getDerived().TransformBinaryOperator(E); -} - template ExprResult TreeTransform:: TransformBinaryConditionalOperator(BinaryConditionalOperator *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 @@ -1023,18 +1023,22 @@ } void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) { + bool hasFP_Features; + BinaryOperator::Opcode opc; VisitExpr(E); + E->setHasFPFeatures(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())); -} - -void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) { - VisitBinaryOperator(E); - E->setComputationLHSType(Record.readType()); - E->setComputationResultType(Record.readType()); + if (hasFP_Features) { + int x = Record.readInt(); + E->setFPFeatures(FPOptions(x)); + } + if (BinaryOperator::isCompoundAssignmentOp(opc)) { + E->setComputationLHSType(Record.readType()); + E->setComputationResultType(Record.readType()); + } } void ASTStmtReader::VisitConditionalOperator(ConditionalOperator *E) { @@ -2691,6 +2695,8 @@ return nullptr; } switch ((StmtCode)MaybeStmtCode.get()) { + default: + llvm_unreachable("Unexpected StmtCode"); case STMT_STOP: Finished = true; break; @@ -2905,11 +2911,9 @@ break; case EXPR_BINARY_OPERATOR: - S = new (Context) BinaryOperator(Empty); - break; - - case EXPR_COMPOUND_ASSIGN_OPERATOR: - S = new (Context) CompoundAssignOperator(Empty); + S = BinaryOperator::CreateEmpty(Context, + Record[ASTStmtReader::NumExprFields], + Record[ASTStmtReader::NumExprFields + 1]); 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 @@ -583,7 +583,6 @@ RECORD(EXPR_CALL); RECORD(EXPR_MEMBER); RECORD(EXPR_BINARY_OPERATOR); - RECORD(EXPR_COMPOUND_ASSIGN_OPERATOR); RECORD(EXPR_CONDITIONAL_OPERATOR); RECORD(EXPR_IMPLICIT_CAST); RECORD(EXPR_CSTYLE_CAST); @@ -3905,7 +3904,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 @@ -891,21 +891,23 @@ void ASTStmtWriter::VisitBinaryOperator(BinaryOperator *E) { VisitExpr(E); + bool HasFPFeatures = E->hasFPFeatures(); + // 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->getFPFeatures().getAsOpaqueInt()); + if (E->isCompoundAssignmentOp()) { + Record.AddTypeRef(E->getComputationLHSType()); + Record.AddTypeRef(E->getComputationResultType()); + } Code = serialization::EXPR_BINARY_OPERATOR; } -void ASTStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { - VisitBinaryOperator(E); - Record.AddTypeRef(E->getComputationLHSType()); - Record.AddTypeRef(E->getComputationResultType()); - Code = serialization::EXPR_COMPOUND_ASSIGN_OPERATOR; -} - void ASTStmtWriter::VisitConditionalOperator(ConditionalOperator *E) { VisitExpr(E); Record.AddStmt(E->getCond()); @@ -1486,7 +1488,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; } diff --git a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp @@ -446,7 +446,6 @@ return true; } - case Stmt::CompoundAssignOperatorClass: case Stmt::BinaryOperatorClass: { const BinaryOperator *BinOp1 = cast(Stmt1); const BinaryOperator *BinOp2 = cast(Stmt2); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1666,12 +1666,6 @@ break; } - case Stmt::CompoundAssignOperatorClass: - Bldr.takeNodes(Pred); - VisitBinaryOperator(cast(S), Pred, Dst); - Bldr.addNodes(Dst); - break; - case Stmt::CompoundLiteralExprClass: Bldr.takeNodes(Pred); VisitCompoundLiteralExpr(cast(S), Pred, Dst); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -141,12 +141,10 @@ SVal V = state->getSVal(LHS, LCtx); // Get the computation type. - QualType CTy = - cast(B)->getComputationResultType(); + QualType CTy = B->getComputationResultType(); CTy = getContext().getCanonicalType(CTy); - QualType CLHSTy = - cast(B)->getComputationLHSType(); + QualType CLHSTy = B->getComputationLHSType(); CLHSTy = getContext().getCanonicalType(CLHSTy); QualType LTy = getContext().getCanonicalType(LHS->getType()); diff --git a/clang/test/AST/ast-dump-expr-json.c b/clang/test/AST/ast-dump-expr-json.c --- a/clang/test/AST/ast-dump-expr-json.c +++ b/clang/test/AST/ast-dump-expr-json.c @@ -270,7 +270,6 @@ // CHECK-NEXT: ] // CHECK-NEXT: } - // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { // CHECK-NEXT: "offset": 157, @@ -417,7 +416,7 @@ // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "CompoundAssignOperator", +// CHECK-NEXT: "kind": "BinaryOperator", // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { // CHECK-NEXT: "offset": 191, @@ -529,7 +528,6 @@ // CHECK-NEXT: ] // CHECK-NEXT: } - // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { // CHECK-NEXT: "offset": 210, diff --git a/clang/test/AST/ast-dump-expr.c b/clang/test/AST/ast-dump-expr.c --- a/clang/test/AST/ast-dump-expr.c +++ b/clang/test/AST/ast-dump-expr.c @@ -16,7 +16,7 @@ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} 'int' 12 a += a; - // CHECK: CompoundAssignOperator 0x{{[^ ]*}} 'int' '+=' ComputeLHSTy='int' ComputeResultTy='int' + // CHECK: BinaryOperator 0x{{[^ ]*}} 'int' '+=' ComputeLHSTy='int' ComputeResultTy='int' // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int' diff --git a/clang/test/AST/dump.cpp b/clang/test/AST/dump.cpp --- a/clang/test/AST/dump.cpp +++ b/clang/test/AST/dump.cpp @@ -14,14 +14,14 @@ #pragma omp declare reduction(fun : float : omp_out += omp_in) initializer(omp_priv = omp_orig + 15) // CHECK: |-OMPDeclareReductionDecl {{.+}} col:35 operator+ 'int' combiner 0x{{.+}} -// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} 'int' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int' +// CHECK-NEXT: | |-BinaryOperator {{.+}} 'int' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int' // CHECK-NEXT: | | |-DeclRefExpr {{.+}} 'int' lvalue Var {{.+}} 'omp_out' 'int' // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'int' // CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'int' lvalue Var {{.+}} 'omp_in' 'int' // CHECK-NEXT: | |-VarDecl {{.+}} col:35 implicit used omp_in 'int' // CHECK-NEXT: | `-VarDecl {{.+}} col:35 implicit used omp_out 'int' // CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} col:40 operator+ 'char' combiner 0x{{.+}} -// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} 'char' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int' +// CHECK-NEXT: | |-BinaryOperator {{.+}} 'char' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int' // CHECK-NEXT: | | |-DeclRefExpr {{.+}} 'char' lvalue Var {{.+}} 'omp_out' 'char' // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'int' // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'char' @@ -29,7 +29,7 @@ // CHECK-NEXT: | |-VarDecl {{.+}} col:40 implicit used omp_in 'char' // CHECK-NEXT: | `-VarDecl {{.+}} col:40 implicit used omp_out 'char' // CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} col:37 fun 'float' combiner 0x{{.+}} initializer 0x{{.+}} -// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} 'float' lvalue '+=' ComputeLHSTy='float' ComputeResultTy='float' +// CHECK-NEXT: | |-BinaryOperator {{.+}} 'float' lvalue '+=' ComputeLHSTy='float' ComputeResultTy='float' // CHECK-NEXT: | | |-DeclRefExpr {{.+}} 'float' lvalue Var {{.+}} 'omp_out' 'float' // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'float' // CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'float' lvalue Var {{.+}} 'omp_in' 'float' diff --git a/clang/test/Import/compound-assign-op/test.cpp b/clang/test/Import/compound-assign-op/test.cpp --- a/clang/test/Import/compound-assign-op/test.cpp +++ b/clang/test/Import/compound-assign-op/test.cpp @@ -2,42 +2,42 @@ // CHECK: VarDecl // CHECK-NEXT: Integer -// CHECK-NEXT: CompoundAssignOperator +// CHECK-NEXT: BinaryOperator // CHECK-SAME: '+=' // CHECK: VarDecl // CHECK-NEXT: Integer -// CHECK-NEXT: CompoundAssignOperator +// CHECK-NEXT: BinaryOperator // CHECK-SAME: '-=' // CHECK: VarDecl // CHECK-NEXT: Integer -// CHECK-NEXT: CompoundAssignOperator +// CHECK-NEXT: BinaryOperator // CHECK-SAME: '*=' // CHECK: VarDecl // CHECK-NEXT: Integer -// CHECK-NEXT: CompoundAssignOperator +// CHECK-NEXT: BinaryOperator // CHECK-SAME: '/=' // CHECK: VarDecl // CHECK-NEXT: Integer -// CHECK-NEXT: CompoundAssignOperator +// CHECK-NEXT: BinaryOperator // CHECK-SAME: '&=' // CHECK: VarDecl // CHECK-NEXT: Integer -// CHECK-NEXT: CompoundAssignOperator +// CHECK-NEXT: BinaryOperator // CHECK-SAME: '^=' // CHECK: VarDecl // CHECK-NEXT: Integer -// CHECK-NEXT: CompoundAssignOperator +// CHECK-NEXT: BinaryOperator // CHECK-SAME: '<<=' // CHECK: VarDecl // CHECK-NEXT: Integer -// CHECK-NEXT: CompoundAssignOperator +// CHECK-NEXT: BinaryOperator // CHECK-SAME: '>>=' void expr() { diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -431,10 +431,6 @@ K = CXCursor_BinaryOperator; break; - case Stmt::CompoundAssignOperatorClass: - K = CXCursor_CompoundAssignOperator; - break; - case Stmt::ConditionalOperatorClass: K = CXCursor_ConditionalOperator; break;