Author: Martin Storsjö
Date: 2025-12-06T14:23:10+02:00
New Revision: 6d38c876478dac4a42f9d6e37692348deabf6a25

URL: 
https://github.com/llvm/llvm-project/commit/6d38c876478dac4a42f9d6e37692348deabf6a25
DIFF: 
https://github.com/llvm/llvm-project/commit/6d38c876478dac4a42f9d6e37692348deabf6a25.diff

LOG: Revert "[clang] Limit lifetimes of temporaries to the full expression 
(#170517)"

This reverts commit 5daad5bf45b3c7280f7b06979fb580f70e2c4fd0.

That commit caused broken compilation for some cases, see
https://github.com/llvm/llvm-project/pull/170517#issuecomment-3620079591.

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/CodeGenOptions.def
    clang/include/clang/Options/Options.td
    clang/lib/CodeGen/CGCall.cpp
    clang/test/CodeGenCXX/stack-reuse-miscompile.cpp
    clang/test/CodeGenCoroutines/pr59181.cpp

Removed: 
    clang/test/CodeGen/lifetime-call-temp.c
    clang/test/CodeGen/lifetime-invoke-c.c
    clang/test/CodeGenCXX/aggregate-lifetime-invoke.cpp
    clang/test/CodeGenCXX/amdgcn-call-with-aggarg.cc


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8edc271b9ba0f..f31e1c343e8aa 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -86,15 +86,6 @@ Potentially Breaking Changes
   options-related code has been moved out of the Driver into a separate 
library.
 - The ``clangFrontend`` library no longer depends on ``clangDriver``, which may
   break downstream projects that relied on this transitive dependency.
-- Clang is now more precise with regards to the lifetime of temporary objects
-  such as when aggregates are passed by value to a function, resulting in
-  better sharing of stack slots and reduced stack usage. This change can lead
-  to use-after-scope related issues in code that unintentionally relied on the
-  previous behavior. If recompiling with ``-fsanitize=address`` shows a
-  use-after-scope warning, then this is likely the case, and the report printed
-  should be able to help users pinpoint where the use-after-scope is occurring.
-  Users can use ``-Xclang -sloppy-temporary-lifetimes`` to retain the old
-  behavior until they are able to find and resolve issues in their code.
 
 C/C++ Language Potentially Breaking Changes
 -------------------------------------------

diff  --git a/clang/include/clang/Basic/CodeGenOptions.def 
b/clang/include/clang/Basic/CodeGenOptions.def
index e7f5b4c9a08a9..76a6463881c6f 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -475,10 +475,6 @@ ENUM_CODEGENOPT(ZeroCallUsedRegs, ZeroCallUsedRegsKind,
 /// non-deleting destructors. (No effect on Microsoft ABI.)
 CODEGENOPT(CtorDtorReturnThis, 1, 0, Benign)
 
-/// Set via -Xclang -sloppy-temporary-lifetimes to disable emission of lifetime
-/// marker intrinsic calls.
-CODEGENOPT(NoLifetimeMarkersForTemporaries, 1, 0, Benign)
-
 /// Enables emitting Import Call sections on supported targets that can be used
 /// by the Windows kernel to enable import call optimization.
 CODEGENOPT(ImportCallOptimization, 1, 0, Benign)

diff  --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 02396fb9b4d2d..c6841937c8d39 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -8151,11 +8151,6 @@ def import_call_optimization : Flag<["-"], 
"import-call-optimization">,
 def replaceable_function: Joined<["-"], "loader-replaceable-function=">,
   MarshallingInfoStringVector<CodeGenOpts<"LoaderReplaceableFunctionNames">>;
 
-def sloppy_temporary_lifetimes
-    : Flag<["-"], "sloppy-temporary-lifetimes">,
-      HelpText<"Don't emit lifetime markers for temporary objects">,
-      MarshallingInfoFlag<CodeGenOpts<"NoLifetimeMarkersForTemporaries">>;
-
 } // let Visibility = [CC1Option]
 
 
//===----------------------------------------------------------------------===//

diff  --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 84d3229863fe9..4a9025b6e0b0f 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4960,27 +4960,7 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, 
const Expr *E,
     return;
   }
 
