[clang] [clang][bytecode] Fix two-pointer-style std::initializer_lists (PR #107682)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Sep 7 03:20:15 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
The first pointer needs to point to the first element of the underlying array. This requires some changes to how we handle array expansion
---
Full diff: https://github.com/llvm/llvm-project/pull/107682.diff
4 Files Affected:
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+6)
- (modified) clang/lib/AST/ByteCode/Interp.h (+3-1)
- (modified) clang/lib/AST/ByteCode/Pointer.h (+3-2)
- (added) clang/test/AST/ByteCode/initializer_list.cpp (+55)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index bada8621b9681f..274ad3e5443d11 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -3320,6 +3320,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;
@@ -3334,6 +3338,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 4ca0e05d67c7c3..6d7de8b334fabd 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -1993,7 +1993,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);
``````````
</details>
https://github.com/llvm/llvm-project/pull/107682
More information about the cfe-commits
mailing list