Skip to content

Commit 09d1414

Browse files
authored
[clang][bytecode] Fix return value of array CXXNewExprs (#127526)
Just like with the __builtin_operator_new version, we need to point to the first array element, not the array element itself.
1 parent b5b8a59 commit 09d1414

File tree

3 files changed

+27
-3
lines changed

3 files changed

+27
-3
lines changed

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,8 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
10631063
return false;
10641064
}
10651065

1066-
if (!Ptr.isRoot() || Ptr.isOnePastEnd() || Ptr.isArrayElement()) {
1066+
if (!Ptr.isRoot() || Ptr.isOnePastEnd() ||
1067+
(Ptr.isArrayElement() && Ptr.getIndex() != 0)) {
10671068
const SourceInfo &Loc = S.Current->getSource(OpPC);
10681069
S.FFDiag(Loc, diag::note_constexpr_delete_subobject)
10691070
<< Ptr.toDiagnosticString(S.getASTContext()) << Ptr.isOnePastEnd();

clang/lib/AST/ByteCode/Interp.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2915,13 +2915,17 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source,
29152915
S.Stk.push<Pointer>(0, nullptr);
29162916
return true;
29172917
}
2918+
assert(NumElements.isPositive());
29182919

29192920
DynamicAllocator &Allocator = S.getAllocator();
29202921
Block *B =
29212922
Allocator.allocate(Source, T, static_cast<size_t>(NumElements),
29222923
S.Ctx.getEvalID(), DynamicAllocator::Form::Array);
29232924
assert(B);
2924-
S.Stk.push<Pointer>(B);
2925+
if (NumElements.isZero())
2926+
S.Stk.push<Pointer>(B);
2927+
else
2928+
S.Stk.push<Pointer>(Pointer(B).atIndex(0));
29252929
return true;
29262930
}
29272931

@@ -2941,13 +2945,18 @@ inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc,
29412945
S.Stk.push<Pointer>(0, ElementDesc);
29422946
return true;
29432947
}
2948+
assert(NumElements.isPositive());
29442949

29452950
DynamicAllocator &Allocator = S.getAllocator();
29462951
Block *B =
29472952
Allocator.allocate(ElementDesc, static_cast<size_t>(NumElements),
29482953
S.Ctx.getEvalID(), DynamicAllocator::Form::Array);
29492954
assert(B);
2950-
S.Stk.push<Pointer>(B);
2955+
if (NumElements.isZero())
2956+
S.Stk.push<Pointer>(B);
2957+
else
2958+
S.Stk.push<Pointer>(Pointer(B).atIndex(0));
2959+
29512960
return true;
29522961
}
29532962

clang/test/AST/ByteCode/new-delete.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,20 @@ namespace NonConstexprArrayCtor {
922922
// both-note {{in call to}}
923923
}
924924

925+
namespace ArrayBaseCast {
926+
struct A {};
927+
struct B : A {};
928+
constexpr bool test() {
929+
B *b = new B[2];
930+
931+
A* a = b;
932+
933+
delete[] b;
934+
return true;
935+
}
936+
static_assert(test());
937+
}
938+
925939
#else
926940
/// Make sure we reject this prior to C++20
927941
constexpr int a() { // both-error {{never produces a constant expression}}

0 commit comments

Comments
 (0)