-  AggValueSlot ArgSlot = AggValueSlot::ignored();
-  // For arguments with aggregate type, create an alloca to store
-  // the value.  If the argument's type has a destructor, that destructor
-  // will run at the end of the full-expression; emit matching lifetime
-  // markers.
-  //
-  // FIXME: For types which don't have a destructor, consider using a
-  // narrower lifetime bound.
-  if (hasAggregateEvaluationKind(E->getType())) {
-    RawAddress ArgSlotAlloca = Address::invalid();
-    ArgSlot = CreateAggTemp(E->getType(), "agg.tmp", &ArgSlotAlloca);
-
-    // Emit a lifetime start/end for this temporary at the end of the full
-    // expression.
-    if (!CGM.getCodeGenOpts().NoLifetimeMarkersForTemporaries &&
-        EmitLifetimeStart(ArgSlotAlloca.getPointer()))
-      pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker,
-                                           ArgSlotAlloca);
-  }
-
-  args.add(EmitAnyExpr(E, ArgSlot), type);
+  args.add(EmitAnyExprToTemp(E), type);
 }
 
 QualType CodeGenFunction::getVarArgType(const Expr *Arg) {

diff  --git a/clang/test/CodeGen/lifetime-call-temp.c 
b/clang/test/CodeGen/lifetime-call-temp.c
deleted file mode 100644
index 3bc68b5e8024a..0000000000000
--- a/clang/test/CodeGen/lifetime-call-temp.c
+++ /dev/null
@@ -1,98 +0,0 @@
-// RUN: %clang -cc1 -triple x86_64-apple-macos -O1 -disable-llvm-passes %s \
-// RUN:   -emit-llvm -o - | FileCheck %s --implicit-check-not=llvm.lifetime
-// RUN: %clang -cc1 -xc++ -std=c++17 -triple x86_64-apple-macos -O1 \
-// RUN:   -disable-llvm-passes %s -emit-llvm -o - -Wno-return-type-c-linkage | 
\
-// RUN:   FileCheck %s --implicit-check-not=llvm.lifetime 
--check-prefixes=CHECK,CXX
-// RUN: %clang -cc1 -xobjective-c -triple x86_64-apple-macos -O1 \
-// RUN:   -disable-llvm-passes %s -emit-llvm -o - | \
-// RUN:   FileCheck %s --implicit-check-not=llvm.lifetime 
--check-prefixes=CHECK,OBJC
-// RUN: %clang -cc1 -triple x86_64-apple-macos -O1 -disable-llvm-passes %s \
-// RUN:   -emit-llvm -o - -sloppy-temporary-lifetimes | \
-// RUN:   FileCheck %s --implicit-check-not=llvm.lifetime 
--check-prefixes=SLOPPY
-
-typedef struct { int x[100]; } aggregate;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void takes_aggregate(aggregate);
-aggregate gives_aggregate();
-
-// CHECK-LABEL: define void @t1
-void t1() {
-  takes_aggregate(gives_aggregate());
-
-  // CHECK: [[AGGTMP:%.*]] = alloca %struct.aggregate, align 8
-  // CHECK: call void @llvm.lifetime.start.p0(ptr [[AGGTMP]])
-  // CHECK: call void{{.*}} @gives_aggregate(ptr{{.*}}sret(%struct.aggregate) 
align 4 [[AGGTMP]])
-  // CHECK: call void @takes_aggregate(ptr noundef byval(%struct.aggregate) 
align 8 [[AGGTMP]])
-  // CHECK: call void @llvm.lifetime.end.p0(ptr [[AGGTMP]])
-
-  // SLOPPY: [[AGGTMP:%.*]] = alloca %struct.aggregate, align 8
-  // SLOPPY-NEXT: call void (ptr, ...) 
@gives_aggregate(ptr{{.*}}sret(%struct.aggregate) align 4 [[AGGTMP]])
-  // SLOPPY-NEXT: call void @takes_aggregate(ptr noundef 
byval(%struct.aggregate) align 8 [[AGGTMP]])
-}
-
-// CHECK: declare {{.*}}llvm.lifetime.start
-// CHECK: declare {{.*}}llvm.lifetime.end
-
-#ifdef __cplusplus
-// CXX: define void @t2
-void t2() {
-  struct S {
-    S(aggregate) {}
-  };
-  S{gives_aggregate()};
-
-  // CXX: [[AGG:%.*]] = alloca %struct.aggregate
-  // CXX: call void @llvm.lifetime.start.p0(ptr [[AGG]]
-  // CXX: call void @gives_aggregate(ptr{{.*}}sret(%struct.aggregate) align 4 
[[AGG]])
-  // CXX: call void @_ZZ2t2EN1SC1E9aggregate(ptr {{.*}}, ptr {{.*}} 
byval(%struct.aggregate) align 8 [[AGG]])
-  // CXX: call void @llvm.lifetime.end.p0(ptr [[AGG]]
-}
-
-struct Dtor {
-  ~Dtor();
-};
-
-void takes_dtor(Dtor);
-Dtor gives_dtor();
-
-// CXX: define void @t3
-void t3() {
-  takes_dtor(gives_dtor());
-
-  // CXX: [[AGG:%.*]] = alloca %struct.Dtor
-  // CXX: call void @llvm.lifetime.start.p0(ptr [[AGG]])
-  // CXX: call void @gives_dtor(ptr{{.*}}sret(%struct.Dtor) align 1 [[AGG]])
-  // CXX: call void @takes_dtor(ptr noundef [[AGG]])
-  // CXX: call void @_ZN4DtorD1Ev(ptr {{.*}} [[AGG]])
-  // CXX: call void @llvm.lifetime.end.p0(ptr [[AGG]])
-  // CXX: ret void
-}
-
-#endif
-
-#ifdef __OBJC__
-
-@interface X
--m:(aggregate)x;
-@end
-
-// OBJC: define void @t4
-void t4(X *x) {
-  [x m: gives_aggregate()];
-
-  // OBJC: [[AGG:%.*]] = alloca %struct.aggregate
-  // OBJC: call void @llvm.lifetime.start.p0(ptr [[AGG]]
-  // OBJC: call void{{.*}} @gives_aggregate(ptr{{.*}}sret(%struct.aggregate) 
align 4 [[AGGTMP]])
-  // OBJC: call {{.*}}@objc_msgSend
-  // OBJC: call void @llvm.lifetime.end.p0(ptr [[AGG]]
-}
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif

