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

Add a flag to `StmtExpr` that indicates whether it needs cleanup.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D125936

Files:
  clang/include/clang/AST/Expr.h
  clang/include/clang/AST/Stmt.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/TreeTransform.h
  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,5 +1,7 @@
 // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s
 
+// CHECK: %[[STRUCT_A:.*]] = type { i8 }
+
 struct A
 {
     ~A();
@@ -12,3 +14,18 @@
     asm("" : : "r"(foo(a)) ); // rdar://8540491
     // CHECK: call void @_ZN1AD1Ev
 }
+
+namespace TestTemplate {
+template <class T>
+void bar(A &a) {
+  asm("" : : "r"(foo(a)) );
+}
+
+// CHECK: define {{.*}}void @_ZN12TestTemplate3barIvEEvR1A(
+// 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]])
+
+void test(A &a) { bar<void>(a); }
+} // namespace TestTemplate
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -2873,9 +2873,10 @@
   /// By default, performs semantic analysis to build the new expression.
   /// Subclasses may override this routine to provide different behavior.
   ExprResult RebuildStmtExpr(SourceLocation LParenLoc, Stmt *SubStmt,
-                             SourceLocation RParenLoc, unsigned TemplateDepth) {
-    return getSema().BuildStmtExpr(LParenLoc, SubStmt, RParenLoc,
-                                   TemplateDepth);
+                             SourceLocation RParenLoc, unsigned TemplateDepth,
+                             bool NeedsCleanup) {
+    return getSema().BuildStmtExpr(LParenLoc, SubStmt, RParenLoc, TemplateDepth,
+                                   NeedsCleanup);
   }
 
   /// Build a new __builtin_choose_expr expression.
@@ -11565,7 +11566,8 @@
   }
 
   return getDerived().RebuildStmtExpr(E->getLParenLoc(), SubStmt.get(),
-                                      E->getRParenLoc(), NewDepth);
+                                      E->getRParenLoc(), NewDepth,
+                                      E->needsCleanup());
 }
 
 template<typename Derived>
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -7299,7 +7299,7 @@
       Context, SubStmt, SourceLocation(), SourceLocation());
   Expr *E = new (Context)
       StmtExpr(CompStmt, Context.VoidTy, SourceLocation(), SourceLocation(),
-               /*FIXME TemplateDepth=*/0);
+               /*FIXME TemplateDepth=*/0, /*NeedsCleanup=*/true);
   return MaybeCreateExprWithCleanups(E);
 }
 
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -15743,13 +15743,15 @@
 }
 
 ExprResult Sema::BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
-                               SourceLocation RPLoc, unsigned TemplateDepth) {
+                               SourceLocation RPLoc, unsigned TemplateDepth,
+                               bool NeedsCleanup) {
   assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
   CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
 
   if (hasAnyUnrecoverableErrorsInThisFunction())
     DiscardCleanupsInEvaluationContext();
-  assert(!Cleanup.exprNeedsCleanups() &&
+  // Cleanups may be needed if temporaries are created in an AsmStmt.
+  assert((!Cleanup.exprNeedsCleanups() || NeedsCleanup) &&
          "cleanups within StmtExpr not correctly bound!");
   PopExpressionEvaluationContext();
 
@@ -15774,8 +15776,8 @@
 
   // FIXME: Check that expression type is complete/non-abstract; statement
   // expressions are not lvalues.
-  Expr *ResStmtExpr =
-      new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc, TemplateDepth);
+  Expr *ResStmtExpr = new (Context)
+      StmtExpr(Compound, Ty, LPLoc, RPLoc, TemplateDepth, NeedsCleanup);
   if (StmtExprMayBindToTemp)
     return MaybeBindToTemporary(ResStmtExpr);
   return ResStmtExpr;
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -5681,7 +5681,8 @@
   ExprResult ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt,
                            SourceLocation RPLoc);
   ExprResult BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
-                           SourceLocation RPLoc, unsigned TemplateDepth);
+                           SourceLocation RPLoc, unsigned TemplateDepth,
+                           bool NeedsCleanup = false);
   // Handle the final expression in a statement expression.
   ExprResult ActOnStmtExprResult(ExprResult E);
   void ActOnStmtExprError();
Index: clang/include/clang/AST/Stmt.h
===================================================================
--- clang/include/clang/AST/Stmt.h
+++ clang/include/clang/AST/Stmt.h
@@ -604,7 +604,11 @@
     /// The number of levels of template parameters enclosing this statement
     /// expression. Used to determine if a statement expression remains
     /// dependent after instantiation.
-    unsigned TemplateDepth;
+    unsigned TemplateDepth : 7;
+
+    /// Whether this StmtExpr needs cleanup. This is always false when it is
+    /// created for a GNU statement expression.
+    unsigned NeedsCleanup : 1;
   };
 
   //===--- C++ Expression bitfields classes ---===//
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -4351,13 +4351,15 @@
   SourceLocation LParenLoc, RParenLoc;
 public:
   StmtExpr(CompoundStmt *SubStmt, QualType T, SourceLocation LParenLoc,
-           SourceLocation RParenLoc, unsigned TemplateDepth)
+           SourceLocation RParenLoc, unsigned TemplateDepth,
+           bool NeedsCleanup = false)
       : Expr(StmtExprClass, T, VK_PRValue, OK_Ordinary), SubStmt(SubStmt),
         LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
     setDependence(computeDependence(this, TemplateDepth));
     // FIXME: A templated statement expression should have an associated
     // DeclContext so that nested declarations always have a dependent context.
     StmtExprBits.TemplateDepth = TemplateDepth;
+    StmtExprBits.NeedsCleanup = NeedsCleanup;
   }
 
   /// Build an empty statement expression.
@@ -4377,6 +4379,8 @@
 
   unsigned getTemplateDepth() const { return StmtExprBits.TemplateDepth; }
 
+  bool needsCleanup() const { return StmtExprBits.NeedsCleanup; }
+
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == StmtExprClass;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to