Skip to content

Conversation

@tbaederr
Copy link
Contributor

So we can know what blocks we're currently running constructors or destructors for.

So we can know what blocks we're currently running constructors or destructors for.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:bytecode Issues for the clang bytecode constexpr interpreter labels Jul 11, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 11, 2025

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

Changes

So we can know what blocks we're currently running constructors or destructors for.


Full diff: https://github.com/llvm/llvm-project/pull/148120.diff

2 Files Affected:

  • (modified) clang/lib/AST/ByteCode/Interp.cpp (+21-22)
  • (modified) clang/lib/AST/ByteCode/InterpState.h (+4)
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index be77657acabcc..18b84fa48fb1d 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -576,23 +576,14 @@ bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { if (!Ptr.isConst() || Ptr.isMutable()) return true; - // The This pointer is writable in constructors and destructors, - // even if isConst() returns true. - // TODO(perf): We could be hitting this code path quite a lot in complex - // constructors. Is there a better way to do this? - if (S.Current->getFunction()) { - for (const InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) { - if (const Function *Func = Frame->getFunction(); - Func && (Func->isConstructor() || Func->isDestructor()) && - Ptr.block() == Frame->getThis().block()) { - return true; - } - } - } - if (!Ptr.isBlockPointer()) return false; + // The This pointer is writable in constructors and destructors, + // even if isConst() returns true. + if (llvm::find(S.InitializingBlocks, Ptr.block())) + return true; + const QualType Ty = Ptr.getType(); const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty; @@ -1524,6 +1515,9 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func, return false; if (Func->isDestructor() && !CheckDestructor(S, OpPC, ThisPtr)) return false; + + if (Func->isConstructor() || Func->isDestructor()) + S.InitializingBlocks.push_back(ThisPtr.block()); } if (!Func->isFullyCompiled()) @@ -1550,16 +1544,21 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func, // Note that we cannot assert(CallResult.hasValue()) here since // Ret() above only sets the APValue if the curent frame doesn't // have a caller set. - if (Interpret(S)) { - NewFrame.release(); // Frame was delete'd already. - assert(S.Current == FrameBefore); - return true; + bool Success = Interpret(S); + // Remove initializing block again. + if (Func->isConstructor() || Func->isDestructor()) + S.InitializingBlocks.pop_back(); + + if (!Success) { + // Interpreting the function failed somehow. Reset to + // previous state. + S.Current = FrameBefore; + return false; } - // Interpreting the function failed somehow. Reset to - // previous state. - S.Current = FrameBefore; - return false; + NewFrame.release(); // Frame was delete'd already. + assert(S.Current == FrameBefore); + return true; } bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, diff --git a/clang/lib/AST/ByteCode/InterpState.h b/clang/lib/AST/ByteCode/InterpState.h index 08765561985e2..861e4c38049ab 100644 --- a/clang/lib/AST/ByteCode/InterpState.h +++ b/clang/lib/AST/ByteCode/InterpState.h @@ -190,6 +190,10 @@ class InterpState final : public State, public SourceMapper { std::pair<const Expr *, const LifetimeExtendedTemporaryDecl *>> SeenGlobalTemporaries; + /// List of blocks we're currently running either constructors or destructors + /// for. + llvm::SmallVector<const Block *> InitializingBlocks; + mutable llvm::BumpPtrAllocator Allocator; }; 
@tbaederr tbaederr merged commit 0e5f9f6 into llvm:main Jul 11, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:bytecode Issues for the clang bytecode constexpr interpreter clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

2 participants