// RUN: %clang_cc1 %s -std=c++11 -O1 -DWITH_DTOR -triple x86_64 -emit-llvm -o - | FileCheck -check-prefix=CHECK-DTOR %s // RUN: %clang_cc1 %s -std=c++11 -O1 -triple x86_64 -emit-llvm -o - | FileCheck -check-prefix=CHECK-NO-DTOR %s struct A { A(); #ifdef WITH_DTOR ~A(); #endif char a[1024]; operator bool() const; }; template <typename T> void Foo(T &&); template <typename T> void Bar(T &&); template <typename T> T Baz(); void Test1() { // CHECK-DTOR-LABEL: Test1 // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR:[0-9]+]]) // CHECK-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR:[^ ]+]]) // CHECK-DTOR: call void @_Z3FooIRK1AEvOT_ // CHECK-DTOR: call void @_ZN1AD1Ev(%struct.A* nonnull %[[VAR]]) // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR]]) // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR:[0-9]+]]) // CHECK-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR:[^ ]+]]) // CHECK-DTOR: call void @_Z3FooIRK1AEvOT_ // CHECK-DTOR: call void @_ZN1AD1Ev(%struct.A* nonnull %[[VAR]]) // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR]]) // CHECK-DTOR: } // CHECK-NO-DTOR-LABEL: Test1 // CHECK-NO-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR:[0-9]+]]) // CHECK-NO-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR:[^ ]+]]) // CHECK-NO-DTOR: call void @_Z3FooIRK1AEvOT_ // CHECK-NO-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR]]) // CHECK-NO-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR:[0-9]+]]) // CHECK-NO-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR:[^ ]+]]) // CHECK-NO-DTOR: call void @_Z3FooIRK1AEvOT_ // CHECK-NO-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR]]) // CHECK-NO-DTOR: } { const A &a = A{}; Foo(a); } { const A &a = A{}; Foo(a); } } void Test2() { // CHECK-DTOR-LABEL: Test2 // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR1:[0-9]+]]) // CHECK-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR1:[^ ]+]]) // CHECK-DTOR: call void @_Z3FooIRK1AEvOT_ // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR2:[0-9]+]]) // CHECK-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR2:[^ ]+]]) // CHECK-DTOR: call void @_Z3FooIRK1AEvOT_ // CHECK-DTOR: call void @_ZN1AD1Ev(%struct.A* nonnull %[[VAR2]]) // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR2]]) // CHECK-DTOR: call void @_ZN1AD1Ev(%struct.A* nonnull %[[VAR1]]) // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR1]]) // CHECK-DTOR: } // CHECK-NO-DTOR-LABEL: Test2 // CHECK-NO-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR1:[0-9]+]]) // CHECK-NO-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR1:[^ ]+]]) // CHECK-NO-DTOR: call void @_Z3FooIRK1AEvOT_ // CHECK-NO-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR2:[0-9]+]]) // CHECK-NO-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR2:[^ ]+]]) // CHECK-NO-DTOR: call void @_Z3FooIRK1AEvOT_ // CHECK-NO-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR2]]) // CHECK-NO-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR1]]) // CHECK-NO-DTOR: } const A &a = A{}; Foo(a); const A &b = A{}; Foo(b); } void Test3() { // CHECK-DTOR-LABEL: Test3 // CHECK-DTOR: call void @llvm.lifetime.start // CHECK-DTOR: call void @llvm.lifetime.start // if.then: // CHECK-DTOR: call void @llvm.lifetime.end // cleanup: // CHECK-DTOR: call void @llvm.lifetime.end // cleanup: // CHECK-DTOR: call void @llvm.lifetime.end // CHECK-DTOR: } const A &a = A{}; if (const A &b = A(a)) { Foo(b); return; } Bar(a); } void Test4() { // CHECK-DTOR-LABEL: Test4 // CHECK-DTOR: call void @llvm.lifetime.start // for.cond.cleanup: // CHECK-DTOR: call void @llvm.lifetime.end // for.body: // CHECK-DTOR: } for (const A &a = A{}; a;) { Foo(a); } } int Test5() { // CHECK-DTOR-LABEL: Test5 // CHECK-DTOR: call void @llvm.lifetime.start // CHECK-DTOR: call i32 @_Z3BazIiET_v() // CHECK-DTOR: store // CHECK-DTOR: call void @_Z3FooIRKiEvOT_ // CHECK-DTOR: load // CHECK-DTOR: call void @llvm.lifetime.end // CHECK-DTOR: } const int &a = Baz<int>(); Foo(a); return a; } void Test6() { // CHECK-DTOR-LABEL: Test6 // CHECK-DTOR: call void @llvm.lifetime.start(i64 {{[0-9]+}}, i8* %[[ADDR:[0-9]+]]) // CHECK-DTOR: call i32 @_Z3BazIiET_v() // CHECK-DTOR: store // CHECK-DTOR: call void @_Z3FooIiEvOT_ // CHECK-DTOR: call void @llvm.lifetime.end(i64 {{[0-9]+}}, i8* %[[ADDR]]) // CHECK-DTOR: call void @llvm.lifetime.start(i64 {{[0-9]+}}, i8* %[[ADDR:[0-9]+]]) // CHECK-DTOR: call i32 @_Z3BazIiET_v() // CHECK-DTOR: store // CHECK-DTOR: call void @_Z3FooIiEvOT_ // CHECK-DTOR: call void @llvm.lifetime.end(i64 {{[0-9]+}}, i8* %[[ADDR]]) // CHECK-DTOR: } Foo(Baz<int>()); Foo(Baz<int>()); } void Test7() { // CHECK-DTOR-LABEL: Test7 // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR:[0-9]+]]) // CHECK-DTOR: call void @_Z3BazI1AET_v({{.*}} %[[SLOT:[^ ]+]]) // CHECK-DTOR: call void @_Z3FooI1AEvOT_({{.*}} %[[SLOT]]) // CHECK-DTOR: call void @_ZN1AD1Ev(%struct.A* nonnull %[[SLOT]]) // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR]]) // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR:[0-9]+]]) // CHECK-DTOR: call void @_Z3BazI1AET_v({{.*}} %[[SLOT:[^ ]+]]) // CHECK-DTOR: call void @_Z3FooI1AEvOT_({{.*}} %[[SLOT]]) // CHECK-DTOR: call void @_ZN1AD1Ev(%struct.A* nonnull %[[SLOT]]) // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR]]) // CHECK-DTOR: } Foo(Baz<A>()); Foo(Baz<A>()); }