From fb46105ceed81ebea8088228969352ac6c52e891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 21 Nov 2025 15:20:40 +0100 Subject: [PATCH] [clang][bytecode] Don't call getThis() on the bottom function frame We can't access the calling frame in that case. Fixes https://github.com/llvm/llvm-project/issues/169032 --- clang/lib/AST/ByteCode/Interp.cpp | 3 ++- clang/lib/AST/ByteCode/InterpFrame.h | 2 ++ clang/test/AST/ByteCode/new-delete.cpp | 12 ++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 280911c324bb1..4222fd97a84fa 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1407,7 +1407,8 @@ bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T) { // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677 // Therefore, we use the C++1y behavior. - if (S.Current->getFunction() && S.Current->getFunction()->isConstructor() && + if (!S.Current->isBottomFrame() && + S.Current->getFunction()->isConstructor() && S.Current->getThis().getDeclDesc()->asDecl() == S.EvaluatingDecl) { return true; } diff --git a/clang/lib/AST/ByteCode/InterpFrame.h b/clang/lib/AST/ByteCode/InterpFrame.h index fa9de2e1e7c6d..febef1097ea8a 100644 --- a/clang/lib/AST/ByteCode/InterpFrame.h +++ b/clang/lib/AST/ByteCode/InterpFrame.h @@ -109,6 +109,7 @@ class InterpFrame final : public Frame { /// Returns the 'this' pointer. const Pointer &getThis() const { assert(hasThisPointer()); + assert(!isBottomFrame()); return stackRef(ThisPointerOffset); } @@ -116,6 +117,7 @@ class InterpFrame final : public Frame { const Pointer &getRVOPtr() const { assert(Func); assert(Func->hasRVO()); + assert(!isBottomFrame()); return stackRef(0); } diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp index 9e0f33e212c18..43e1f6bfcc9a6 100644 --- a/clang/test/AST/ByteCode/new-delete.cpp +++ b/clang/test/AST/ByteCode/new-delete.cpp @@ -1114,6 +1114,18 @@ namespace ZeroSizeArray { static_assert(foo() == 0); } +namespace NonLiteralType { + /// This used to crash. + constexpr void foo() { + struct O {}; + + struct S { + O *s; + constexpr S() : s{std::allocator{}.allocate(1)} {} + }; + } +} + #else /// Make sure we reject this prior to C++20 constexpr int a() { // both-error {{never produces a constant expression}}