[clang] 881547d - [clang][Interp] Implement add and sub compound assign operators
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 30 00:11:46 PDT 2022
Author: Timm Bäder
Date: 2022-10-30T08:11:04+01:00
New Revision: 881547db03a6ea243505a8ccba1547f2f18c05ca
URL: https://github.com/llvm/llvm-project/commit/881547db03a6ea243505a8ccba1547f2f18c05ca
DIFF: https://github.com/llvm/llvm-project/commit/881547db03a6ea243505a8ccba1547f2f18c05ca.diff
LOG: [clang][Interp] Implement add and sub compound assign operators
Differential Revision: https://reviews.llvm.org/D136528
Added:
Modified:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/test/AST/Interp/literals.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 30ae7fbfc637a..2edd16bc7e6cc 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -414,6 +414,57 @@ bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral(
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);
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 489e8bdb79ca4..4c7550aa497df 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -85,6 +85,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
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;
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 1c6aa4e26979c..afb98e3c1ef99 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -415,5 +415,43 @@ namespace IncDec {
// 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
More information about the cfe-commits
mailing list