https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/107565
The first pointer needs to point to the first element of the underlying array. This requires some changes to how we handle array expansion >From 8968151c4773910e6f85d9273899432556376300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Fri, 6 Sep 2024 12:56:14 +0200 Subject: [PATCH] [clang][bytecode] Fix two-pointer-style std::initializer_lists The first pointer needs to point to the first element of the underlying array. This requires some changes to how we handle array expansion --- clang/lib/AST/ByteCode/Compiler.cpp | 6 +++ clang/lib/AST/ByteCode/Interp.h | 4 +- clang/lib/AST/ByteCode/Pointer.h | 5 +- clang/test/AST/ByteCode/initializer_list.cpp | 55 ++++++++++++++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 clang/test/AST/ByteCode/initializer_list.cpp diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index a831f196abdcb5..241d1ad9703170 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -3202,6 +3202,10 @@ bool Compiler<Emitter>::VisitCXXStdInitializerListExpr( if (!this->visit(SubExpr)) return false; + if (!this->emitConstUint8(0, E)) + return false; + if (!this->emitArrayElemPtrPopUint8(E)) + return false; if (!this->emitInitFieldPtr(R->getField(0u)->Offset, E)) return false; @@ -3216,6 +3220,8 @@ bool Compiler<Emitter>::VisitCXXStdInitializerListExpr( if (!this->emitGetFieldPtr(R->getField(0u)->Offset, E)) return false; + if (!this->emitExpandPtr(E)) + return false; if (!this->emitConst(static_cast<APSInt>(ArrayType->getSize()), PT_Uint64, E)) return false; if (!this->emitArrayElemPtrPop(PT_Uint64, E)) diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index be900769f25845..d1fff19d1c9ddf 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -1991,7 +1991,9 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, template <PrimType Name, class T = typename PrimConv<Name>::T> bool AddOffset(InterpState &S, CodePtr OpPC) { const T &Offset = S.Stk.pop<T>(); - const Pointer &Ptr = S.Stk.pop<Pointer>(); + Pointer Ptr = S.Stk.pop<Pointer>(); + if (Ptr.isBlockPointer()) + Ptr = Ptr.expand(); return OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr); } diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index d05d8e9bc1f388..acbef437752388 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -241,9 +241,8 @@ class Pointer { if (asBlockPointer().Base != Offset) return *this; - // If at base, point to an array of base types. if (isRoot()) - return Pointer(Pointee, RootPtrMark, 0); + return Pointer(Pointee, asBlockPointer().Base, asBlockPointer().Base); // Step into the containing array, if inside one. unsigned Next = asBlockPointer().Base - getInlineDesc()->Offset; @@ -711,8 +710,10 @@ class Pointer { /// Returns the embedded descriptor preceding a field. InlineDescriptor *getInlineDesc() const { + assert(isBlockPointer()); assert(asBlockPointer().Base != sizeof(GlobalInlineDescriptor)); assert(asBlockPointer().Base <= asBlockPointer().Pointee->getSize()); + assert(asBlockPointer().Base >= sizeof(InlineDescriptor)); return getDescriptor(asBlockPointer().Base); } diff --git a/clang/test/AST/ByteCode/initializer_list.cpp b/clang/test/AST/ByteCode/initializer_list.cpp new file mode 100644 index 00000000000000..4e3b8dc9120167 --- /dev/null +++ b/clang/test/AST/ByteCode/initializer_list.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -fms-extensions -std=c++20 -verify=expected,both %s +// RUN: %clang_cc1 -std=c++20 -fms-extensions -verify=ref,both %s + +// both-no-diagnostics + +namespace std { + typedef decltype(sizeof(int)) size_t; + template <class _E> + class initializer_list + { + const _E* __begin_; + size_t __size_; + + initializer_list(const _E* __b, size_t __s) + : __begin_(__b), + __size_(__s) + {} + + public: + typedef _E value_type; + typedef const _E& reference; + typedef const _E& const_reference; + typedef size_t size_type; + + typedef const _E* iterator; + typedef const _E* const_iterator; + + constexpr initializer_list() : __begin_(nullptr), __size_(0) {} + + constexpr size_t size() const {return __size_;} + constexpr const _E* begin() const {return __begin_;} + constexpr const _E* end() const {return __begin_ + __size_;} + }; +} + +class Thing { +public: + int m = 12; + constexpr Thing(int m) : m(m) {} + constexpr bool operator==(const Thing& that) const { + return this->m == that.m; + } +}; + +constexpr bool is_contained(std::initializer_list<Thing> Set, const Thing &Element) { + return (*Set.begin() == Element); +} + +constexpr int foo() { + const Thing a{12}; + const Thing b{14}; + return is_contained({a}, b); +} + +static_assert(foo() == 0); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits