r222194 - Fix an assertion when ending a function definition.

John McCall rjmccall at apple.com
Mon Nov 17 16:19:01 PST 2014


Author: rjmccall
Date: Mon Nov 17 18:19:01 2014
New Revision: 222194

URL: http://llvm.org/viewvc/llvm-project?rev=222194&view=rev
Log:
Fix an assertion when ending a function definition.

The bug is that ExprCleanupObjects isn't always empty
in a fresh evaluation context.  New evaluation contexts just
track the current depth of the stack.

The assertion will misfire whenever we finish processing
a function body inside an expression that contained an earlier
block literal with non-trivial captures.  That's actually
a lot less likely than you'd think, though, because it has
to be a real function declaration, not just another block.
Mixed block/lambda code would work, as would a template
instantiation or a local class definition.

The code works correctly if the assertion is disabled.

rdar://16356628

Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/SemaCXX/blocks.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=222194&r1=222193&r2=222194&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Nov 17 18:19:01 2014
@@ -10579,7 +10579,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl
       }
     }
 
-    assert(ExprCleanupObjects.empty() && "Leftover temporaries in function");
+    assert(ExprCleanupObjects.size() == ExprEvalContexts.back().NumCleanupObjects
+           && "Leftover temporaries in function");
     assert(!ExprNeedsCleanups && "Unaccounted cleanups in function");
     assert(MaybeODRUseExprs.empty() &&
            "Leftover expressions for odr-use checking");

Modified: cfe/trunk/test/SemaCXX/blocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/blocks.cpp?rev=222194&r1=222193&r2=222194&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/blocks.cpp (original)
+++ cfe/trunk/test/SemaCXX/blocks.cpp Mon Nov 17 18:19:01 2014
@@ -100,3 +100,48 @@ namespace test5 {
       });
   }
 }
+
+
+// rdar://16356628
+//
+// Ensure that we can end function bodies while parsing an
+// expression that requires an explicitly-tracked cleanup object
+// (i.e. a block literal).
+
+// The nested function body in this test case is a template
+// instantiation.  The template function has to be constexpr because
+// we'll otherwise delay its instantiation to the end of the
+// translation unit.
+namespace test6a {
+  template <class T> constexpr int func() { return 0; }
+  void run(void (^)(), int);
+
+  void test() {
+    int aCapturedVar = 0;
+    run(^{ (void) aCapturedVar; }, func<int>());
+  }
+}
+
+// The nested function body in this test case is a method of a local
+// class.
+namespace test6b {
+  void run(void (^)(), void (^)());
+  void test() {
+    int aCapturedVar = 0;
+    run(^{ (void) aCapturedVar; },
+        ^{ struct A { static void foo() {} };
+            A::foo(); });
+  }
+}
+
+// The nested function body in this test case is a lambda invocation
+// function.
+namespace test6c {
+  void run(void (^)(), void (^)());
+  void test() {
+    int aCapturedVar = 0;
+    run(^{ (void) aCapturedVar; },
+        ^{ struct A { static void foo() {} };
+            A::foo(); });
+  }
+}





More information about the cfe-commits mailing list