Index: cfe/trunk/lib/Sema/SemaDecl.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -12406,8 +12406,13 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, SkipBodyInfo *SkipBody) { - if (!D) + if (!D) { + // Parsing the function declaration failed in some way. Push on a fake scope + // anyway so we can try to parse the function body. + PushFunctionScope(); return D; + } + FunctionDecl *FD = nullptr; if (FunctionTemplateDecl *FunTmpl = dyn_cast(D)) @@ -12816,6 +12821,9 @@ getCurFunction()->ObjCWarnForNoInitDelegation = false; } } else { + // Parsing the function declaration failed in some way. Pop the fake scope + // we pushed on. + PopFunctionScopeInfo(ActivePolicy, dcl); return nullptr; } Index: cfe/trunk/test/SemaCXX/pr36536.cpp =================================================================== --- cfe/trunk/test/SemaCXX/pr36536.cpp +++ cfe/trunk/test/SemaCXX/pr36536.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify -fno-spell-checking + +// These test cases are constructed to make clang call ActOnStartOfFunctionDef +// with nullptr. + +struct ImplicitDefaultCtor1 {}; +struct Foo { + typedef int NameInClass; + void f(); +}; +namespace bar { +// FIXME: Improved our recovery to make this a redeclaration of Foo::f, +// even though this is in the wrong namespace. That will allow name lookup to +// find NameInClass below. Users are likely to hit this when they forget to +// close namespaces. +// expected-error@+1 {{cannot define or redeclare 'f' here}} +void Foo::f() { + switch (0) { case 0: ImplicitDefaultCtor1 o; } + // expected-error@+1 {{unknown type name 'NameInClass'}} + NameInClass var; +} +} // namespace bar + +struct ImplicitDefaultCtor2 {}; +template class TFoo { void f(); }; +// expected-error@+1 {{nested name specifier 'decltype(TFoo())::'}} +template void decltype(TFoo())::f() { + switch (0) { case 0: ImplicitDefaultCtor1 o; } +} + +namespace tpl2 { +struct ImplicitDefaultCtor3 {}; +template class A { + template class B { + void mf2(); + }; +}; +template +template <> +// expected-error@+1 {{nested name specifier 'A::B::'}} +void A::B::mf2() { + switch (0) { case 0: ImplicitDefaultCtor3 o; } +} +}