diff  --git a/clang/test/CodeGen/lifetime-invoke-c.c 
b/clang/test/CodeGen/lifetime-invoke-c.c
deleted file mode 100644
index f3573f4b2ec17..0000000000000
--- a/clang/test/CodeGen/lifetime-invoke-c.c
+++ /dev/null
@@ -1,50 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s -O1 
-disable-llvm-passes -fexceptions | FileCheck %s
-
-struct Trivial {
-  int x[100];
-};
-
-void cleanup(int *p) {}
-void func(struct Trivial t);
-struct Trivial gen(void);
-
-// CHECK-LABEL: define dso_local void @test()
-void test() {
-  int x __attribute__((cleanup(cleanup)));
-
-  // CHECK: %[[AGG1:.*]] = alloca %struct.Trivial
-  // CHECK: %[[AGG2:.*]] = alloca %struct.Trivial
-
-  // CHECK: call void @llvm.lifetime.start.p0(ptr %[[AGG1]])
-  // CHECK: invoke void @gen(ptr{{.*}} sret(%struct.Trivial){{.*}} %[[AGG1]])
-
-  // CHECK: invoke void @func(ptr{{.*}} %[[AGG1]])
-  // CHECK-NEXT: to label %[[CONT1:.*]] unwind label %[[LPAD1:.*]]
-
-  // CHECK: [[CONT1]]:
-  // CHECK-NOT: call void @llvm.lifetime.end.p0(ptr %[[AGG1]])
-
-  // CHECK: call void @llvm.lifetime.start.p0(ptr %[[AGG2]])
-  // CHECK: invoke void @gen(ptr{{.*}} sret(%struct.Trivial){{.*}} %[[AGG2]])
-  // CHECK: invoke void @func(ptr{{.*}} %[[AGG2]])
-  // CHECK-NEXT: to label %[[CONT2:.*]] unwind label %[[LPAD2:.*]]
-
-  // CHECK: [[CONT2]]:
-  // CHECK-DAG: call void @llvm.lifetime.end.p0(ptr %[[AGG2]])
-  // CHECK-DAG: call void @llvm.lifetime.end.p0(ptr %[[AGG1]])
-
-  // CHECK: [[LPAD1]]:
-  // CHECK: landingpad
-  // CHECK: br label %[[EHCLEANUP:.*]]
-
-  // CHECK: [[LPAD2]]:
-  // CHECK: landingpad
-  // CHECK: call void @llvm.lifetime.end.p0(ptr %[[AGG2]])
-  // CHECK: br label %[[EHCLEANUP]]
-
-  // CHECK: [[EHCLEANUP]]:
-  // CHECK: call void @llvm.lifetime.end.p0(ptr %[[AGG1]])
-  // CHECK: call void @cleanup
-  func(gen());
-  func(gen());
-}

