aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-03-08 13:13:52 +0100
committerGitHub <noreply@github.com>2025-03-08 13:13:52 +0100
commit3b8f9a228c5f12f282778b18117b9a88c07e87cb (patch)
tree19e68d4a07b03b1a8f4f2670a16b83888a8860ac
parent73e14de207a3aa0fa071fa56756e8e316edf5227 (diff)
downloadllvm-3b8f9a228c5f12f282778b18117b9a88c07e87cb.zip
llvm-3b8f9a228c5f12f282778b18117b9a88c07e87cb.tar.gz
llvm-3b8f9a228c5f12f282778b18117b9a88c07e87cb.tar.bz2
[clang][bytecode] Loosen assertion This() for array elements (#130399)
getRecord() returns null on array elements, even for composite arrays. The assertion here was overly restrictive and having an array element as instance pointer should be fine otherwise.
-rw-r--r--clang/lib/AST/ByteCode/Interp.h7
-rw-r--r--clang/test/AST/ByteCode/placement-new.cpp24
2 files changed, 29 insertions, 2 deletions
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 401bbef..f2ddeac 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2432,9 +2432,12 @@ inline bool This(InterpState &S, CodePtr OpPC) {
// Ensure the This pointer has been cast to the correct base.
if (!This.isDummy()) {
assert(isa<CXXMethodDecl>(S.Current->getFunction()->getDecl()));
- assert(This.getRecord());
+ [[maybe_unused]] const Record *R = This.getRecord();
+ if (!R)
+ R = This.narrow().getRecord();
+ assert(R);
assert(
- This.getRecord()->getDecl() ==
+ R->getDecl() ==
cast<CXXMethodDecl>(S.Current->getFunction()->getDecl())->getParent());
}
diff --git a/clang/test/AST/ByteCode/placement-new.cpp b/clang/test/AST/ByteCode/placement-new.cpp
index 7a4fc89..c353162 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -339,6 +339,30 @@ namespace PR48606 {
static_assert(f());
}
+/// This used to crash because of an assertion in the implementation
+/// of the This instruction.
+namespace ExplicitThisOnArrayElement {
+ struct S {
+ int a = 12;
+ constexpr S(int a) {
+ this->a = a;
+ }
+ };
+
+ template <class _Tp, class... _Args>
+ constexpr void construct_at(_Tp *__location, _Args &&...__args) {
+ new (__location) _Tp(__args...);
+ }
+
+ constexpr bool foo() {
+ auto *M = std::allocator<S>().allocate(13); // both-note {{allocation performed here was not deallocated}}
+ construct_at(M, 12);
+ return true;
+ }
+
+ static_assert(foo()); // both-error {{not an integral constant expression}}
+}
+
#ifdef BYTECODE
constexpr int N = [] // expected-error {{must be initialized by a constant expression}} \
// expected-note {{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}} \