diff options
author | Timm Bäder <tbaeder@redhat.com> | 2024-06-07 10:31:16 +0200 |
---|---|---|
committer | Timm Bäder <tbaeder@redhat.com> | 2024-06-07 10:32:16 +0200 |
commit | 1c0063b58a4fc23c94c7f5bf5a937bbdf9703cc0 (patch) | |
tree | 9a0bcc6526e7bd344d683416f74ba89d10a6ba48 | |
parent | 36bc7410cb68e32d4416b951a118d5a799d3a226 (diff) | |
download | llvm-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.cpp | 44 | ||||
-rw-r--r-- | clang/test/AST/Interp/cxx20.cpp | 15 |
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); + } +} |