Re: [PATCH] D20499: [Temporary, Lifetime] Add lifetime marks for temporaries
timshen added a comment. ...and r274396 to remove all of the checks for symbolic labels, which are not generated by release builds, nor controlled by a runtime-flag. Repository: rL LLVM http://reviews.llvm.org/D20499 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D20499: [Temporary, Lifetime] Add lifetime marks for temporaries
timshen added a comment. Also committed r274387 to remove unnecessary CHECks. It seems to cause problems in certain platforms. Repository: rL LLVM http://reviews.llvm.org/D20499 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D20499: [Temporary, Lifetime] Add lifetime marks for temporaries
This revision was automatically updated to reflect the committed changes. timshen marked an inline comment as done. Closed by commit rL274385: [Temporary, Lifetime] Add lifetime marks for temporaries (authored by timshen). Changed prior to commit: http://reviews.llvm.org/D20499?vs=62433=62543#toc Repository: rL LLVM http://reviews.llvm.org/D20499 Files: cfe/trunk/lib/CodeGen/CGCleanup.cpp cfe/trunk/lib/CodeGen/CGDecl.cpp cfe/trunk/lib/CodeGen/CGExpr.cpp cfe/trunk/lib/CodeGen/CodeGenFunction.h cfe/trunk/lib/CodeGen/EHScopeStack.h cfe/trunk/test/CodeGen/temporary-lifetime-exceptions.cpp cfe/trunk/test/CodeGen/temporary-lifetime.cpp cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp Index: cfe/trunk/test/CodeGen/temporary-lifetime-exceptions.cpp === --- cfe/trunk/test/CodeGen/temporary-lifetime-exceptions.cpp +++ cfe/trunk/test/CodeGen/temporary-lifetime-exceptions.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 %s -fexceptions -fcxx-exceptions -std=c++11 -O1 -triple x86_64 -emit-llvm -o - | FileCheck %s + +// lifetime.end should be invoked even if the destructor doesn't run due to an +// exception thrown from previous ctor call. + +struct A { A(); ~A(); }; +A Baz(const A&); + +void Test1() { + // CHECK-LABEL: @_Z5Test1v( + // CHECK: getelementptr + // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* [[TMP:[^ ]+]]) + // CHECK-NEXT: getelementptr + // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* [[TMP1:[^ ]+]]) + + // Normal exit + // CHECK: call void @llvm.lifetime.end(i64 1, i8* [[TMP1]]) + // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* [[TMP]]) + + // Exception exit + // CHECK: call void @llvm.lifetime.end(i64 1, i8* [[TMP1]]) + // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* [[TMP]]) + Baz(Baz(A())); +} Index: cfe/trunk/test/CodeGen/temporary-lifetime.cpp === --- cfe/trunk/test/CodeGen/temporary-lifetime.cpp +++ cfe/trunk/test/CodeGen/temporary-lifetime.cpp @@ -0,0 +1,165 @@ +// 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 +void Foo(T &&); + +template +void Bar(T &&); + +template +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{}; +Foo(a); + } + { +const 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_ +
Re: [PATCH] D20499: [Temporary, Lifetime] Add lifetime marks for temporaries
timshen updated this revision to Diff 62433. timshen added a comment. Done. Added a new testcase to ensure the correct behavior with exceptions turned on. http://reviews.llvm.org/D20499 Files: lib/CodeGen/CGCleanup.cpp lib/CodeGen/CGDecl.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/EHScopeStack.h test/CodeGen/temporary-lifetime-exceptions.cpp test/CodeGen/temporary-lifetime.cpp test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp Index: test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp === --- test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 %s -// RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-optzns %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-LIFETIME %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O0 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-optzns %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O3 -check-prefix WIN32-LIFETIME %s struct A { A(); @@ -95,40 +95,78 @@ return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow()); } -// WIN32-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { -// WIN32: alloca i1 -// WIN32: %[[arg1_cond:.*]] = alloca i1 +// WIN32-O0-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { +// WIN32-O0: alloca i1 +// WIN32-O0: %[[arg1_cond:.*]] = alloca i1 //Start all four cleanups as deactivated. -// WIN32: store i1 false -// WIN32: store i1 false -// WIN32: store i1 false -// WIN32: store i1 false -// WIN32: br i1 +// WIN32-O0: store i1 false +// WIN32-O0: store i1 false +// WIN32-O0: store i1 false +// WIN32-O0: store i1 false +// WIN32-O0: br i1 //True condition. -// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true -// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true, i1* %[[arg1_cond]] -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true -// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true -// WIN32: store i1 false, i1* %[[arg1_cond]] -// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// WIN32-O0: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true +// WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z" +// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true, i1* %[[arg1_cond]] +// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true +// WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z" +// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true +// WIN32-O0: store i1 false, i1* %[[arg1_cond]] +// WIN32-O0: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" //False condition. -// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"() +// WIN32-O0: invoke i32 @"\01?CouldThrow@@YAHXZ"() //Two normal cleanups for TakeRef args. -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) -// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" -// WIN32: ret i32 +// WIN32-O0: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32-O0-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32-O0: ret i32 // //Somewhere in the landing pad soup, we conditionally destroy arg1. -// WIN32: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]] -// WIN32: br i1 %[[isactive]] -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) -// WIN32: } +// WIN32-O0: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]] +// WIN32-O0: br i1 %[[isactive]] +// WIN32-O0: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32-O0: } + +// WIN32-O3-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { +// WIN32-O3: alloca i1 +// WIN32-O3: alloca i1 +// WIN32-O3: %[[arg1_cond:.*]] = alloca i1 +//Start all four cleanups as deactivated. +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: br i1 +//True condition. +// WIN32-O3: call x86_thiscallcc
Re: [PATCH] D20499: [Temporary, Lifetime] Add lifetime marks for temporaries
rsmith added inline comments. Comment at: lib/CodeGen/CGExpr.cpp:438 @@ -426,1 +437,3 @@ +} EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true); +if (Size) { Seems like you should push the cleanup before you emit the initializer; the cleanup should run if the initializer throws. http://reviews.llvm.org/D20499 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D20499: [Temporary, Lifetime] Add lifetime marks for temporaries
timshen added a comment. I'm looking at some internal test failures caused by this patch. http://reviews.llvm.org/D20499 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D20499: [Temporary, Lifetime] Add lifetime marks for temporaries
vitalybuka added a comment. Is anything blocking us on this review? http://reviews.llvm.org/D20499 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D20499: [Temporary, Lifetime] Add lifetime marks for temporaries
timshen marked an inline comment as done. timshen added a comment. http://reviews.llvm.org/D20499 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D20499: [Temporary, Lifetime] Add lifetime marks for temporaries
timshen updated this revision to Diff 58734. timshen added a comment. Herald added a subscriber: klimek. Used pushFullExprCleanup. microsoft-abi-eh-cleanups.cpp fails because each pushFullExprCleanup introduces a new cleanup.cond variable, even if that pushFullExprCleanup is just for lifetime marks. With LLVM optimizations turned on (e.g. -O1), these cleanup.conds get eliminated; -O0 doesn't generate lifetime marks. So there is no practical affect unless "-disable-llvm-optzns -O3" -- as the test does -- are passed together. http://reviews.llvm.org/D20499 Files: include/clang/AST/ExprCXX.h include/clang/AST/Stmt.h include/clang/Sema/CleanupInfo.h include/clang/Sema/ScopeInfo.h include/clang/Sema/Sema.h lib/AST/Expr.cpp lib/AST/ExprCXX.cpp lib/Analysis/Consumed.cpp lib/CodeGen/CGCleanup.cpp lib/CodeGen/CGDecl.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/EHScopeStack.h lib/Sema/Sema.cpp lib/Sema/SemaCast.cpp lib/Sema/SemaCoroutine.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaExprObjC.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaLambda.cpp lib/Sema/SemaOpenMP.cpp lib/Sema/SemaStmt.cpp lib/Serialization/ASTReaderStmt.cpp lib/Serialization/ASTWriterStmt.cpp test/CodeGen/temporary-lifetime.cpp test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp unittests/ASTMatchers/ASTMatchersNodeTest.cpp Index: unittests/ASTMatchers/ASTMatchersNodeTest.cpp === --- unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -999,8 +999,8 @@ EXPECT_TRUE(matches("struct Foo { ~Foo(); };" "const Foo f = Foo();", varDecl(hasInitializer(exprWithCleanups(); - EXPECT_FALSE(matches("struct Foo { };" - "const Foo f = Foo();", + EXPECT_FALSE(matches("struct Foo { }; Foo a;" + "const Foo f = a;", varDecl(hasInitializer(exprWithCleanups(); } Index: test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp === --- test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 %s -// RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-optzns %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-LIFETIME %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O0 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-optzns %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O3 -check-prefix WIN32-LIFETIME %s struct A { A(); @@ -95,40 +95,78 @@ return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow()); } -// WIN32-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { -// WIN32: alloca i1 -// WIN32: %[[arg1_cond:.*]] = alloca i1 +// WIN32-O0-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { +// WIN32-O0: alloca i1 +// WIN32-O0: %[[arg1_cond:.*]] = alloca i1 //Start all four cleanups as deactivated. -// WIN32: store i1 false -// WIN32: store i1 false -// WIN32: store i1 false -// WIN32: store i1 false -// WIN32: br i1 +// WIN32-O0: store i1 false +// WIN32-O0: store i1 false +// WIN32-O0: store i1 false +// WIN32-O0: store i1 false +// WIN32-O0: br i1 //True condition. -// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true -// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true, i1* %[[arg1_cond]] -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true -// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true -// WIN32: store i1 false, i1* %[[arg1_cond]] -// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// WIN32-O0: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true +// WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z" +// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true, i1* %[[arg1_cond]] +// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true +// WIN32-O0: invoke void
Re: [PATCH] D20499: [Temporary, Lifetime] Add lifetime marks for temporaries
timshen updated this revision to Diff 58738. timshen added a comment. Upload the rebased patch. http://reviews.llvm.org/D20499 Files: lib/CodeGen/CGCleanup.cpp lib/CodeGen/CGDecl.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/EHScopeStack.h test/CodeGen/temporary-lifetime.cpp test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp Index: test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp === --- test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 %s -// RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-optzns %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-LIFETIME %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O0 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-optzns %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O3 -check-prefix WIN32-LIFETIME %s struct A { A(); @@ -95,40 +95,78 @@ return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow()); } -// WIN32-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { -// WIN32: alloca i1 -// WIN32: %[[arg1_cond:.*]] = alloca i1 +// WIN32-O0-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { +// WIN32-O0: alloca i1 +// WIN32-O0: %[[arg1_cond:.*]] = alloca i1 //Start all four cleanups as deactivated. -// WIN32: store i1 false -// WIN32: store i1 false -// WIN32: store i1 false -// WIN32: store i1 false -// WIN32: br i1 +// WIN32-O0: store i1 false +// WIN32-O0: store i1 false +// WIN32-O0: store i1 false +// WIN32-O0: store i1 false +// WIN32-O0: br i1 //True condition. -// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true -// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true, i1* %[[arg1_cond]] -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true -// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true -// WIN32: store i1 false, i1* %[[arg1_cond]] -// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// WIN32-O0: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true +// WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z" +// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true, i1* %[[arg1_cond]] +// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true +// WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z" +// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true +// WIN32-O0: store i1 false, i1* %[[arg1_cond]] +// WIN32-O0: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" //False condition. -// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"() +// WIN32-O0: invoke i32 @"\01?CouldThrow@@YAHXZ"() //Two normal cleanups for TakeRef args. -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) -// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" -// WIN32: ret i32 +// WIN32-O0: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32-O0-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32-O0: ret i32 // //Somewhere in the landing pad soup, we conditionally destroy arg1. -// WIN32: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]] -// WIN32: br i1 %[[isactive]] -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) -// WIN32: } +// WIN32-O0: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]] +// WIN32-O0: br i1 %[[isactive]] +// WIN32-O0: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32-O0: } + +// WIN32-O3-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { +// WIN32-O3: alloca i1 +// WIN32-O3: alloca i1 +// WIN32-O3: %[[arg1_cond:.*]] = alloca i1 +//Start all four cleanups as deactivated. +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: br i1 +//True condition. +// WIN32-O3: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O3: store i1 true +// WIN32-O3: invoke void
Re: [PATCH] D20499: [Temporary, Lifetime] Add lifetime marks for temporaries
timshen updated this revision to Diff 58737. timshen added a comment. Upload the rebased patch. http://reviews.llvm.org/D20499 Files: include/clang/AST/ExprCXX.h include/clang/AST/Stmt.h include/clang/Sema/CleanupInfo.h include/clang/Sema/ScopeInfo.h include/clang/Sema/Sema.h lib/AST/Expr.cpp lib/AST/ExprCXX.cpp lib/Analysis/Consumed.cpp lib/CodeGen/CGExprConstant.cpp lib/Sema/Sema.cpp lib/Sema/SemaCast.cpp lib/Sema/SemaCoroutine.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaExprObjC.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaLambda.cpp lib/Sema/SemaOpenMP.cpp lib/Sema/SemaStmt.cpp lib/Serialization/ASTReaderStmt.cpp lib/Serialization/ASTWriterStmt.cpp unittests/ASTMatchers/ASTMatchersNodeTest.cpp Index: unittests/ASTMatchers/ASTMatchersNodeTest.cpp === --- unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -999,8 +999,8 @@ EXPECT_TRUE(matches("struct Foo { ~Foo(); };" "const Foo f = Foo();", varDecl(hasInitializer(exprWithCleanups(); - EXPECT_FALSE(matches("struct Foo { };" - "const Foo f = Foo();", + EXPECT_FALSE(matches("struct Foo { }; Foo a;" + "const Foo f = a;", varDecl(hasInitializer(exprWithCleanups(); } Index: lib/Serialization/ASTWriterStmt.cpp === --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -1430,7 +1430,8 @@ Record.push_back(E->getNumObjects()); for (unsigned i = 0, e = E->getNumObjects(); i != e; ++i) Record.AddDeclRef(E->getObject(i)); - + + Record.push_back(E->cleanupsHaveSideEffects()); Record.AddStmt(E->getSubExpr()); Code = serialization::EXPR_EXPR_WITH_CLEANUPS; } Index: lib/Serialization/ASTReaderStmt.cpp === --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -1448,6 +1448,7 @@ E->getTrailingObjects()[i] = ReadDeclAs(Record, Idx); + E->ExprWithCleanupsBits.CleanupsHaveSideEffects = Record[Idx++]; E->SubExpr = Reader.ReadSubExpr(); } Index: lib/Sema/SemaStmt.cpp === --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -1518,6 +1518,10 @@ // variables Increment and DRE. bool ProcessIterationStmt(Sema , Stmt* Statement, bool , DeclRefExpr *) { +if (auto Cleanups = dyn_cast(Statement)) + if (!Cleanups->cleanupsHaveSideEffects()) +Statement = Cleanups->getSubExpr(); + if (UnaryOperator *UO = dyn_cast(Statement)) { switch (UO->getOpcode()) { default: return false; @@ -2472,6 +2476,10 @@ QualType VariableType = VD->getType(); + if (auto Cleanups = dyn_cast(InitExpr)) +if (!Cleanups->cleanupsHaveSideEffects()) + InitExpr = Cleanups->getSubExpr(); + const MaterializeTemporaryExpr *MTE = dyn_cast(InitExpr); Index: lib/Sema/SemaOpenMP.cpp === --- lib/Sema/SemaOpenMP.cpp +++ lib/Sema/SemaOpenMP.cpp @@ -3792,6 +3792,10 @@ } return true; } + if (auto *ExprTemp = dyn_cast(S)) +if (!ExprTemp->cleanupsHaveSideEffects()) + S = ExprTemp->getSubExpr(); + InitSrcRange = S->getSourceRange(); if (Expr *E = dyn_cast(S)) S = E->IgnoreParens(); @@ -3979,6 +3983,10 @@ SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl; return true; } + if (auto *ExprTemp = dyn_cast(S)) +if (!ExprTemp->cleanupsHaveSideEffects()) + S = ExprTemp->getSubExpr(); + IncrementSrcRange = S->getSourceRange(); S = S->IgnoreParens(); if (auto UO = dyn_cast(S)) { Index: lib/Sema/SemaLambda.cpp === --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -1500,7 +1500,7 @@ SourceRange IntroducerRange; bool ExplicitParams; bool ExplicitResultType; - bool LambdaExprNeedsCleanups; + CleanupInfo LambdaCleanup; bool ContainsUnexpandedParameterPack; SmallVector ArrayIndexVars; SmallVectorArrayIndexStarts; @@ -1510,7 +1510,7 @@ IntroducerRange = LSI->IntroducerRange; ExplicitParams = LSI->ExplicitParams; ExplicitResultType = !LSI->HasImplicitReturnType; -LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups; +LambdaCleanup = LSI->Cleanup; ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack; CallOperator->setLexicalDeclContext(Class); @@ -1591,9 +1591,8 @@ CheckCompletedCXXClass(Class); } - if (LambdaExprNeedsCleanups) -ExprNeedsCleanups = true; - + Cleanup.mergeFrom(LambdaCleanup); + LambdaExpr
Re: [PATCH] D20499: [Temporary, Lifetime] Add lifetime marks for temporaries
rsmith added inline comments. Comment at: lib/CodeGen/CGExpr.cpp:446 @@ +445,3 @@ + case SD_FullExpression: +EHStack.pushCleanup(NormalEHLifetimeMarker, Object, + Size); This should use pushFullExprCleanup. http://reviews.llvm.org/D20499 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits