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__ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits