Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/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: clang/test/SemaCXX/pr36536.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/pr36536.cpp @@ -0,0 +1,45 @@ +// 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 { +// expected-error@+1 {{cannot define or redeclare 'f' here}} +void Foo::f() { + switch (0) { case 0: ImplicitDefaultCtor1 o; } + + // FIXME: If we improved our recovery to redeclare Foo::f in the wrong + // namespace, we could find the right type name here. Users probably run into + // this when they forget to close a namespace, and we'd generate far fewer + // errors if names in Foo were in scope. + // 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; } +} +}