aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimm Bäder <tbaeder@redhat.com>2024-06-07 10:31:16 +0200
committerTimm Bäder <tbaeder@redhat.com>2024-06-07 10:32:16 +0200
commit1c0063b58a4fc23c94c7f5bf5a937bbdf9703cc0 (patch)
tree9a0bcc6526e7bd344d683416f74ba89d10a6ba48
parent36bc7410cb68e32d4416b951a118d5a799d3a226 (diff)
downloadllvm-1c0063b58a4fc23c94c7f5bf5a937bbdf9703cc0.zip
llvm-1c0063b58a4fc23c94c7f5bf5a937bbdf9703cc0.tar.gz
llvm-1c0063b58a4fc23c94c7f5bf5a937bbdf9703cc0.tar.bz2
[clang][Interp] Remove StoragKind limitation in Pointer assign operators
It's not strictly needed and did cause some test failures.
-rw-r--r--clang/lib/AST/Interp/Pointer.cpp44
-rw-r--r--clang/test/AST/Interp/cxx20.cpp15
2 files changed, 37 insertions, 22 deletions
diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp
index a60b4d2..e3d21f9 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -64,26 +64,26 @@ Pointer::~Pointer() {
}
void Pointer::operator=(const Pointer &P) {
- if (!this->isIntegralPointer() || !P.isBlockPointer())
- assert(P.StorageKind == StorageKind || (this->isZero() && P.isZero()));
-
+ // If the current storage type is Block, we need to remove
+ // this pointer from the block.
bool WasBlockPointer = isBlockPointer();
- StorageKind = P.StorageKind;
if (StorageKind == Storage::Block) {
Block *Old = PointeeStorage.BS.Pointee;
- if (WasBlockPointer && PointeeStorage.BS.Pointee)
+ if (WasBlockPointer && Old) {
PointeeStorage.BS.Pointee->removePointer(this);
+ Old->cleanup();
+ }
+ }
- Offset = P.Offset;
+ StorageKind = P.StorageKind;
+ Offset = P.Offset;
+
+ if (P.isBlockPointer()) {
PointeeStorage.BS = P.PointeeStorage.BS;
if (PointeeStorage.BS.Pointee)
PointeeStorage.BS.Pointee->addPointer(this);
-
- if (WasBlockPointer && Old)
- Old->cleanup();
-
- } else if (StorageKind == Storage::Int) {
+ } else if (P.isIntegralPointer()) {
PointeeStorage.Int = P.PointeeStorage.Int;
} else {
assert(false && "Unhandled storage kind");
@@ -91,26 +91,26 @@ void Pointer::operator=(const Pointer &P) {
}
void Pointer::operator=(Pointer &&P) {
- if (!this->isIntegralPointer() || !P.isBlockPointer())
- assert(P.StorageKind == StorageKind || (this->isZero() && P.isZero()));
-
+ // If the current storage type is Block, we need to remove
+ // this pointer from the block.
bool WasBlockPointer = isBlockPointer();
- StorageKind = P.StorageKind;
if (StorageKind == Storage::Block) {
Block *Old = PointeeStorage.BS.Pointee;
- if (WasBlockPointer && PointeeStorage.BS.Pointee)
+ if (WasBlockPointer && Old) {
PointeeStorage.BS.Pointee->removePointer(this);
+ Old->cleanup();
+ }
+ }
- Offset = P.Offset;
+ StorageKind = P.StorageKind;
+ Offset = P.Offset;
+
+ if (P.isBlockPointer()) {
PointeeStorage.BS = P.PointeeStorage.BS;
if (PointeeStorage.BS.Pointee)
PointeeStorage.BS.Pointee->addPointer(this);
-
- if (WasBlockPointer && Old)
- Old->cleanup();
-
- } else if (StorageKind == Storage::Int) {
+ } else if (P.isIntegralPointer()) {
PointeeStorage.Int = P.PointeeStorage.Int;
} else {
assert(false && "Unhandled storage kind");
diff --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp
index 49ee040..c750be8 100644
--- a/clang/test/AST/Interp/cxx20.cpp
+++ b/clang/test/AST/Interp/cxx20.cpp
@@ -782,3 +782,18 @@ namespace APValues {
constexpr const A &v = get<A{}>;
constexpr const A &w = get<A{1, &g, &A::n, "hello"}>;
}
+
+namespace self_referencing {
+ struct S {
+ S* ptr = nullptr;
+ constexpr S(int i) : ptr(this) {
+ if (this == ptr && i)
+ ptr = nullptr;
+ }
+ constexpr ~S() {}
+ };
+
+ void test() {
+ S s(1);
+ }
+}