diff  --git a/clang/test/CodeGenCXX/aggregate-lifetime-invoke.cpp 
b/clang/test/CodeGenCXX/aggregate-lifetime-invoke.cpp
deleted file mode 100644
index 32af6b51fe9c8..0000000000000
--- a/clang/test/CodeGenCXX/aggregate-lifetime-invoke.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s -O1 
-fexceptions -fcxx-exceptions | FileCheck %s
-
-extern "C" {
-
-struct Trivial {
-  int x[100];
-};
-
-void func_that_throws(Trivial t);
-
-// CHECK-LABEL: define{{.*}} void @test()
-void test() {
-  // CHECK: %[[AGG1:.*]] = alloca %struct.Trivial
-  // CHECK: %[[AGG2:.*]] = alloca %struct.Trivial
-
-  // CHECK: call void @llvm.lifetime.start.p0(ptr{{.*}} %[[AGG1]])
-  // CHECK: invoke void @func_that_throws(ptr{{.*}} %[[AGG1]])
-  // CHECK-NEXT: to label %[[CONT1:.*]] unwind label %[[LPAD1:.*]]
-
-  // CHECK: [[CONT1]]:
-  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr{{.*}} %[[AGG2]])
-  // CHECK: invoke void @func_that_throws(ptr{{.*}} %[[AGG2]])
-  // CHECK-NEXT: to label %[[CONT2:.*]] unwind label %[[LPAD2:.*]]
-
-  // CHECK: [[CONT2]]:
-  // CHECK-DAG: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG2]])
-  // CHECK-DAG: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG1]])
-  // CHECK: br label %[[TRY_CONT:.*]]
-
-  // CHECK: [[LPAD1]]:
-  // CHECK: landingpad
-  // CHECK: br label %[[EHCLEANUP:.*]]
-
-  // CHECK: [[LPAD2]]:
-  // CHECK: landingpad
-  // CHECK: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG2]])
-  // CHECK: br label %[[EHCLEANUP]]
-
-  // CHECK: [[EHCLEANUP]]:
-  // CHECK: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG1]])
-  try {
-    func_that_throws(Trivial{0});
-    func_that_throws(Trivial{0});
-  } catch (...) {
-  }
-}
-} // end extern "C"

