Skip to content

Commit 03888a9

Browse files
authored
[clang][bytecode] Handle non-arrays in initElem{,Pop} (#112719)
... provided the given index is 0. Skip the atIndex() in that case.
1 parent 2ef24e0 commit 03888a9

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

clang/lib/AST/ByteCode/Interp.h

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,27 +1863,48 @@ bool InitPop(InterpState &S, CodePtr OpPC) {
18631863
template <PrimType Name, class T = typename PrimConv<Name>::T>
18641864
bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx) {
18651865
const T &Value = S.Stk.pop<T>();
1866-
const Pointer &Ptr = S.Stk.peek<Pointer>().atIndex(Idx);
1866+
const Pointer &Ptr = S.Stk.peek<Pointer>();
1867+
18671868
if (Ptr.isUnknownSizeArray())
18681869
return false;
1869-
if (!CheckInit(S, OpPC, Ptr))
1870+
1871+
// In the unlikely event that we're initializing the first item of
1872+
// a non-array, skip the atIndex().
1873+
if (Idx == 0 && !Ptr.getFieldDesc()->isArray()) {
1874+
Ptr.initialize();
1875+
new (&Ptr.deref<T>()) T(Value);
1876+
return true;
1877+
}
1878+
1879+
const Pointer &ElemPtr = Ptr.atIndex(Idx);
1880+
if (!CheckInit(S, OpPC, ElemPtr))
18701881
return false;
1871-
Ptr.initialize();
1872-
new (&Ptr.deref<T>()) T(Value);
1882+
ElemPtr.initialize();
1883+
new (&ElemPtr.deref<T>()) T(Value);
18731884
return true;
18741885
}
18751886

18761887
/// The same as InitElem, but pops the pointer as well.
18771888
template <PrimType Name, class T = typename PrimConv<Name>::T>
18781889
bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) {
18791890
const T &Value = S.Stk.pop<T>();
1880-
const Pointer &Ptr = S.Stk.pop<Pointer>().atIndex(Idx);
1891+
const Pointer &Ptr = S.Stk.pop<Pointer>();
18811892
if (Ptr.isUnknownSizeArray())
18821893
return false;
1883-
if (!CheckInit(S, OpPC, Ptr))
1894+
1895+
// In the unlikely event that we're initializing the first item of
1896+
// a non-array, skip the atIndex().
1897+
if (Idx == 0 && !Ptr.getFieldDesc()->isArray()) {
1898+
Ptr.initialize();
1899+
new (&Ptr.deref<T>()) T(Value);
1900+
return true;
1901+
}
1902+
1903+
const Pointer &ElemPtr = Ptr.atIndex(Idx);
1904+
if (!CheckInit(S, OpPC, ElemPtr))
18841905
return false;
1885-
Ptr.initialize();
1886-
new (&Ptr.deref<T>()) T(Value);
1906+
ElemPtr.initialize();
1907+
new (&ElemPtr.deref<T>()) T(Value);
18871908
return true;
18881909
}
18891910

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,20 @@ consteval auto ok4() {
5252
}
5353
static_assert(ok4() == 37);
5454

55+
consteval int ok5() {
56+
int i;
57+
new (&i) int[1]{1};
58+
59+
struct S {
60+
int a; int b;
61+
} s;
62+
new (&s) S[1]{{12, 13}};
63+
64+
return 25;
65+
// return s.a + s.b; FIXME: Broken in the current interpreter.
66+
}
67+
static_assert(ok5() == 25);
68+
5569
/// FIXME: Broken in both interpreters.
5670
#if 0
5771
consteval int ok5() {

0 commit comments

Comments
 (0)