ahatanak updated this revision to Diff 437248.
ahatanak added a comment.

Stop wrapping a `GCCAsmStmt` with an `ExprWithCleanups`. Instead, just pop the 
cleanups after the asm statement to destruct the temporaries.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125936/new/

https://reviews.llvm.org/D125936

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Sema/SemaCoroutine.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaStmtAsm.cpp
  clang/test/CodeGenCXX/asm.cpp
  clang/test/SemaTemplate/instantiate-expr-1.cpp

Index: clang/test/SemaTemplate/instantiate-expr-1.cpp
===================================================================
--- clang/test/SemaTemplate/instantiate-expr-1.cpp
+++ 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 <class T>
+void foo() {
+  __asm__ __volatile__("%[i]"
+                       :
+                       : [i] "r"(-S()));
+}
+
+void test() { foo<void>(); }
+} // namespace TestAsmCleanup
Index: clang/test/CodeGenCXX/asm.cpp
===================================================================
--- clang/test/CodeGenCXX/asm.cpp
+++ 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 {
+template <class T>
+void foo0(A &a) {
+  asm("" : : "r"(foo(a)) );
+  asm("");
+}
+
+// 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 "",
+
+void test0(A &a) { foo0<void>(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 <class T>
+void foo1(A a) {
+  asm("" : : "r"(^{ (void)a; return 0; }()));
+  asm("");
+}
+
+void test1(A &a) { foo1<void>(a); }
+} // namespace TestTemplate
Index: clang/lib/Sema/SemaStmtAsm.cpp
===================================================================
--- clang/lib/Sema/SemaStmtAsm.cpp
+++ clang/lib/Sema/SemaStmtAsm.cpp
@@ -733,6 +733,9 @@
   }
   if (NS->isAsmGoto())
     setFunctionHasBranchIntoScope();
+
+  CleanupVarDeclMarking();
+  DiscardCleanupsInEvaluationContext();
   return NS;
 }
 
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -7283,26 +7283,6 @@
   return E;
 }
 
-Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
-  assert(SubStmt && "sub-statement can't be null!");
-
-  CleanupVarDeclMarking();
-
-  if (!Cleanup.exprNeedsCleanups())
-    return SubStmt;
-
-  // FIXME: In order to attach the temporaries, wrap the statement into
-  // a StmtExpr; currently this is only used for asm statements.
-  // This is hacky, either create a new CXXStmtWithTemporaries statement or
-  // a new AsmStmtWithTemporaries.
-  CompoundStmt *CompStmt = CompoundStmt::Create(
-      Context, SubStmt, SourceLocation(), SourceLocation());
-  Expr *E = new (Context)
-      StmtExpr(CompStmt, Context.VoidTy, SourceLocation(), SourceLocation(),
-               /*FIXME TemplateDepth=*/0);
-  return MaybeCreateExprWithCleanups(E);
-}
-
 /// Process the expression contained within a decltype. For such expressions,
 /// certain semantic checks on temporaries are delayed until this point, and
 /// are omitted for the 'topmost' call in the decltype expression. If the
@@ -8803,12 +8783,6 @@
   return MaybeCreateExprWithCleanups(FullExpr);
 }
 
-StmtResult Sema::ActOnFinishFullStmt(Stmt *FullStmt) {
-  if (!FullStmt) return StmtError();
-
-  return MaybeCreateStmtWithCleanups(FullStmt);
-}
-
 Sema::IfExistsResult
 Sema::CheckMicrosoftIfExistsSymbol(Scope *S,
                                    CXXScopeSpec &SS,
Index: clang/lib/Sema/SemaCoroutine.cpp
===================================================================
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -1517,7 +1517,6 @@
   } else if (HasRVoid) {
     Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,
                                       /*IsImplicit*/false);
-    Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get());
     if (Fallthrough.isInvalid())
       return false;
   }
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -300,7 +300,6 @@
     ProhibitAttributes(Attrs);
     bool msAsm = false;
     Res = ParseAsmStatement(msAsm);
-    Res = Actions.ActOnFinishFullStmt(Res.get());
     if (msAsm) return Res;
     SemiError = "asm";
     break;
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -2286,6 +2286,10 @@
 }
 
 void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
+  // Temporaries created in GCC AsmStmts have to be destructed at the end of the
+  // statement.
+  CodeGenFunction::RunCleanupsScope Cleanups(*this);
+
   // Assemble the final asm string.
   std::string AsmString = S.generateAsmString(getContext());
 
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -6591,7 +6591,6 @@
   /// requires any cleanups, surround it with a ExprWithCleanups node.
   /// Otherwise, just returns the passed-in expression.
   Expr *MaybeCreateExprWithCleanups(Expr *SubExpr);
-  Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt);
   ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr);
 
   MaterializeTemporaryExpr *
@@ -6604,7 +6603,6 @@
   }
   ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC,
                                  bool DiscardedValue, bool IsConstexpr = false);
-  StmtResult ActOnFinishFullStmt(Stmt *Stmt);
 
   // Marks SS invalid if it represents an incomplete type.
   bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to