Index: lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -2796,6 +2796,13 @@ isa(D)) return nullptr; + // If the declaration we are looking for is an incomplete or forward type + // declaration, we may not have a chance to instantiate it. + if (const TagDecl *TD = dyn_cast(D)) + if (TD->getDefinition() || + (!TD->isThisDeclarationADefinition() && !TD->isFreeStanding())) + return nullptr; + // If we didn't find the decl, then we either have a sema bug, or we have a // forward reference to a label declaration. Return null to indicate that // we have an uninstantiated label. Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4399,6 +4399,21 @@ isa(D)) return D; + // If the declaration we are looking for is an incomplete or forward type + // declaration, we may not have a chance to instantiate it. + if (const TagDecl *TD = dyn_cast(D)) { + const TagDecl *DeclToInstantiate = nullptr; + if (TagDecl *Def = TD->getDefinition()) + DeclToInstantiate = Def; + else if (!TD->isThisDeclarationADefinition() && !TD->isFreeStanding()) + DeclToInstantiate = TD; + if (DeclToInstantiate) { + Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); + CurrentInstantiationScope->InstantiatedLocal(D, Inst); + return cast(Inst); + } + } + if (D->isInvalidDecl()) return nullptr; Index: test/SemaTemplate/instantiate-local-class.cpp =================================================================== --- test/SemaTemplate/instantiate-local-class.cpp +++ test/SemaTemplate/instantiate-local-class.cpp @@ -194,3 +194,22 @@ void f() { F(); } }; } + +namespace PR18653 { + template void f(); + template struct str { + void m() { + f(); + } + }; + template struct str; + + template void f() { void g(struct x); } + template void f(); + + template void f2() { + void g2(struct x2); + struct x2 {}; + } + template void f2(); +}