diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -2289,6 +2289,9 @@ } void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { + // Pop all cleanup blocks at the end of the asm statement. + CodeGenFunction::RunCleanupsScope Cleanups(*this); + // Assemble the final asm string. std::string AsmString = S.generateAsmString(getContext()); diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -325,7 +325,6 @@ ProhibitAttributes(GNUAttrs); bool msAsm = false; Res = ParseAsmStatement(msAsm); - Res = Actions.ActOnFinishFullStmt(Res.get()); if (msAsm) return Res; SemiError = "asm"; break; diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -733,6 +733,9 @@ } if (NS->isAsmGoto()) setFunctionHasBranchIntoScope(); + + CleanupVarDeclMarking(); + DiscardCleanupsInEvaluationContext(); return NS; } diff --git a/clang/test/CodeGenCXX/asm.cpp b/clang/test/CodeGenCXX/asm.cpp --- a/clang/test/CodeGenCXX/asm.cpp +++ b/clang/test/CodeGenCXX/asm.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple i386-unknown-unknown -fblocks -emit-llvm %s -o - | FileCheck %s + +// CHECK: %[[STRUCT_A:.*]] = type { i8 } struct A { @@ -12,3 +14,39 @@ asm("" : : "r"(foo(a)) ); // rdar://8540491 // CHECK: call void @_ZN1AD1Ev } + +namespace TestTemplate { +// Check that the temporary is destructed after the first asm statement. + +// CHECK: define {{.*}}void @_ZN12TestTemplate4foo0IvEEvR1A( +// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_A]], +// CHECK: %[[CALL:.*]] = call noundef i32 @_Z3foo1A({{.*}}%[[AGG_TMP]]) +// CHECK: call void asm sideeffect "", "r,~{dirflag},~{fpsr},~{flags}"(i32 %[[CALL]]) +// CHECK: call void @_ZN1AD1Ev({{.*}}%[[AGG_TMP]]) +// CHECK: call void asm sideeffect "", + +template +void foo0(A &a) { + asm("" : : "r"(foo(a)) ); + asm(""); +} + +void test0(A &a) { foo0(a); } + +// Check that the block capture is destructed at the end of the enclosing scope. + +// CHECK: define {{.*}}void @_ZN12TestTemplate4foo1IvEEv1A( +// CHECK: %[[BLOCK:.*]] = alloca <{ ptr, i32, i32, ptr, ptr, %[[STRUCT_A]] }>, align 4 +// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, %[[STRUCT_A]] }>, ptr %[[BLOCK]], i32 0, i32 5 +// CHECK: call void asm sideeffect "", "r,~{dirflag},~{fpsr},~{flags}"(i32 %{{.*}}) +// CHECK: call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void @_ZN1AD1Ev({{.*}} %[[BLOCK_CAPTURED]]) + +template +void foo1(A a) { + asm("" : : "r"(^{ (void)a; return 0; }())); + asm(""); +} + +void test1(A &a) { foo1(a); } +} // namespace TestTemplate diff --git a/clang/test/CodeGenObjC/asm.m b/clang/test/CodeGenObjC/asm.m new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenObjC/asm.m @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fblocks -fobjc-arc -emit-llvm -o - %s | FileCheck %s + +// CHECK: %[[STRUCT_A:.*]] = type { ptr } + +typedef struct { + id f; +} A; + +id a; + +// Check that the compound literal is destructed at the end of the enclosing scope. + +// CHECK-LABEL: define void @foo0() +// CHECK: %[[_COMPOUNDLITERAL:.*]] = alloca %[[STRUCT_A]], align 8 +// CHECK: getelementptr inbounds %[[STRUCT_A]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 0 +// CHECK: %[[F1:.*]] = getelementptr inbounds %[[STRUCT_A]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 0 +// CHECK: %[[V2:.*]] = load ptr, ptr %[[F1]], align 8 +// CHECK: call void asm sideeffect "", "r,~{dirflag},~{fpsr},~{flags}"(ptr %[[V2]]) +// CHECK: call void asm sideeffect "", +// CHECK: call void @__destructor_8_s0(ptr %[[_COMPOUNDLITERAL]]) + +void foo0() { + asm("" : : "r"(((A){a}).f) ); + asm(""); +} diff --git a/clang/test/SemaTemplate/instantiate-expr-1.cpp b/clang/test/SemaTemplate/instantiate-expr-1.cpp --- a/clang/test/SemaTemplate/instantiate-expr-1.cpp +++ b/clang/test/SemaTemplate/instantiate-expr-1.cpp @@ -190,3 +190,19 @@ test_asm_tied(1.f); // expected-note {{instantiation of}} } } + +namespace TestAsmCleanup { +struct S { + operator int() const { return 1; } + ~S(); +}; + +template +void foo() { + __asm__ __volatile__("%[i]" + : + : [i] "r"(-S())); +} + +void test() { foo(); } +} // namespace TestAsmCleanup