Index: clang/lib/AST/Interp/ByteCodeExprGen.h =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.h +++ clang/lib/AST/Interp/ByteCodeExprGen.h @@ -89,6 +89,7 @@ bool VisitCharacterLiteral(const CharacterLiteral *E); bool VisitExprWithCleanups(const ExprWithCleanups *E); bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); + bool VisitCompoundAssignOperator(const CompoundAssignOperator *E); protected: bool visitExpr(const Expr *E) override; Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -564,6 +564,57 @@ return false; } +template +bool ByteCodeExprGen::VisitCompoundAssignOperator( + const CompoundAssignOperator *E) { + const Expr *LHS = E->getLHS(); + const Expr *RHS = E->getRHS(); + Optional LT = classify(E->getLHS()->getType()); + Optional RT = classify(E->getRHS()->getType()); + + if (!LT || !RT) + return false; + + assert(!E->getType()->isPointerType() && + "Support pointer arithmethic in compound assignment operators"); + + // Get LHS pointer, load its value and get RHS value. + if (!visit(LHS)) + return false; + if (!this->emitLoad(*LT, E)) + return false; + if (!visit(RHS)) + return false; + + // Perform operation. + switch (E->getOpcode()) { + case BO_AddAssign: + if (!this->emitAdd(*LT, E)) + return false; + break; + case BO_SubAssign: + if (!this->emitSub(*LT, E)) + return false; + break; + + case BO_MulAssign: + case BO_DivAssign: + case BO_RemAssign: + case BO_ShlAssign: + case BO_ShrAssign: + case BO_AndAssign: + case BO_XorAssign: + case BO_OrAssign: + default: + llvm_unreachable("Unimplemented compound assign operator"); + } + + // And store the result in LHS. + if (DiscardResult) + return this->emitStorePop(*LT, E); + return this->emitStore(*LT, E); +} + template bool ByteCodeExprGen::discard(const Expr *E) { OptionScope Scope(this, /*NewDiscardResult=*/true); return this->Visit(E); Index: clang/test/AST/Interp/literals.cpp =================================================================== --- clang/test/AST/Interp/literals.cpp +++ clang/test/AST/Interp/literals.cpp @@ -408,5 +408,22 @@ return -1; } + + constexpr int getTwo() { + int i = 1; + return (i += 1); + } + static_assert(getTwo() == 2, ""); + + constexpr int sub(int a) { + return (a -= 2); + } + static_assert(sub(7) == 5, ""); + + constexpr int subAll(int a) { + return (a -= a); + } + static_assert(subAll(213) == 0); + }; #endif