https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/112719
... provided the given index is 0. Skip the atIndex() in that case. >From cc844864398bceb91a31c22cd52d16e6dbd9eb71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Thu, 17 Oct 2024 15:05:29 +0200 Subject: [PATCH] [clang][bytecode] Handle non-arrays in initElem{,Pop} ... provided the given index is 0. Skip the atIndex() in that case. --- clang/lib/AST/ByteCode/Interp.h | 37 ++++++++++++++++++----- clang/test/AST/ByteCode/placement-new.cpp | 14 +++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index dece95971b7617..a1a92562cc5e3d 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -1863,13 +1863,24 @@ bool InitPop(InterpState &S, CodePtr OpPC) { template <PrimType Name, class T = typename PrimConv<Name>::T> bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx) { const T &Value = S.Stk.pop<T>(); - const Pointer &Ptr = S.Stk.peek<Pointer>().atIndex(Idx); + const Pointer &Ptr = S.Stk.peek<Pointer>(); + if (Ptr.isUnknownSizeArray()) return false; - if (!CheckInit(S, OpPC, Ptr)) + + // In the unlikely event that we're initializing the first item of + // a non-array, skip the atIndex(). + if (Idx == 0 && !Ptr.getFieldDesc()->isArray()) { + Ptr.initialize(); + new (&Ptr.deref<T>()) T(Value); + return true; + } + + const Pointer &ElemPtr = Ptr.atIndex(Idx); + if (!CheckInit(S, OpPC, ElemPtr)) return false; - Ptr.initialize(); - new (&Ptr.deref<T>()) T(Value); + ElemPtr.initialize(); + new (&ElemPtr.deref<T>()) T(Value); return true; } @@ -1877,13 +1888,23 @@ bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx) { template <PrimType Name, class T = typename PrimConv<Name>::T> bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) { const T &Value = S.Stk.pop<T>(); - const Pointer &Ptr = S.Stk.pop<Pointer>().atIndex(Idx); + const Pointer &Ptr = S.Stk.pop<Pointer>(); if (Ptr.isUnknownSizeArray()) return false; - if (!CheckInit(S, OpPC, Ptr)) + + // In the unlikely event that we're initializing the first item of + // a non-array, skip the atIndex(). + if (Idx == 0 && !Ptr.getFieldDesc()->isArray()) { + Ptr.initialize(); + new (&Ptr.deref<T>()) T(Value); + return true; + } + + const Pointer &ElemPtr = Ptr.atIndex(Idx); + if (!CheckInit(S, OpPC, ElemPtr)) return false; - Ptr.initialize(); - new (&Ptr.deref<T>()) T(Value); + ElemPtr.initialize(); + new (&ElemPtr.deref<T>()) T(Value); return true; } diff --git a/clang/test/AST/ByteCode/placement-new.cpp b/clang/test/AST/ByteCode/placement-new.cpp index caf3ac97fd1c04..6bd83f2372eab6 100644 --- a/clang/test/AST/ByteCode/placement-new.cpp +++ b/clang/test/AST/ByteCode/placement-new.cpp @@ -52,6 +52,20 @@ consteval auto ok4() { } static_assert(ok4() == 37); +consteval int ok5() { + int i; + new (&i) int[1]{1}; + + struct S { + int a; int b; + } s; + new (&s) S[1]{{12, 13}}; + + return 25; + // return s.a + s.b; FIXME: Broken in the current interpreter. +} +static_assert(ok5() == 25); + /// FIXME: Broken in both interpreters. #if 0 consteval int ok5() { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits