Author: Timm Bäder Date: 2023-02-03T16:42:46+01:00 New Revision: 4a2c4acb98694bb90c04e05052898708a03a7ebc
URL: https://github.com/llvm/llvm-project/commit/4a2c4acb98694bb90c04e05052898708a03a7ebc DIFF: https://github.com/llvm/llvm-project/commit/4a2c4acb98694bb90c04e05052898708a03a7ebc.diff LOG: [clang][Interp] Support pointers in compound assignment operators Differential Revision: https://reviews.llvm.org/D140874 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 f8ee3a80326b..2b4e324f7b0f 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -685,6 +685,41 @@ bool ByteCodeExprGen<Emitter>::VisitFloatCompoundAssignOperator( return this->emitStore(*LT, E); } +template <class Emitter> +bool ByteCodeExprGen<Emitter>::VisitPointerCompoundAssignOperator( + const CompoundAssignOperator *E) { + BinaryOperatorKind Op = E->getOpcode(); + const Expr *LHS = E->getLHS(); + const Expr *RHS = E->getRHS(); + std::optional<PrimType> LT = classify(LHS->getType()); + std::optional<PrimType> RT = classify(RHS->getType()); + + if (Op != BO_AddAssign && Op != BO_SubAssign) + return false; + + if (!LT || !RT) + return false; + assert(*LT == PT_Ptr); + + if (!visit(LHS)) + return false; + + if (!this->emitLoadPtr(LHS)) + return false; + + if (!visit(RHS)) + return false; + + if (Op == BO_AddAssign) + this->emitAddOffset(*RT, E); + else + this->emitSubOffset(*RT, E); + + if (DiscardResult) + return this->emitStorePopPtr(E); + return this->emitStorePtr(E); +} + template <class Emitter> bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator( const CompoundAssignOperator *E) { @@ -694,6 +729,9 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator( if (E->getType()->isFloatingType()) return VisitFloatCompoundAssignOperator(E); + if (E->getType()->isPointerType()) + return VisitPointerCompoundAssignOperator(E); + const Expr *LHS = E->getLHS(); const Expr *RHS = E->getRHS(); std::optional<PrimType> LHSComputationT = @@ -705,9 +743,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator( if (!LT || !RT || !ResultT || !LHSComputationT) return false; - assert(!E->getType()->isPointerType() && - "Support pointer arithmethic in compound assignment operators"); - + assert(!E->getType()->isPointerType() && "Handled above"); assert(!E->getType()->isFloatingType() && "Handled above"); // Get LHS pointer, load its value and get RHS value. diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 6b16b62a2e58..74cd5984daf5 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -87,6 +87,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, bool VisitCharacterLiteral(const CharacterLiteral *E); bool VisitCompoundAssignOperator(const CompoundAssignOperator *E); bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E); + bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E); bool VisitExprWithCleanups(const ExprWithCleanups *E); bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index c57485aecbf9..7121a24052f9 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -669,5 +669,42 @@ namespace IncDec { // expected-note {{in call to 'IntMul}} \ // ref-error {{not an integral constant expression}} \ // ref-note {{in call to 'IntMul}} + constexpr int arr[] = {1,2,3}; + constexpr int ptrInc1() { + const int *p = arr; + p += 2; + return *p; + } + static_assert(ptrInc1() == 3, ""); + + constexpr int ptrInc2() { + const int *p = arr; + return *(p += 1); + } + static_assert(ptrInc2() == 2, ""); + + constexpr int ptrInc3() { // expected-error {{never produces a constant expression}} \ + // ref-error {{never produces a constant expression}} + const int *p = arr; + p += 12; // expected-note {{cannot refer to element 12 of array of 3 elements}} \ + // ref-note {{cannot refer to element 12 of array of 3 elements}} + return *p; + } + + constexpr int ptrIncDec1() { + const int *p = arr; + p += 2; + p -= 1; + return *p; + } + static_assert(ptrIncDec1() == 2, ""); + + constexpr int ptrDec1() { // expected-error {{never produces a constant expression}} \ + // ref-error {{never produces a constant expression}} + const int *p = arr; + p -= 1; // expected-note {{cannot refer to element -1 of array of 3 elements}} \ + // ref-note {{cannot refer to element -1 of array of 3 elements}} + return *p; + } }; #endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits