[clang] e44784f - [clang][bytecode] Fix pseudo dtor calls on non-pointers (#153970)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 16 23:48:00 PDT 2025
Author: Timm Baeder
Date: 2025-08-17T08:47:57+02:00
New Revision: e44784fb44bd00acc0ecd25537a359c3a1df8f17
URL: https://github.com/llvm/llvm-project/commit/e44784fb44bd00acc0ecd25537a359c3a1df8f17
DIFF: https://github.com/llvm/llvm-project/commit/e44784fb44bd00acc0ecd25537a359c3a1df8f17.diff
LOG: [clang][bytecode] Fix pseudo dtor calls on non-pointers (#153970)
The isGLValue() check made us ignore expressions we shouldn't ignore.
Added:
Modified:
clang/lib/AST/ByteCode/Compiler.cpp
clang/test/AST/ByteCode/builtin-functions.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 6c6c8d41d3b93..b228cea7cb58b 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -5146,7 +5146,8 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
if (!this->emitCheckPseudoDtor(E))
return false;
const Expr *Base = PD->getBase();
- if (!Base->isGLValue())
+ // E.g. `using T = int; 0.~T();`.
+ if (OptPrimType BaseT = classify(Base); !BaseT || BaseT != PT_Ptr)
return this->discard(Base);
if (!this->visit(Base))
return false;
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 1223cf8bdc74f..878c0d1a40f26 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -21,6 +21,27 @@
#error "huh?"
#endif
+
+inline constexpr void* operator new(__SIZE_TYPE__, void* p) noexcept { return p; }
+namespace std {
+ using size_t = decltype(sizeof(0));
+ template<typename T> struct allocator {
+ constexpr T *allocate(size_t N) {
+ return (T*)__builtin_operator_new(sizeof(T) * N); // #alloc
+ }
+ constexpr void deallocate(void *p, __SIZE_TYPE__) {
+ __builtin_operator_delete(p);
+ }
+ };
+template<typename T, typename... Args>
+constexpr T* construct_at(T* p, Args&&... args) { return ::new((void*)p) T(static_cast<Args&&>(args)...); }
+
+ template<typename T>
+ constexpr void destroy_at(T* p) {
+ p->~T();
+ }
+}
+
extern "C" {
typedef decltype(sizeof(int)) size_t;
extern size_t wcslen(const wchar_t *p);
@@ -1767,6 +1788,28 @@ namespace WithinLifetime {
}
} xstd; // both-error {{is not a constant expression}} \
// both-note {{in call to}}
+
+ consteval bool test_dynamic(bool read_after_deallocate) {
+ std::allocator<int> a;
+ int* p = a.allocate(1);
+ // a.allocate starts the lifetime of an array,
+ // the complete object of *p has started its lifetime
+ if (__builtin_is_within_lifetime(p))
+ return false;
+ std::construct_at(p);
+ if (!__builtin_is_within_lifetime(p))
+ return false;
+ std::destroy_at(p);
+ if (__builtin_is_within_lifetime(p))
+ return false;
+ a.deallocate(p, 1);
+ if (read_after_deallocate)
+ __builtin_is_within_lifetime(p); // both-note {{read of heap allocated object that has been deleted}}
+ return true;
+ }
+ static_assert(test_dynamic(false));
+ static_assert(test_dynamic(true)); // both-error {{not an integral constant expression}} \
+ // both-note {{in call to}}
}
#ifdef __SIZEOF_INT128__
More information about the cfe-commits
mailing list