https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/127526
Just like with the __builtin_operator_new version, we need to point to the first array element, not the array element itself. >From ba084758083d32d2db4773abd181880717830706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Mon, 17 Feb 2025 18:33:51 +0100 Subject: [PATCH] [clang][bytecode] Fix returne value of array CXXNewExprs Just like with the __builtin_operator_new version, we need to point to the first array element, not the array element itself. --- clang/lib/AST/ByteCode/Interp.cpp | 3 ++- clang/lib/AST/ByteCode/Interp.h | 13 +++++++++++-- clang/test/AST/ByteCode/new-delete.cpp | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index c80be094856b0..0310870f7372e 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1063,7 +1063,8 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm, return false; } - if (!Ptr.isRoot() || Ptr.isOnePastEnd() || Ptr.isArrayElement()) { + if (!Ptr.isRoot() || Ptr.isOnePastEnd() || + (Ptr.isArrayElement() && Ptr.getIndex() != 0)) { const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_delete_subobject) << Ptr.toDiagnosticString(S.getASTContext()) << Ptr.isOnePastEnd(); diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 73cc107b7dbff..10cf21e28437c 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -2915,13 +2915,17 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source, S.Stk.push<Pointer>(0, nullptr); return true; } + assert(NumElements.isPositive()); DynamicAllocator &Allocator = S.getAllocator(); Block *B = Allocator.allocate(Source, T, static_cast<size_t>(NumElements), S.Ctx.getEvalID(), DynamicAllocator::Form::Array); assert(B); - S.Stk.push<Pointer>(B); + if (NumElements.isZero()) + S.Stk.push<Pointer>(B); + else + S.Stk.push<Pointer>(Pointer(B).atIndex(0)); return true; } @@ -2941,13 +2945,18 @@ inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc, S.Stk.push<Pointer>(0, ElementDesc); return true; } + assert(NumElements.isPositive()); DynamicAllocator &Allocator = S.getAllocator(); Block *B = Allocator.allocate(ElementDesc, static_cast<size_t>(NumElements), S.Ctx.getEvalID(), DynamicAllocator::Form::Array); assert(B); - S.Stk.push<Pointer>(B); + if (NumElements.isZero()) + S.Stk.push<Pointer>(B); + else + S.Stk.push<Pointer>(Pointer(B).atIndex(0)); + return true; } diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp index e9850d27666e5..7e5f6ab8815ea 100644 --- a/clang/test/AST/ByteCode/new-delete.cpp +++ b/clang/test/AST/ByteCode/new-delete.cpp @@ -922,6 +922,20 @@ namespace NonConstexprArrayCtor { // both-note {{in call to}} } +namespace ArrayBaseCast { + struct A {}; + struct B : A {}; + constexpr bool test() { + B *b = new B[2]; + + A* a = b; + + delete[] b; + return true; + } + static_assert(test()); +} + #else /// Make sure we reject this prior to C++20 constexpr int a() { // both-error {{never produces a constant expression}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits