This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG881547db03a6: [clang][Interp] Implement add and sub compound assign operators (authored by tbaeder).
Changed prior to commit: https://reviews.llvm.org/D136528?vs=470138&id=471817#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D136528/new/ https://reviews.llvm.org/D136528 Files: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/test/AST/Interp/literals.cpp
Index: clang/test/AST/Interp/literals.cpp =================================================================== --- clang/test/AST/Interp/literals.cpp +++ clang/test/AST/Interp/literals.cpp @@ -415,5 +415,43 @@ // expected-note {{in call to 'UnderFlow()'}} \ // ref-error {{not an integral constant expression}} \ // ref-note {{in call to 'UnderFlow()'}} + + 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 add(int a, int b) { + a += b; // expected-note {{is outside the range of representable values}} \ + // ref-note {{is outside the range of representable values}} + return a; + } + static_assert(add(1, 2) == 3, ""); + static_assert(add(INT_MAX, 1) == 0, ""); // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'add}} \ + // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'add}} + + constexpr int sub(int a, int b) { + a -= b; // expected-note {{is outside the range of representable values}} \ + // ref-note {{is outside the range of representable values}} + return a; + } + static_assert(sub(10, 20) == -10, ""); + static_assert(sub(INT_MIN, 1) == 0, ""); // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'sub}} \ + // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'sub}} + + constexpr int subAll(int a) { + return (a -= a); + } + static_assert(subAll(213) == 0, ""); }; #endif Index: clang/lib/AST/Interp/ByteCodeExprGen.h =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.h +++ clang/lib/AST/Interp/ByteCodeExprGen.h @@ -85,6 +85,7 @@ bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E); bool VisitStringLiteral(const StringLiteral *E); bool VisitCharacterLiteral(const CharacterLiteral *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 @@ -414,6 +414,57 @@ return this->emitConst(E, E->getValue()); } +template <class Emitter> +bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator( + const CompoundAssignOperator *E) { + const Expr *LHS = E->getLHS(); + const Expr *RHS = E->getRHS(); + Optional<PrimType> LT = classify(E->getLHS()->getType()); + Optional<PrimType> 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 <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) { OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true); return this->Visit(E);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits