diff options
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | clang/test/SemaCXX/blocks.cpp | 45 |
2 files changed, 47 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a4b995fa977..b63863e96bb 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10579,7 +10579,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, } } - 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"); diff --git a/clang/test/SemaCXX/blocks.cpp b/clang/test/SemaCXX/blocks.cpp index a2672d13b72..0521802172f 100644 --- a/clang/test/SemaCXX/blocks.cpp +++ b/clang/test/SemaCXX/blocks.cpp @@ -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(); }); + } +} |