diff  --git a/clang/test/CodeGenCXX/amdgcn-call-with-aggarg.cc 
b/clang/test/CodeGenCXX/amdgcn-call-with-aggarg.cc
deleted file mode 100644
index 9b598a48f6436..0000000000000
--- a/clang/test/CodeGenCXX/amdgcn-call-with-aggarg.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm -O3 
-disable-llvm-passes -o - %s | FileCheck %s
-
-struct A {
-  float x, y, z, w;
-};
-
-void foo(A a);
-
-// CHECK-LABEL: @_Z4testv
-// CHECK:         [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 4, addrspace(5)
-// CHECK-NEXT:    [[AGG_TMP:%.*]] = alloca [[STRUCT_A]], align 4, addrspace(5)
-// CHECK-NEXT:    [[A_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A]] to 
ptr
-// CHECK-NEXT:    [[AGG_TMP_ASCAST:%.*]] = addrspacecast ptr addrspace(5) 
[[AGG_TMP]] to ptr
-// CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 16, ptr addrspace(5) 
[[A]]) #[[ATTR4:[0-9]+]]
-// CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 16, ptr addrspace(5) 
[[AGG_TMP]]) #[[ATTR4]]
-void test() {
-  A a;
-  foo(a);
-}

diff  --git a/clang/test/CodeGenCXX/stack-reuse-miscompile.cpp 
b/clang/test/CodeGenCXX/stack-reuse-miscompile.cpp
index 50c374d2710f4..67fa9f9c9cd98 100644
--- a/clang/test/CodeGenCXX/stack-reuse-miscompile.cpp
+++ b/clang/test/CodeGenCXX/stack-reuse-miscompile.cpp
@@ -26,8 +26,6 @@ const char * f(S s)
 // CHECK: [[T2:%.*]] = alloca %class.T, align 4
 // CHECK: [[T3:%.*]] = alloca %class.T, align 4
 //
-// CHECK: [[AGG:%.*]] = alloca %class.S, align 4
-//
 // FIXME: We could defer starting the lifetime of the return object of concat
 // until the call.
 // CHECK: call void @llvm.lifetime.start.p0(ptr [[T1]])
@@ -36,12 +34,10 @@ const char * f(S s)
 // CHECK: [[T4:%.*]] = call noundef ptr @_ZN1TC1EPKc(ptr {{[^,]*}} [[T2]], ptr 
noundef @.str)
 //
 // CHECK: call void @llvm.lifetime.start.p0(ptr [[T3]])
-// CHECK: call void @llvm.lifetime.start.p0(ptr [[AGG]])
 // CHECK: [[T5:%.*]] = call noundef ptr @_ZN1TC1E1S(ptr {{[^,]*}} [[T3]], [2 x 
i32] %{{.*}})
 //
 // CHECK: call void @_ZNK1T6concatERKS_(ptr dead_on_unwind writable 
sret(%class.T) align 4 [[T1]], ptr {{[^,]*}} [[T2]], ptr noundef nonnull align 
4 dereferenceable(16) [[T3]])
 // CHECK: [[T6:%.*]] = call noundef ptr @_ZNK1T3strEv(ptr {{[^,]*}} [[T1]])
-// CHECK: call void @llvm.lifetime.end.p0(ptr [[AGG]])
 //
 // CHECK: call void @llvm.lifetime.end.p0(
 // CHECK: call void @llvm.lifetime.end.p0(

diff  --git a/clang/test/CodeGenCoroutines/pr59181.cpp 
b/clang/test/CodeGenCoroutines/pr59181.cpp
index a68a61984f981..21e784e0031de 100644
--- a/clang/test/CodeGenCoroutines/pr59181.cpp
+++ b/clang/test/CodeGenCoroutines/pr59181.cpp
@@ -49,7 +49,6 @@ void foo() {
 }
 
 // CHECK: cleanup.cont:{{.*}}
-// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[AGG:%agg.tmp]])
 // CHECK-NEXT: load i8
 // CHECK-NEXT: trunc
 // CHECK-NEXT: store i1 false
@@ -58,6 +57,3 @@ void foo() {
 // CHECK-NOT: call void @llvm.lifetime
 // CHECK: call void @llvm.coro.await.suspend.void(
 // CHECK-NEXT: %{{[0-9]+}} = call i8 @llvm.coro.suspend(
-
-// CHECK-LABEL: cond.end:
-// check call @llvm.lifetime.end.p0(ptr [[AGG]])


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to