Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -4884,8 +4884,7 @@ void ActOnFinishCXXMemberDecls(); void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param); - void ActOnReenterTemplateScope(Scope *S, Decl *Template); - void ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D); + unsigned ActOnReenterTemplateScope(Scope *S, Decl *Template); void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record); void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method); void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param); Index: lib/Parse/ParseTemplate.cpp =================================================================== --- lib/Parse/ParseTemplate.cpp +++ lib/Parse/ParseTemplate.cpp @@ -1249,34 +1249,23 @@ SmallVectorImpl::reverse_iterator II = DeclContextsToReenter.rbegin(); for (; II != DeclContextsToReenter.rend(); ++II) { - if (ClassTemplatePartialSpecializationDecl *MD = - dyn_cast_or_null(*II)) { - TemplateParamScopeStack.push_back( - new ParseScope(this, Scope::TemplateParamScope)); - Actions.ActOnReenterTemplateScope(getCurScope(), MD); - ++CurTemplateDepthTracker; - } else if (CXXRecordDecl *MD = dyn_cast_or_null(*II)) { - bool IsClassTemplate = MD->getDescribedClassTemplate() != 0; - TemplateParamScopeStack.push_back( - new ParseScope(this, Scope::TemplateParamScope, - /*ManageScope*/IsClassTemplate)); - Actions.ActOnReenterTemplateScope(getCurScope(), - MD->getDescribedClassTemplate()); - if (IsClassTemplate) - ++CurTemplateDepthTracker; - } + Decl *D = dyn_cast(*II); + + TemplateParamScopeStack.push_back(new ParseScope(this, + Scope::TemplateParamScope)); + unsigned NumParamLists = + Actions.ActOnReenterTemplateScope(getCurScope(), D); + CurTemplateDepthTracker.addDepth(NumParamLists); + TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); Actions.PushDeclContext(Actions.getCurScope(), *II); } TemplateParamScopeStack.push_back( new ParseScope(this, Scope::TemplateParamScope)); - DeclaratorDecl *Declarator = dyn_cast(FunD); - const unsigned DeclaratorNumTemplateParameterLists = - (Declarator ? Declarator->getNumTemplateParameterLists() : 0); - if (Declarator && DeclaratorNumTemplateParameterLists != 0) { - Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator); - CurTemplateDepthTracker.addDepth(DeclaratorNumTemplateParameterLists); + if (unsigned NumLists = FunD->getNumTemplateParameterLists()) { + Actions.ActOnReenterTemplateScope(getCurScope(), FunD); + CurTemplateDepthTracker.addDepth(NumLists); } Actions.ActOnReenterTemplateScope(getCurScope(), LPT.D); ++CurTemplateDepthTracker; Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -5980,47 +5980,41 @@ } } -void Sema::ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D) { +unsigned Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) { if (!D) - return; + return 0; - int NumParamList = D->getNumTemplateParameterLists(); - for (int i = 0; i < NumParamList; i++) { - TemplateParameterList* Params = D->getTemplateParameterList(i); - for (TemplateParameterList::iterator Param = Params->begin(), - ParamEnd = Params->end(); - Param != ParamEnd; ++Param) { - NamedDecl *Named = cast(*Param); - if (Named->getDeclName()) { - S->AddDecl(Named); - IdResolver.AddDecl(Named); - } - } + SmallVector ParameterLists; + + if (TemplateDecl *TD = dyn_cast(D)) + ParameterLists.push_back(TD->getTemplateParameters()); + + if (auto *PSD = dyn_cast(D)) + ParameterLists.push_back(PSD->getTemplateParameters()); + + if (DeclaratorDecl *DD = dyn_cast(D)) { + for (unsigned i = 0; i < DD->getNumTemplateParameterLists(); ++i) + ParameterLists.push_back(DD->getTemplateParameterList(i)); } -} -void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) { - if (!D) - return; - - TemplateParameterList *Params = 0; - if (TemplateDecl *Template = dyn_cast(D)) - Params = Template->getTemplateParameters(); - else if (ClassTemplatePartialSpecializationDecl *PartialSpec - = dyn_cast(D)) - Params = PartialSpec->getTemplateParameters(); - else - return; + if (CXXRecordDecl *RD = dyn_cast(D)) { + for (unsigned i = 0; i < RD->getNumTemplateParameterLists(); ++i) + ParameterLists.push_back(RD->getTemplateParameterList(i)); - for (TemplateParameterList::iterator Param = Params->begin(), - ParamEnd = Params->end(); - Param != ParamEnd; ++Param) { - NamedDecl *Named = cast(*Param); - if (Named->getDeclName()) { - S->AddDecl(Named); - IdResolver.AddDecl(Named); + if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) + ParameterLists.push_back(CTD->getTemplateParameters()); + } + + for (TemplateParameterList *Params : ParameterLists) { + for (NamedDecl *Param : *Params) { + if (Param->getDeclName()) { + S->AddDecl(Param); + IdResolver.AddDecl(Param); + } } } + + return ParameterLists.size(); } void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) { Index: test/Parser/DelayedTemplateParsing.cpp =================================================================== --- test/Parser/DelayedTemplateParsing.cpp +++ test/Parser/DelayedTemplateParsing.cpp @@ -123,3 +123,61 @@ template auto invalidTrailingRetType() -> Bogus {} // expected-error {{unknown type name 'Bogus'}} + +namespace PR19613 { + +struct HeapTypeConfig { + static void from_bitset(); +}; + +template +struct TypeImpl { + struct BitsetType; + + static void Any() { + BitsetType::New(); + } +}; + +template +struct TypeImpl::BitsetType { + static void New() { + Config::from_bitset(); + } +}; + +static void f() { + TypeImpl::Any(); +} + +template struct S { + template struct T; +}; +template template struct S::T { + template struct U; + template struct U { + template static int f() { + return sizeof(A) + sizeof(B) + sizeof(C) + sizeof(E); + } + }; +}; + +static void g() { + S::T::U::f(); +} + +template struct SS { + template struct X; + template struct X; +}; +template template struct SS::X { + static int f() { + return sizeof(T) + sizeof(U); + } +}; + +static void h() { + SS::X::f(); +} + +}