mibintc updated this revision to Diff 251746. mibintc added a comment. This revision fixes the clang-tidy,clang-format and removes the redundant accessors. Ready for your review.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D76384/new/ https://reviews.llvm.org/D76384 Files: clang/include/clang/AST/Expr.h clang/include/clang/AST/ExprCXX.h clang/include/clang/AST/JSONNodeDumper.h clang/include/clang/AST/RecursiveASTVisitor.h clang/include/clang/AST/Stmt.h clang/include/clang/AST/StmtVisitor.h clang/include/clang/AST/TextNodeDumper.h clang/include/clang/Basic/LangOptions.h clang/include/clang/Basic/StmtNodes.td clang/include/clang/Serialization/ASTBitCodes.h clang/lib/AST/ASTImporter.cpp clang/lib/AST/Expr.cpp clang/lib/AST/ExprCXX.cpp clang/lib/AST/ExprClassification.cpp clang/lib/AST/ExprConstant.cpp clang/lib/AST/ItaniumMangle.cpp clang/lib/AST/JSONNodeDumper.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/StmtProfile.cpp clang/lib/AST/TextNodeDumper.cpp clang/lib/Analysis/BodyFarm.cpp clang/lib/Analysis/ReachableCode.cpp clang/lib/Analysis/ThreadSafetyCommon.cpp clang/lib/CodeGen/CGExpr.cpp clang/lib/CodeGen/CGExprComplex.cpp clang/lib/CodeGen/CGExprScalar.cpp clang/lib/CodeGen/CodeGenFunction.h clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp clang/lib/Frontend/Rewrite/RewriteObjC.cpp clang/lib/Index/IndexBody.cpp clang/lib/Sema/AnalysisBasedWarnings.cpp clang/lib/Sema/SemaAttr.cpp clang/lib/Sema/SemaChecking.cpp clang/lib/Sema/SemaExceptionSpec.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Sema/SemaOpenMP.cpp clang/lib/Sema/SemaOverload.cpp clang/lib/Sema/SemaPseudoObject.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReaderStmt.cpp clang/lib/Serialization/ASTWriter.cpp clang/lib/Serialization/ASTWriterStmt.cpp clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp clang/lib/StaticAnalyzer/Core/ExprEngine.cpp clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp clang/test/AST/ast-dump-expr-json.c clang/test/AST/ast-dump-expr.c clang/test/AST/dump.cpp clang/test/Analysis/loopexit-cfg-output.cpp clang/test/Import/compound-assign-op/test.cpp clang/test/Sema/warn-unreachable.c clang/tools/libclang/CXCursor.cpp
Index: clang/tools/libclang/CXCursor.cpp =================================================================== --- clang/tools/libclang/CXCursor.cpp +++ clang/tools/libclang/CXCursor.cpp @@ -383,10 +383,6 @@ K = CXCursor_BinaryOperator; break; - case Stmt::CompoundAssignOperatorClass: - K = CXCursor_CompoundAssignOperator; - break; - case Stmt::ConditionalOperatorClass: K = CXCursor_ConditionalOperator; break; Index: clang/test/Sema/warn-unreachable.c =================================================================== --- clang/test/Sema/warn-unreachable.c +++ clang/test/Sema/warn-unreachable.c @@ -83,9 +83,9 @@ - // expected-warning {{will never be executed}} halt(); case 8: - i - += // expected-warning {{will never be executed}} - halt(); + i // expected-warning {{will never be executed}} + += + halt(); case 9: halt() ? // expected-warning {{will never be executed}} Index: clang/test/Import/compound-assign-op/test.cpp =================================================================== --- clang/test/Import/compound-assign-op/test.cpp +++ 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() { Index: clang/test/Analysis/loopexit-cfg-output.cpp =================================================================== --- clang/test/Analysis/loopexit-cfg-output.cpp +++ clang/test/Analysis/loopexit-cfg-output.cpp @@ -208,9 +208,9 @@ // CHECK-NEXT: Succs (2): B4 B1 // CHECK: [B3] -// CHECK-NEXT: 1: j -// CHECK-NEXT: 2: 2 -// CHECK-NEXT: 3: [B3.1] += [B3.2] +// CHECK-NEXT: 1: 2 +// CHECK-NEXT: 2: j +// CHECK-NEXT: 3: [B3.2] += [B3.1] // CHECK-NEXT: Preds (2): B4 B5 // CHECK-NEXT: Succs (1): B2 Index: clang/test/AST/dump.cpp =================================================================== --- clang/test/AST/dump.cpp +++ 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 {{.+}} <line:[[@LINE-4]]:35> col:35 operator+ 'int' combiner 0x{{.+}} -// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:47, col:58> 'int' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int' +// CHECK-NEXT: | |-BinaryOperator {{.+}} <col:47, col:58> 'int' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int' // CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:47> 'int' lvalue Var {{.+}} 'omp_out' 'int' // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:58> 'int' <LValueToRValue> // CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:58> 'int' lvalue Var {{.+}} 'omp_in' 'int' // CHECK-NEXT: | |-VarDecl {{.+}} <col:35> col:35 implicit used omp_in 'int' // CHECK-NEXT: | `-VarDecl {{.+}} <col:35> col:35 implicit used omp_out 'int' // CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} <col:40> col:40 operator+ 'char' combiner 0x{{.+}} -// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:47, col:58> 'char' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int' +// CHECK-NEXT: | |-BinaryOperator {{.+}} <col:47, col:58> 'char' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int' // CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:47> 'char' lvalue Var {{.+}} 'omp_out' 'char' // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:58> 'int' <IntegralCast> // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:58> 'char' <LValueToRValue> @@ -29,7 +29,7 @@ // CHECK-NEXT: | |-VarDecl {{.+}} <col:40> col:40 implicit used omp_in 'char' // CHECK-NEXT: | `-VarDecl {{.+}} <col:40> col:40 implicit used omp_out 'char' // CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} <line:[[@LINE-17]]:37> col:37 fun 'float' combiner 0x{{.+}} initializer 0x{{.+}} -// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:45, col:56> 'float' lvalue '+=' ComputeLHSTy='float' ComputeResultTy='float' +// CHECK-NEXT: | |-BinaryOperator {{.+}} <col:45, col:56> 'float' lvalue '+=' ComputeLHSTy='float' ComputeResultTy='float' // CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:45> 'float' lvalue Var {{.+}} 'omp_out' 'float' // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:56> 'float' <LValueToRValue> // CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:56> 'float' lvalue Var {{.+}} 'omp_in' 'float' Index: clang/test/AST/ast-dump-expr.c =================================================================== --- clang/test/AST/ast-dump-expr.c +++ clang/test/AST/ast-dump-expr.c @@ -16,7 +16,7 @@ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:7> 'int' 12 a += a; - // CHECK: CompoundAssignOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'int' '+=' ComputeLHSTy='int' ComputeResultTy='int' + // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'int' '+=' ComputeLHSTy='int' ComputeResultTy='int' // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int' Index: clang/test/AST/ast-dump-expr-json.c =================================================================== --- clang/test/AST/ast-dump-expr-json.c +++ 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, Index: clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -141,12 +141,10 @@ SVal V = state->getSVal(LHS, LCtx); // Get the computation type. - QualType CTy = - cast<CompoundAssignOperator>(B)->getComputationResultType(); + QualType CTy = B->getComputationResultType(); CTy = getContext().getCanonicalType(CTy); - QualType CLHSTy = - cast<CompoundAssignOperator>(B)->getComputationLHSType(); + QualType CLHSTy = B->getComputationLHSType(); CLHSTy = getContext().getCanonicalType(CLHSTy); QualType LTy = getContext().getCanonicalType(LHS->getType()); Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1664,12 +1664,6 @@ break; } - case Stmt::CompoundAssignOperatorClass: - Bldr.takeNodes(Pred); - VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst); - Bldr.addNodes(Dst); - break; - case Stmt::CompoundLiteralExprClass: Bldr.takeNodes(Pred); VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst); Index: clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp @@ -445,7 +445,6 @@ return true; } - case Stmt::CompoundAssignOperatorClass: case Stmt::BinaryOperatorClass: { const BinaryOperator *BinOp1 = cast<BinaryOperator>(Stmt1); const BinaryOperator *BinOp2 = cast<BinaryOperator>(Stmt2); Index: clang/lib/Serialization/ASTWriterStmt.cpp =================================================================== --- clang/lib/Serialization/ASTWriterStmt.cpp +++ clang/lib/Serialization/ASTWriterStmt.cpp @@ -778,6 +778,7 @@ VisitExpr(E); Record.push_back(E->getNumArgs()); Record.AddSourceLocation(E->getRParenLoc()); + Record.push_back(E->getFPFeatures().getInt()); Record.AddStmt(E->getCallee()); for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); Arg != ArgEnd; ++Arg) @@ -868,21 +869,24 @@ 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->isCompoundAssignmentOp()); 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().getInt()); + 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()); @@ -1463,7 +1467,6 @@ void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { VisitCallExpr(E); Record.push_back(E->getOperator()); - Record.push_back(E->getFPFeatures().getInt()); Record.AddSourceRange(E->Range); Code = serialization::EXPR_CXX_OPERATOR_CALL; } Index: clang/lib/Serialization/ASTWriter.cpp =================================================================== --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -582,7 +582,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); Index: clang/lib/Serialization/ASTReaderStmt.cpp =================================================================== --- clang/lib/Serialization/ASTReaderStmt.cpp +++ clang/lib/Serialization/ASTReaderStmt.cpp @@ -915,6 +915,7 @@ unsigned NumArgs = Record.readInt(); assert((NumArgs == E->getNumArgs()) && "Wrong NumArgs!"); E->setRParenLoc(readSourceLocation()); + E->setFPFeatures(FPOptions(Record.readInt())); E->setCallee(Record.readSubExpr()); for (unsigned I = 0; I != NumArgs; ++I) E->setArg(I, Record.readSubExpr()); @@ -1006,18 +1007,23 @@ } void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) { + bool hasFP_Features; + bool isCompoundAssign; VisitExpr(E); + E->setHasFPFeatures(hasFP_Features = Record.readInt()); + E->setIsCompoundAssign(isCompoundAssign = 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 (isCompoundAssign) { + E->setComputationLHSType(Record.readType()); + E->setComputationResultType(Record.readType()); + } } void ASTStmtReader::VisitConditionalOperator(ConditionalOperator *E) { @@ -1579,7 +1585,6 @@ void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { VisitCallExpr(E); E->CXXOperatorCallExprBits.OperatorKind = Record.readInt(); - E->CXXOperatorCallExprBits.FPFeatures = Record.readInt(); E->Range = Record.readSourceRange(); } @@ -2865,11 +2870,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: Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -3384,7 +3384,8 @@ // Build the CallExpr ExprResult TheCall = CallExpr::Create( SemaRef.Context, Callee, SubExprs, Builtin->getCallResultType(), - Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc); + Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc, + FPOptions()); // Type-check the __builtin_shufflevector expression. return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.get())); @@ -10096,7 +10097,10 @@ return E; Sema::FPFeaturesStateRAII FPFeaturesState(getSema()); - getSema().FPFeatures = E->getFPFeatures(); + if (E->HasFPFeatures()) + getSema().FPFeatures = E->getFPFeatures(); + else + getSema().FPFeatures = FPOptions(); return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(), LHS.get(), RHS.get()); @@ -10147,13 +10151,6 @@ } template<typename Derived> -ExprResult -TreeTransform<Derived>::TransformCompoundAssignOperator( - CompoundAssignOperator *E) { - return getDerived().TransformBinaryOperator(E); -} - -template<typename Derived> ExprResult TreeTransform<Derived>:: TransformBinaryConditionalOperator(BinaryConditionalOperator *e) { // Just rebuild the common and RHS expressions and see whether we Index: clang/lib/Sema/SemaPseudoObject.cpp =================================================================== --- clang/lib/Sema/SemaPseudoObject.cpp +++ clang/lib/Sema/SemaPseudoObject.cpp @@ -448,11 +448,9 @@ 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()); } else { ExprResult opLHS = buildGet(); if (opLHS.isInvalid()) return ExprError(); @@ -463,14 +461,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 = BinaryOperator::Create( + S.Context, syntacticLHS, capturedRHS, opcode, result.get()->getType(), + result.get()->getValueKind(), OK_Ordinary, opLHS.get()->getType(), + result.get()->getType(), opcLoc, FPOptions()); } // The result of the assignment, if not void, is the value set into @@ -1586,9 +1580,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, FPOptions()); // Filter out non-overload placeholder types in the RHS. if (RHS->getType()->isNonOverloadPlaceholderType()) { @@ -1639,30 +1633,26 @@ /// operations. Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) { Expr *syntax = E->getSyntacticForm(); + BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax); if (UnaryOperator *uop = dyn_cast<UnaryOperator>(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<CompoundAssignOperator>(syntax)) { - Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS()); - Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr(); - return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(), - cop->getType(), - cop->getValueKind(), - cop->getObjectKind(), - cop->getComputationLHSType(), - cop->getComputationResultType(), - cop->getOperatorLoc(), - FPOptions()); - } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) { + } else if (bop && bop->isCompoundAssignmentOp()) { Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr(); - return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(), - bop->getType(), bop->getValueKind(), - bop->getObjectKind(), - bop->getOperatorLoc(), FPOptions()); + return BinaryOperator::Create( + Context, lhs, rhs, bop->getOpcode(), bop->getType(), + bop->getValueKind(), bop->getObjectKind(), bop->getComputationLHSType(), + bop->getComputationResultType(), bop->getOperatorLoc(), FPOptions()); + } else if (bop) { + Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); + Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr(); + return BinaryOperator::Create(Context, lhs, rhs, bop->getOpcode(), + bop->getType(), bop->getValueKind(), + bop->getObjectKind(), bop->getOperatorLoc(), + FPOptions()); } else { assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject)); return stripOpaqueValuesFromPseudoObjectRef(*this, syntax); Index: clang/lib/Sema/SemaOverload.cpp =================================================================== --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -12719,7 +12719,7 @@ // lookup to instantiation time to be able to search into type dependent // base classes. CallExpr *CE = CallExpr::Create(Context, Fn, Args, Context.DependentTy, - VK_RValue, RParenLoc); + VK_RValue, RParenLoc, FPFeatures); CE->markDependentForPostponedNameLookup(); *Result = CE; return true; @@ -13005,8 +13005,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(); @@ -13175,14 +13175,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, + Context.DependentTy, Context.DependentTy, + OpLoc, FPFeatures); } // FIXME: save results of ADL from here? @@ -13856,7 +13856,7 @@ if (isa<CXXPseudoDestructorExpr>(NakedMemExpr)) return CallExpr::Create(Context, MemExprE, Args, Context.VoidTy, VK_RValue, - RParenLoc); + RParenLoc, FPFeatures); UnbridgedCastsSet UnbridgedCasts; if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) @@ -14459,7 +14459,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(); Index: clang/lib/Sema/SemaOpenMP.cpp =================================================================== --- clang/lib/Sema/SemaOpenMP.cpp +++ clang/lib/Sema/SemaOpenMP.cpp @@ -9075,20 +9075,18 @@ AtomicBody = AtomicBody->IgnoreParenImpCasts(); if (AtomicBody->getType()->isScalarType() || AtomicBody->isInstantiationDependent()) { - if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>( - 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<BinaryOperator>( - AtomicBody->IgnoreParenImpCasts())) { - // Check for Binary Operation - if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId)) + if (auto *AtomicBinOp = + dyn_cast<BinaryOperator>(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<UnaryOperator>( AtomicBody->IgnoreParenImpCasts())) { // Check for Unary Operation @@ -14660,8 +14658,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, S.FPFeatures); } else { ReductionOp = S.BuildBinOp( Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, LHSDRE, RHSDRE); Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ clang/lib/Sema/SemaExprCXX.cpp @@ -6998,9 +6998,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->HasFPFeatures() ? BO->getFPFeatures() : FPOptions()); } } Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -5756,7 +5756,7 @@ } return CallExpr::Create(Context, Fn, /*Args=*/{}, Context.VoidTy, - VK_RValue, RParenLoc); + VK_RValue, RParenLoc, FPFeatures); } if (Fn->getType() == Context.PseudoObjectTy) { ExprResult result = CheckPlaceholderExpr(Fn); @@ -5778,7 +5778,7 @@ Fn->getBeginLoc()); return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, - VK_RValue, RParenLoc); + VK_RValue, RParenLoc, FPFeatures); } } @@ -5807,7 +5807,7 @@ if (!find.HasFormOfMemberPointer) { if (Expr::hasAnyTypeDependentArguments(ArgExprs)) return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, - VK_RValue, RParenLoc); + VK_RValue, RParenLoc, FPFeatures); OverloadExpr *ovl = find.Expression; if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl)) return BuildOverloadedCallExpr( @@ -6003,7 +6003,7 @@ ResultTy, VK_RValue, RParenLoc, NumParams); } else { TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, - RParenLoc, NumParams, UsesADL); + RParenLoc, FPFeatures, NumParams, UsesADL); } if (!getLangOpts().CPlusPlus) { @@ -6033,7 +6033,7 @@ RParenLoc, NumParams); else TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, - RParenLoc, NumParams, UsesADL); + RParenLoc, FPFeatures, NumParams, UsesADL); } // We can now handle the nulled arguments for the default arguments. TheCall->setNumArgsUnsafe(std::max<unsigned>(Args.size(), NumParams)); @@ -12890,13 +12890,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, BinOpResTy, BinOpResTy, OpLoc, + FPFeatures); LHS = convertVector(LHS.get(), Context.FloatTy, S); - auto *BO = new (Context) BinaryOperator(LHS.get(), RHS.get(), Opc, BinOpResTy, - VK, OK, OpLoc, FPFeatures); + auto *BO = BinaryOperator::Create(Context, LHS.get(), RHS.get(), Opc, + BinOpResTy, VK, OK, OpLoc, FPFeatures); return convertVector(BO, ResultTy->castAs<VectorType>()->getElementType(), S); } @@ -13210,8 +13210,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. @@ -13225,9 +13225,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, CompLHSTy, CompResultTy, OpLoc, + FPFeatures); } /// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison @@ -18320,7 +18323,7 @@ CK_BuiltinFnToFnPtr) .get(); return CallExpr::Create(Context, E, /*Args=*/{}, Context.IntTy, - VK_RValue, SourceLocation()); + VK_RValue, SourceLocation(), FPFeatures); } } Index: clang/lib/Sema/SemaExceptionSpec.cpp =================================================================== --- clang/lib/Sema/SemaExceptionSpec.cpp +++ clang/lib/Sema/SemaExceptionSpec.cpp @@ -1301,7 +1301,6 @@ case Expr::OMPArraySectionExprClass: case Expr::BinaryOperatorClass: case Expr::DependentCoawaitExprClass: - case Expr::CompoundAssignOperatorClass: case Expr::CStyleCastExprClass: case Expr::CXXStaticCastExprClass: case Expr::CXXFunctionalCastExprClass: Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -10853,7 +10853,8 @@ /// Analyze the given compound assignment for the possible losing of /// floating-point precision. static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) { - assert(isa<CompoundAssignOperator>(E) && + + assert(E->isCompoundAssignmentOp() && "Must be compound assignment operation"); // Recurse on the LHS and RHS in here AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); @@ -10864,9 +10865,7 @@ // Now check the outermost expression const auto *ResultBT = E->getLHS()->getType()->getAs<BuiltinType>(); - const auto *RBT = cast<CompoundAssignOperator>(E) - ->getComputationResultType() - ->getAs<BuiltinType>(); + const auto *RBT = E->getComputationResultType()->getAs<BuiltinType>(); // The below checks assume source is floating point. if (!ResultBT || !RBT || !RBT->isFloatingPoint()) return; @@ -11722,7 +11721,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); } @@ -12529,7 +12528,7 @@ Region = LHSRegion; Visit(BO->getLHS()); - if (O && isa<CompoundAssignOperator>(BO)) + if (O && BO->isCompoundAssignmentOp()) notePostUse(O, BO); } else { @@ -12537,7 +12536,7 @@ Region = LHSRegion; Visit(BO->getLHS()); - if (O && isa<CompoundAssignOperator>(BO)) + if (O && BO->isCompoundAssignmentOp()) notePostUse(O, BO); Region = RHSRegion; @@ -12559,10 +12558,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) { Index: clang/lib/Sema/SemaAttr.cpp =================================================================== --- clang/lib/Sema/SemaAttr.cpp +++ clang/lib/Sema/SemaAttr.cpp @@ -930,12 +930,15 @@ switch (FPC) { case LangOptions::FPC_On: FPFeatures.setAllowFPContractWithinStatement(); + FPFeatures.setHasPragmaFPFeatures(); break; case LangOptions::FPC_Fast: FPFeatures.setAllowFPContractAcrossStatement(); + FPFeatures.setHasPragmaFPFeatures(); break; case LangOptions::FPC_Off: FPFeatures.setDisallowFPContract(); + FPFeatures.setHasPragmaFPFeatures(); break; } } Index: clang/lib/Sema/AnalysisBasedWarnings.cpp =================================================================== --- clang/lib/Sema/AnalysisBasedWarnings.cpp +++ 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) Index: clang/lib/Index/IndexBody.cpp =================================================================== --- clang/lib/Index/IndexBody.cpp +++ clang/lib/Index/IndexBody.cpp @@ -75,6 +75,10 @@ if (auto BO = dyn_cast<BinaryOperator>(Parent)) { if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E) Roles |= (unsigned)SymbolRole::Write; + if (BO->isCompoundAssignmentOp()) { + Roles |= (unsigned)SymbolRole::Read; + Roles |= (unsigned)SymbolRole::Write; + } } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) { if (UO->isIncrementDecrementOp()) { @@ -84,12 +88,6 @@ Roles |= (unsigned)SymbolRole::AddressOf; } - } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) { - if (CA->getLHS()->IgnoreParenCasts() == E) { - Roles |= (unsigned)SymbolRole::Read; - Roles |= (unsigned)SymbolRole::Write; - } - } else if (auto CE = dyn_cast<CallExpr>(Parent)) { if (CE->getCallee()->IgnoreParenCasts() == E) { addCallRole(Roles, Relations); Index: clang/lib/Frontend/Rewrite/RewriteObjC.cpp =================================================================== --- clang/lib/Frontend/Rewrite/RewriteObjC.cpp +++ clang/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -2026,8 +2026,9 @@ const auto *FT = msgSendType->castAs<FunctionType>(); - 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, FPOptions()); return Exp; } @@ -2613,7 +2614,7 @@ const auto *FT = msgSendType->castAs<FunctionType>(); CallExpr *STCE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), - VK_RValue, SourceLocation()); + VK_RValue, SourceLocation(), FPOptions()); return STCE; } @@ -2706,7 +2707,7 @@ DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType, VK_LValue, SourceLocation()); SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType, - VK_LValue, SourceLocation()); + VK_LValue, SourceLocation(), FPOptions()); // The code for super is a little tricky to prevent collision with // the structure definition in the header. The rewriter has it's own // internal definition (__rw_objc_super) that is uses. This is why @@ -2801,7 +2802,7 @@ DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType, VK_LValue, SourceLocation()); SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType, - VK_LValue, SourceLocation()); + VK_LValue, SourceLocation(), FPOptions()); // The code for super is a little tricky to prevent collision with // the structure definition in the header. The rewriter has it's own // internal definition (__rw_objc_super) that is uses. This is why @@ -2966,7 +2967,7 @@ const auto *FT = msgSendType->castAs<FunctionType>(); CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), - VK_RValue, EndLoc); + VK_RValue, EndLoc, FPOptions()); Stmt *ReplacingStmt = CE; if (MsgSendStretFlavor) { // We have the method which returns a struct/union. Must also generate @@ -3816,7 +3817,7 @@ BlkExprs.push_back(*I); } CallExpr *CE = CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), - VK_RValue, SourceLocation()); + VK_RValue, SourceLocation(), FPOptions()); return CE; } @@ -4526,7 +4527,7 @@ InitExprs.push_back(FlagExp); } NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue, - SourceLocation()); + SourceLocation(), FPOptions()); NewRep = new (Context) UnaryOperator( NewRep, UO_AddrOf, Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary, SourceLocation(), false); Index: clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp =================================================================== --- clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -2108,8 +2108,9 @@ DRE, nullptr, VK_RValue); const auto *FT = msgSendType->castAs<FunctionType>(); - 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, FPOptions()); return Exp; } @@ -2690,7 +2691,7 @@ auto *FT = msgSendType->castAs<FunctionType>(); CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), - VK_RValue, EndLoc); + VK_RValue, EndLoc, FPOptions()); ReplaceStmt(Exp, CE); return CE; } @@ -2730,7 +2731,7 @@ InitExprs.push_back(Exp->getElement(i)); Expr *NSArrayCallExpr = CallExpr::Create(*Context, NSArrayDRE, InitExprs, NSArrayFType, VK_LValue, - SourceLocation()); + SourceLocation(), FPOptions()); FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(), @@ -2811,7 +2812,7 @@ const FunctionType *FT = msgSendType->castAs<FunctionType>(); CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), - VK_RValue, EndLoc); + VK_RValue, EndLoc, FPOptions()); ReplaceStmt(Exp, CE); return CE; } @@ -2859,7 +2860,7 @@ // (const id [])objects Expr *NSValueCallExpr = CallExpr::Create(*Context, NSDictDRE, ValueExprs, NSDictFType, VK_LValue, - SourceLocation()); + SourceLocation(), FPOptions()); FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(), @@ -2877,8 +2878,9 @@ CK_BitCast, DictLiteralValueME); // (const id <NSCopying> [])keys - Expr *NSKeyCallExpr = CallExpr::Create( - *Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue, SourceLocation()); + Expr *NSKeyCallExpr = + CallExpr::Create(*Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue, + SourceLocation(), FPOptions()); MemberExpr *DictLiteralKeyME = MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD, @@ -2962,7 +2964,7 @@ const FunctionType *FT = msgSendType->castAs<FunctionType>(); CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), - VK_RValue, EndLoc); + VK_RValue, EndLoc, FPOptions()); ReplaceStmt(Exp, CE); return CE; } @@ -3174,7 +3176,7 @@ DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, castType, VK_RValue, SourceLocation()); CallExpr *STCE = CallExpr::Create(*Context, DRE, MsgExprs, castType, - VK_LValue, SourceLocation()); + VK_LValue, SourceLocation(), FPOptions()); FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(), @@ -3275,7 +3277,7 @@ DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType, VK_LValue, SourceLocation()); SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType, - VK_LValue, SourceLocation()); + VK_LValue, SourceLocation(), FPOptions()); // The code for super is a little tricky to prevent collision with // the structure definition in the header. The rewriter has it's own // internal definition (__rw_objc_super) that is uses. This is why @@ -3370,7 +3372,7 @@ DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType, VK_LValue, SourceLocation()); SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType, - VK_LValue, SourceLocation()); + VK_LValue, SourceLocation(), FPOptions()); // The code for super is a little tricky to prevent collision with // the structure definition in the header. The rewriter has it's own // internal definition (__rw_objc_super) that is uses. This is why @@ -3535,7 +3537,7 @@ const FunctionType *FT = msgSendType->castAs<FunctionType>(); CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), - VK_RValue, EndLoc); + VK_RValue, EndLoc, FPOptions()); Stmt *ReplacingStmt = CE; if (MsgSendStretFlavor) { // We have the method which returns a struct/union. Must also generate @@ -4646,7 +4648,7 @@ BlkExprs.push_back(*I); } CallExpr *CE = CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), - VK_RValue, SourceLocation()); + VK_RValue, SourceLocation(), FPOptions()); return CE; } @@ -5388,7 +5390,7 @@ InitExprs.push_back(FlagExp); } NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue, - SourceLocation()); + SourceLocation(), FPOptions()); if (GlobalBlockExpr) { assert (!GlobalConstructionExp && Index: clang/lib/CodeGen/CodeGenFunction.h =================================================================== --- clang/lib/CodeGen/CodeGenFunction.h +++ 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 Index: clang/lib/CodeGen/CGExprScalar.cpp =================================================================== --- clang/lib/CodeGen/CGExprScalar.cpp +++ clang/lib/CodeGen/CGExprScalar.cpp @@ -91,6 +91,7 @@ Value *RHS; QualType Ty; // Computation Type. BinaryOperator::Opcode Opcode; // Opcode of BinOp to perform + bool HasFPFeatures; FPOptions FPFeatures; const Expr *E; // Entire expr, for error unsupported. May not be binop. @@ -777,20 +778,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 +2899,18 @@ Result.RHS = Visit(E->getRHS()); Result.Ty = E->getType(); Result.Opcode = E->getOpcode(); - Result.FPFeatures = E->getFPFeatures(); + Result.HasFPFeatures = E->HasFPFeatures(); + if (Result.HasFPFeatures) + Result.FPFeatures = E->getFPFeatures(); + else + Result.FPFeatures = FPOptions(CGF.getLangOpts()); 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 +2922,11 @@ OpInfo.RHS = Visit(E->getRHS()); OpInfo.Ty = E->getComputationResultType(); OpInfo.Opcode = E->getOpcode(); - OpInfo.FPFeatures = E->getFPFeatures(); + OpInfo.HasFPFeatures = E->HasFPFeatures(); + if (OpInfo.HasFPFeatures) + OpInfo.FPFeatures = E->getFPFeatures(); + else + OpInfo.FPFeatures = FPOptions(CGF.getLangOpts()); OpInfo.E = E; // Load/convert the LHS. LValue LHSLV = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store); @@ -3032,8 +3041,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 +4633,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()) { Index: clang/lib/CodeGen/CGExprComplex.cpp =================================================================== --- clang/lib/CodeGen/CGExprComplex.cpp +++ 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); Index: clang/lib/CodeGen/CGExpr.cpp =================================================================== --- clang/lib/CodeGen/CGExpr.cpp +++ clang/lib/CodeGen/CGExpr.cpp @@ -1271,15 +1271,17 @@ return EmitObjCSelectorLValue(cast<ObjCSelectorExpr>(E)); case Expr::ObjCIsaExprClass: return EmitObjCIsaExpr(cast<ObjCIsaExpr>(E)); - case Expr::BinaryOperatorClass: - return EmitBinaryOperatorLValue(cast<BinaryOperator>(E)); - case Expr::CompoundAssignOperatorClass: { - QualType Ty = E->getType(); - if (const AtomicType *AT = Ty->getAs<AtomicType>()) - Ty = AT->getValueType(); - if (!Ty->isAnyComplexType()) - return EmitCompoundAssignmentLValue(cast<CompoundAssignOperator>(E)); - return EmitComplexCompoundAssignmentLValue(cast<CompoundAssignOperator>(E)); + case Expr::BinaryOperatorClass: { + const auto BO = cast<BinaryOperator>(E); + if (BO->isCompoundAssignmentOp()) { + QualType Ty = BO->getType(); + if (const AtomicType *AT = Ty->getAs<AtomicType>()) + Ty = AT->getValueType(); + if (!Ty->isAnyComplexType()) + return EmitCompoundAssignmentLValue(BO); + return EmitComplexCompoundAssignmentLValue(BO); + } + return EmitBinaryOperatorLValue(BO); } case Expr::CallExprClass: case Expr::CXXMemberCallExprClass: Index: clang/lib/Analysis/ThreadSafetyCommon.cpp =================================================================== --- clang/lib/Analysis/ThreadSafetyCommon.cpp +++ clang/lib/Analysis/ThreadSafetyCommon.cpp @@ -222,7 +222,6 @@ case Stmt::UnaryOperatorClass: return translateUnaryOperator(cast<UnaryOperator>(S), Ctx); case Stmt::BinaryOperatorClass: - case Stmt::CompoundAssignOperatorClass: return translateBinaryOperator(cast<BinaryOperator>(S), Ctx); case Stmt::ArraySubscriptExprClass: Index: clang/lib/Analysis/ReachableCode.cpp =================================================================== --- clang/lib/Analysis/ReachableCode.cpp +++ clang/lib/Analysis/ReachableCode.cpp @@ -561,12 +561,6 @@ R1 = UO->getSubExpr()->getSourceRange(); return UO->getOperatorLoc(); } - case Expr::CompoundAssignOperatorClass: { - const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S); - R1 = CAO->getLHS()->getSourceRange(); - R2 = CAO->getRHS()->getSourceRange(); - return CAO->getOperatorLoc(); - } case Expr::BinaryConditionalOperatorClass: case Expr::ConditionalOperatorClass: { const AbstractConditionalOperator *CO = Index: clang/lib/Analysis/BodyFarm.cpp =================================================================== --- clang/lib/Analysis/BodyFarm.cpp +++ clang/lib/Analysis/BodyFarm.cpp @@ -114,20 +114,18 @@ BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty) { - return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS), - BO_Assign, Ty, VK_RValue, - OK_Ordinary, SourceLocation(), FPOptions()); + return BinaryOperator::Create( + C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), BO_Assign, Ty, + VK_RValue, OK_Ordinary, SourceLocation(), FPOptions()); } BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS, BinaryOperator::Opcode Op) { assert(BinaryOperator::isLogicalOp(Op) || BinaryOperator::isComparisonOp(Op)); - return new (C) BinaryOperator(const_cast<Expr*>(LHS), - const_cast<Expr*>(RHS), - Op, - C.getLogicalOperationType(), - VK_RValue, + return BinaryOperator::Create(C, const_cast<Expr *>(LHS), + const_cast<Expr *>(RHS), Op, + C.getLogicalOperationType(), VK_RValue, OK_Ordinary, SourceLocation(), FPOptions()); } @@ -269,7 +267,7 @@ } return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_RValue, - SourceLocation()); + SourceLocation(), FPOptions()); } static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M, @@ -514,7 +512,7 @@ /*Args=*/None, /*QualType=*/C.VoidTy, /*ExprValueType=*/VK_RValue, - /*SourceLocation=*/SourceLocation()); + /*SourceLocation=*/SourceLocation(), FPOptions()); // (2) Create the assignment to the predicate. Expr *DoneValue = @@ -578,8 +576,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(), FPOptions()); return CE; } Index: clang/lib/AST/TextNodeDumper.cpp =================================================================== --- clang/lib/AST/TextNodeDumper.cpp +++ 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) { Index: clang/lib/AST/StmtProfile.cpp =================================================================== --- clang/lib/AST/StmtProfile.cpp +++ clang/lib/AST/StmtProfile.cpp @@ -1231,11 +1231,6 @@ ID.AddInteger(S->getOpcode()); } -void -StmtProfiler::VisitCompoundAssignOperator(const CompoundAssignOperator *S) { - VisitBinaryOperator(S); -} - void StmtProfiler::VisitConditionalOperator(const ConditionalOperator *S) { VisitExpr(S); } @@ -1504,35 +1499,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; @@ -1544,11 +1539,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; @@ -1635,8 +1630,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); Index: clang/lib/AST/StmtPrinter.cpp =================================================================== --- clang/lib/AST/StmtPrinter.cpp +++ clang/lib/AST/StmtPrinter.cpp @@ -1437,12 +1437,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 << " ? "; Index: clang/lib/AST/JSONNodeDumper.cpp =================================================================== --- clang/lib/AST/JSONNodeDumper.cpp +++ 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) { Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -4127,7 +4127,6 @@ break; } - case Expr::CompoundAssignOperatorClass: // fallthrough case Expr::BinaryOperatorClass: { const BinaryOperator *BO = cast<BinaryOperator>(E); if (BO->getOpcode() == BO_PtrMemD) Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -7480,7 +7480,6 @@ return VisitUnaryPreIncDec(UO); } bool VisitBinAssign(const BinaryOperator *BO); - bool VisitCompoundAssignOperator(const CompoundAssignOperator *CAO); bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { @@ -7781,32 +7780,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; @@ -14155,7 +14150,6 @@ case Expr::ArraySubscriptExprClass: case Expr::OMPArraySectionExprClass: case Expr::MemberExprClass: - case Expr::CompoundAssignOperatorClass: case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: case Expr::DesignatedInitExprClass: Index: clang/lib/AST/ExprClassification.cpp =================================================================== --- clang/lib/AST/ExprClassification.cpp +++ clang/lib/AST/ExprClassification.cpp @@ -295,7 +295,6 @@ return ClassifyInternal(Ctx,cast<GenericSelectionExpr>(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<BinaryOperator>(E)); Index: clang/lib/AST/ExprCXX.cpp =================================================================== --- clang/lib/AST/ExprCXX.cpp +++ clang/lib/AST/ExprCXX.cpp @@ -528,14 +528,11 @@ FPOptions FPFeatures, ADLCallKind UsesADL) : CallExpr(CXXOperatorCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, - OperatorLoc, /*MinNumArgs=*/0, UsesADL) { + OperatorLoc, FPFeatures, /*MinNumArgs=*/0, UsesADL) { CXXOperatorCallExprBits.OperatorKind = OpKind; - CXXOperatorCallExprBits.FPFeatures = FPFeatures.getInt(); assert( (CXXOperatorCallExprBits.OperatorKind == static_cast<unsigned>(OpKind)) && "OperatorKind overflow!"); - assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getInt()) && - "FPFeatures overflow!"); Range = getSourceRangeImpl(); } @@ -595,7 +592,7 @@ QualType Ty, ExprValueKind VK, SourceLocation RP, unsigned MinNumArgs) : CallExpr(CXXMemberCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, RP, - MinNumArgs, NotADL) {} + FPOptions(), MinNumArgs, NotADL) {} CXXMemberCallExpr::CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty) : CallExpr(CXXMemberCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {} @@ -834,7 +831,7 @@ SourceLocation LitEndLoc, SourceLocation SuffixLoc) : CallExpr(UserDefinedLiteralClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, - LitEndLoc, /*MinNumArgs=*/0, NotADL), + LitEndLoc, FPOptions(), /*MinNumArgs=*/0, NotADL), UDSuffixLoc(SuffixLoc) {} UserDefinedLiteral::UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty) @@ -1611,7 +1608,7 @@ ExprValueKind VK, SourceLocation RP, unsigned MinNumArgs) : CallExpr(CUDAKernelCallExprClass, Fn, /*PreArgs=*/Config, Args, Ty, VK, - RP, MinNumArgs, NotADL) {} + RP, FPOptions(), MinNumArgs, NotADL) {} CUDAKernelCallExpr::CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty) : CallExpr(CUDAKernelCallExprClass, /*NumPreArgs=*/END_PREARG, NumArgs, Index: clang/lib/AST/Expr.cpp =================================================================== --- clang/lib/AST/Expr.cpp +++ clang/lib/AST/Expr.cpp @@ -1221,11 +1221,12 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs, ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, - SourceLocation RParenLoc, unsigned MinNumArgs, - ADLCallKind UsesADL) + SourceLocation RParenLoc, FPOptions FP_Features, + unsigned MinNumArgs, ADLCallKind UsesADL) : Expr(SC, Ty, VK, OK_Ordinary), RParenLoc(RParenLoc) { NumArgs = std::max<unsigned>(Args.size(), MinNumArgs); unsigned NumPreArgs = PreArgs.size(); + FPFeatures = FP_Features; CallExprBits.NumPreArgs = NumPreArgs; assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!"); @@ -1261,15 +1262,15 @@ CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, - SourceLocation RParenLoc, unsigned MinNumArgs, - ADLCallKind UsesADL) { + SourceLocation RParenLoc, FPOptions FP_Features, + unsigned MinNumArgs, ADLCallKind UsesADL) { unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs); unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); void *Mem = Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, alignof(CallExpr)); return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, - RParenLoc, MinNumArgs, UsesADL); + RParenLoc, FP_Features, MinNumArgs, UsesADL); } CallExpr *CallExpr::CreateTemporary(void *Mem, Expr *Fn, QualType Ty, @@ -1277,8 +1278,9 @@ ADLCallKind UsesADL) { assert(!(reinterpret_cast<uintptr_t>(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, FPOptions(), /*MinNumArgs=*/0, UsesADL); } CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, @@ -2283,7 +2285,6 @@ R2 = BO->getRHS()->getSourceRange(); return true; } - case CompoundAssignOperatorClass: case VAArgExprClass: case AtomicExprClass: return false; @@ -3293,7 +3294,6 @@ case MSPropertyRefExprClass: case MSPropertySubscriptExprClass: - case CompoundAssignOperatorClass: case VAArgExprClass: case AtomicExprClass: case CXXThrowExprClass: @@ -4263,6 +4263,44 @@ 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) { + bool hasFPFeatures = FPFeatures.hasPragmaFPFeatures(); + unsigned SizeOfTrailingObjects = + BinaryOperator::sizeOfTrailingObjects(hasFPFeatures, 0); + void *Mem = C.Allocate(sizeof(BinaryOperator) + SizeOfTrailingObjects, + alignof(BinaryOperator)); + return new (Mem) + BinaryOperator(lhs, rhs, opc, ResTy, VK, OK, opLoc, FPFeatures); +} + +BinaryOperator * +BinaryOperator::Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, + QualType ResTy, ExprValueKind VK, ExprObjectKind OK, + QualType CompLHSType, QualType CompResultType, + SourceLocation opLoc, FPOptions FPFeatures) { + bool hasFPFeatures = FPFeatures.hasPragmaFPFeatures(); + unsigned SizeOfTrailingObjects = + BinaryOperator::sizeOfTrailingObjects(hasFPFeatures, 1); + void *Mem = C.Allocate(sizeof(BinaryOperator) + SizeOfTrailingObjects, + alignof(BinaryOperator)); + return new (Mem) BinaryOperator(lhs, rhs, opc, ResTy, VK, OK, CompLHSType, + CompResultType, opLoc, FPFeatures); +} + const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e)) e = ewc->getSubExpr(); Index: clang/lib/AST/ASTImporter.cpp =================================================================== --- clang/lib/AST/ASTImporter.cpp +++ 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); @@ -6685,12 +6684,26 @@ auto ToRHS = importChecked(Err, E->getRHS()); auto ToType = importChecked(Err, E->getType()); auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); + auto HasFPFeatures = E->HasFPFeatures(); 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()) { + auto ToComputationLHSType = importChecked(Err, E->getComputationLHSType()); + auto ToComputationResultType = + importChecked(Err, E->getComputationResultType()); + if (Err) + return std::move(Err); + return BinaryOperator::Create( + Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType, + E->getValueKind(), E->getObjectKind(), ToComputationLHSType, + ToComputationResultType, ToOperatorLoc, + HasFPFeatures ? E->getFPFeatures() : FPOptions()); + } + return BinaryOperator::Create( + Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType, + E->getValueKind(), E->getObjectKind(), ToOperatorLoc, + HasFPFeatures ? E->getFPFeatures() : FPOptions()); } ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) { @@ -6785,25 +6798,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<CXXCastPath> ASTNodeImporter::ImportCastPath(CastExpr *CE) { CXXCastPath Path; @@ -7555,8 +7549,8 @@ } return CallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, ToType, - E->getValueKind(), ToRParenLoc, /*MinNumArgs=*/0, - E->getADLCallKind()); + E->getValueKind(), ToRParenLoc, FPOptions(), + /*MinNumArgs=*/0, E->getADLCallKind()); } ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) { Index: clang/include/clang/Serialization/ASTBitCodes.h =================================================================== --- clang/include/clang/Serialization/ASTBitCodes.h +++ clang/include/clang/Serialization/ASTBitCodes.h @@ -1556,9 +1556,6 @@ /// A BinaryOperator record. EXPR_BINARY_OPERATOR, - /// A CompoundAssignOperator record. - EXPR_COMPOUND_ASSIGN_OPERATOR, - /// A ConditionOperator record. EXPR_CONDITIONAL_OPERATOR, Index: clang/include/clang/Basic/StmtNodes.td =================================================================== --- clang/include/clang/Basic/StmtNodes.td +++ clang/include/clang/Basic/StmtNodes.td @@ -74,7 +74,6 @@ def MemberExpr : StmtNode<Expr>; def CastExpr : StmtNode<Expr, 1>; def BinaryOperator : StmtNode<Expr>; -def CompoundAssignOperator : StmtNode<BinaryOperator>; def AbstractConditionalOperator : StmtNode<Expr, 1>; def ConditionalOperator : StmtNode<AbstractConditionalOperator>; def BinaryConditionalOperator : StmtNode<AbstractConditionalOperator>; Index: clang/include/clang/Basic/LangOptions.h =================================================================== --- clang/include/clang/Basic/LangOptions.h +++ clang/include/clang/Basic/LangOptions.h @@ -356,28 +356,31 @@ /// 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), has_pragma_features(0) {} // Used for serializing. explicit FPOptions(unsigned I) : fp_contract(static_cast<LangOptions::FPContractModeKind>(I & 3)), fenv_access(static_cast<LangOptions::FEnvAccessModeKind>((I >> 2) & 1)), rounding(static_cast<LangOptions::FPRoundingModeKind>((I >> 3) & 7)), - exceptions(static_cast<LangOptions::FPExceptionModeKind>((I >> 6) & 3)) - {} + exceptions(static_cast<LangOptions::FPExceptionModeKind>((I >> 6) & 3)), + has_pragma_features((I >> 7) & 1) {} 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), has_pragma_features(0) {} // FIXME: Use getDefaultFEnvAccessMode() when available. + bool hasPragmaFPFeatures() const { + return has_pragma_features; + ; + } + void setHasPragmaFPFeatures(bool B = true) { has_pragma_features = B; } + bool allowFPContractWithinStatement() const { return fp_contract == LangOptions::FPC_On; } @@ -430,8 +433,8 @@ /// Used to serialize this. unsigned getInt() const { - return fp_contract | (fenv_access << 2) | (rounding << 3) - | (exceptions << 6); + return fp_contract | (fenv_access << 2) | (rounding << 3) | + (exceptions << 6) | (has_pragma_features << 7); } private: @@ -442,6 +445,7 @@ unsigned fenv_access : 1; unsigned rounding : 3; unsigned exceptions : 2; + unsigned has_pragma_features : 1; }; /// Describes the kind of translation unit being processed. Index: clang/include/clang/AST/TextNodeDumper.h =================================================================== --- clang/include/clang/AST/TextNodeDumper.h +++ 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); Index: clang/include/clang/AST/StmtVisitor.h =================================================================== --- clang/include/clang/AST/StmtVisitor.h +++ clang/include/clang/AST/StmtVisitor.h @@ -70,16 +70,26 @@ 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<UnaryOperator>(S)) { @@ -141,9 +151,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) Index: clang/include/clang/AST/Stmt.h =================================================================== --- clang/include/clang/AST/Stmt.h +++ clang/include/clang/AST/Stmt.h @@ -523,10 +523,6 @@ unsigned Opc : 6; - /// This is only meaningful for operations on floating point - /// types and 0 otherwise. - unsigned FPFeatures : 8; - SourceLocation OpLoc; }; @@ -606,9 +602,6 @@ /// The kind of this overloaded operator. One of the enumerator /// value of OverloadedOperatorKind. unsigned OperatorKind : 6; - - // Only meaningful for floating point types. - unsigned FPFeatures : 8; }; class CXXRewrittenBinaryOperatorBitfields { Index: clang/include/clang/AST/RecursiveASTVisitor.h =================================================================== --- clang/include/clang/AST/RecursiveASTVisitor.h +++ 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 @@ -2676,7 +2676,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, {}) Index: clang/include/clang/AST/JSONNodeDumper.h =================================================================== --- clang/include/clang/AST/JSONNodeDumper.h +++ 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); Index: clang/include/clang/AST/ExprCXX.h =================================================================== --- clang/include/clang/AST/ExprCXX.h +++ clang/include/clang/AST/ExprCXX.h @@ -162,21 +162,6 @@ static bool classof(const Stmt *T) { return T->getStmtClass() == CXXOperatorCallExprClass; } - - // Set the FP contractability status of this operator. Only meaningful for - // operations on floating point types. - void setFPFeatures(FPOptions F) { - CXXOperatorCallExprBits.FPFeatures = F.getInt(); - } - FPOptions getFPFeatures() const { - return FPOptions(CXXOperatorCallExprBits.FPFeatures); - } - - // Get the FP contractability status of this operator. Only meaningful for - // operations on floating point types. - bool isFPContractableWithinStatement() const { - return getFPFeatures().allowFPContractWithinStatement(); - } }; /// Represents a call to a member function that Index: clang/include/clang/AST/Expr.h =================================================================== --- clang/include/clang/AST/Expr.h +++ clang/include/clang/AST/Expr.h @@ -2567,12 +2567,15 @@ static constexpr ADLCallKind NotADL = ADLCallKind::NotADL; static constexpr ADLCallKind UsesADL = ADLCallKind::UsesADL; + FPOptions FPFeatures; + protected: /// Build a call expression, assuming that appropriate storage has been /// allocated for the trailing objects. CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs, ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, - SourceLocation RParenLoc, unsigned MinNumArgs, ADLCallKind UsesADL); + SourceLocation RParenLoc, FPOptions FP_Features, unsigned MinNumArgs, + ADLCallKind UsesADL); /// Build an empty call expression, for deserialization. CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs, @@ -2614,7 +2617,8 @@ /// expression on the stack. static CallExpr *Create(const ASTContext &Ctx, Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, - SourceLocation RParenLoc, unsigned MinNumArgs = 0, + SourceLocation RParenLoc, FPOptions FP_Features, + unsigned MinNumArgs = 0, ADLCallKind UsesADL = NotADL); /// Create a temporary call expression with no arguments in the memory @@ -2658,6 +2662,17 @@ return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); } + // Set the FPFeatures status of this CallExpr. Only meaningful for + // operations on floating point types. e.g. intrinsics + void setFPFeatures(FPOptions F) { FPFeatures = F; } + FPOptions getFPFeatures() const { return FPFeatures; } + + // Get the FP contractability status of this CallExpr. Only meaningful for + // operations on floating point types. e.g. intrinsics + bool isFPContractableWithinStatement() const { + return FPFeatures.allowFPContractWithinStatement(); + } + /// getNumArgs - Return the number of actual arguments to this call. unsigned getNumArgs() const { return NumArgs; } @@ -3394,9 +3409,26 @@ /// 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<BinaryOperator, unsigned, QualType> { enum { LHS, RHS, END_EXPR }; Stmt *SubExprs[END_EXPR]; + bool hasFPFeatures; + bool isCompoundAssign; + + /// 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<unsigned>) const { + return hasFPFeatures ? 1 : 0; + } + unsigned numTrailingObjects(OverloadToken<QualType>) const { + return isCompoundAssign ? 2 : 0; + } public: typedef BinaryOperatorKind Opcode; @@ -3406,18 +3438,37 @@ FPOptions FPFeatures) : Expr(BinaryOperatorClass, ResTy, VK, OK) { BinaryOperatorBits.Opc = opc; - BinaryOperatorBits.FPFeatures = FPFeatures.getInt(); BinaryOperatorBits.OpLoc = opLoc; + hasFPFeatures = FPFeatures.hasPragmaFPFeatures(); + isCompoundAssign = 0; + if (hasFPFeatures) { + *getTrailingObjects<unsigned>() = FPFeatures.getInt(); + } SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; assert(!isCompoundAssignmentOp() && - "Use CompoundAssignOperator for compound assignments"); + "Use BinaryOperator for compound assignments"); setDependence(computeDependence(this)); } - - /// Construct an empty binary operator. - explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty) { - BinaryOperatorBits.Opc = BO_Comma; + BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, + ExprValueKind VK, ExprObjectKind OK, QualType CompLHSType, + QualType CompResultType, SourceLocation opLoc, + FPOptions FPFeatures) + : Expr(BinaryOperatorClass, ResTy, VK, OK) { + BinaryOperatorBits.Opc = opc; + BinaryOperatorBits.OpLoc = opLoc; + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + hasFPFeatures = FPFeatures.hasPragmaFPFeatures(); + isCompoundAssign = 1; + if (hasFPFeatures) { + *getTrailingObjects<unsigned>() = FPFeatures.getInt(); + } + assert(isCompoundAssignmentOp() && + "Expected CompoundAssignOperator for compound assignments"); + setComputationLHSType(CompLHSType); + setComputationResultType(CompResultType); + setDependence(computeDependence(this)); } SourceLocation getExprLoc() const { return getOperatorLoc(); } @@ -3548,8 +3599,7 @@ Expr *LHS, Expr *RHS); static bool classof(const Stmt *S) { - return S->getStmtClass() >= firstBinaryOperatorConstant && - S->getStmtClass() <= lastBinaryOperatorConstant; + return S->getStmtClass() == BinaryOperatorClass; } // Iterators @@ -3563,11 +3613,40 @@ // 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<unsigned>() = F.getInt(); } + 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); + static BinaryOperator *Create(const ASTContext &C, Expr *lhs, Expr *rhs, + Opcode opc, QualType ResTy, ExprValueKind VK, + ExprObjectKind OK, QualType CompLHSType, + QualType CompResultType, SourceLocation opLoc, + FPOptions FPFeatures); + + unsigned getFPFeat() const { + assert(HasFPFeatures()); + return *getTrailingObjects<unsigned>(); + } + unsigned getFPFeat() { + assert(HasFPFeatures()); + return *getTrailingObjects<unsigned>(); + } + + void setIsCompoundAssign(bool B) { isCompoundAssign = B; } + bool IsCompoundAssign() const { return isCompoundAssign; } + + void setHasFPFeatures(bool B) { hasFPFeatures = B; } + bool HasFPFeatures() const { return hasFPFeatures; } FPOptions getFPFeatures() const { - return FPOptions(BinaryOperatorBits.FPFeatures); + assert(HasFPFeatures()); + return FPOptions(*getTrailingObjects<unsigned>()); } // Get the FP contractability status of this operator. Only meaningful for @@ -3580,62 +3659,37 @@ // operations on floating point types. bool isFEnvAccessOn() const { return getFPFeatures().allowFEnvAccess(); } + QualType getComputationLHSType() const { + return getTrailingObjects<QualType>()[0]; + } + void setComputationLHSType(QualType T) { + getTrailingObjects<QualType>()[0] = T; + } + QualType getComputationResultType() const { + return getTrailingObjects<QualType>()[1]; + } + void setComputationResultType(QualType T) { + getTrailingObjects<QualType>()[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; } + friend TrailingObjects; }; /// AbstractConditionalOperator - An abstract base class for
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits