https://github.com/rjodinchr updated https://github.com/llvm/llvm-project/pull/238332
>From 3536fe4c60fa3cfd1c2726bdaa9e2669dd9f18c0 Mon Sep 17 00:00:00 2001 From: Romaric Jodin <[email protected]> Date: Tue, 3 Nov 2026 11:53:09 +0100 Subject: [PATCH] [CodeGen] Store Value* instead of polymorphic Cleanup in EmitCall In CodeGenFunction::EmitCall, CallLifetimeEnd derives from the polymorphic base class EHScopeStack::Cleanup so that it can be pushed onto EHStack when cleanup happens on both normal and unwind edges. For non-cleanup calls, however, CallLifetimeEnd instances were also stored by value in SmallVector<CallLifetimeEnd, 2> CallLifetimeEndAfterCall and invoked directly after the call. SmallVector inline storage uses aligned_char_array_union raw bytes and obtains a typed begin() pointer via reinterpret_cast<T *>(Buffer) before elements are constructed in place. Because CallLifetimeEnd has a vtable, compiling with Control Flow Integrity (-fsanitize=cfi-unrelated-cast) instruments the cast inside SmallVector::begin() and checks the vtable pointer on uninitialized stack bytes during push_back(), trapping at runtime before placement new can construct the CallLifetimeEnd object. Since CallLifetimeEnd only wraps a single llvm::Value *Addr and calls CGF.EmitLifetimeEnd(Addr), store llvm::Value * directly in SmallVector<llvm::Value *, 2> CallLifetimeEndAfterCall and invoke EmitLifetimeEnd on each address after the call. --- clang/lib/CodeGen/CGCall.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 718ee7b547b43d..1d7f9f742b87e9 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -5821,7 +5821,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // When passing arguments using temporary allocas, we need to add the // appropriate lifetime markers. This vector keeps track of all the lifetime // markers that need to be ended right after the call. - SmallVector<CallLifetimeEnd, 2> CallLifetimeEndAfterCall; + SmallVector<llvm::Value *, 2> CallLifetimeEndAfterCall; // Translate all of the arguments as necessary to match the IR lowering. assert(CallInfo.arg_size() == CallArgs.size() && @@ -5976,7 +5976,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // Emit lifetime markers for the temporary alloca and add cleanup code to // emit the end lifetime marker after the call. if (EmitLifetimeStart(AI.getPointer())) - CallLifetimeEndAfterCall.emplace_back(AI); + CallLifetimeEndAfterCall.push_back(AI.getPointer()); // Generate the copy. I->copyInto(*this, AI); @@ -6858,10 +6858,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, AllocAlignAttrEmitter.EmitAsAnAssumption(Loc, RetTy, Ret); } - // Explicitly call CallLifetimeEnd::Emit just to re-use the code even though - // we can't use the full cleanup mechanism. - for (CallLifetimeEnd &LifetimeEnd : CallLifetimeEndAfterCall) - LifetimeEnd.Emit(*this, /*Flags=*/{}); + // Emit the end lifetime markers for any temporary allocas created for the + // call arguments. + for (llvm::Value *LifetimeEndAddr : CallLifetimeEndAfterCall) + EmitLifetimeEnd(LifetimeEndAddr); if (!ReturnValue.isExternallyDestructed() && RetTy.isDestructedType() == QualType::DK_nontrivial_c_struct) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
