[PATCH] -fdelayed-template-parsing: handle cases where a late-parsed function is not a direct member of a template, but rather nested inside a class that's a member of a template (PR19613)
Hans Wennborg
hans at chromium.org
Thu May 1 10:27:40 PDT 2014
Thanks for the review! New patch coming up.
================
Comment at: include/clang/Sema/Sema.h:4887-4889
@@ -4886,4 +4886,5 @@
void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param);
void ActOnReenterTemplateScope(Scope *S, Decl *Template);
void ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D);
+ void ActOnReenterRecordTemplateScope(Scope *S, CXXRecordDecl *RD);
void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record);
----------------
Richard Smith wrote:
> Can we fold these three functions together, so we can just say 'reenter the scope of this declaration' and enter all its template parameter lists at once? It's a bit strange that 'ActOnReenterDeclaratorTemplateScope' doesn't actually enter the innermost template scope if the declarator is itself declaring a template.
Done. I've folded them into one function.
================
Comment at: lib/Parse/ParseTemplate.cpp:1254-1256
@@ -1253,5 +1253,5 @@
dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) {
TemplateParamScopeStack.push_back(
new ParseScope(this, Scope::TemplateParamScope));
Actions.ActOnReenterTemplateScope(getCurScope(), MD);
++CurTemplateDepthTracker;
----------------
Richard Smith wrote:
> This side also might have surrounding template parameter lists, if a partial specialization is defined out of line:
>
> template<typename T> struct S {
> template<typename U> struct X;
> template<typename U> struct X<U*>;
> };
> template<typename T> template<typename U> struct S<T>::X<U*> {
> void f() {}
> };
Thanks! Added this to the battery of tests.
================
Comment at: lib/Parse/ParseTemplate.cpp:1262-1272
@@ -1260,7 +1261,13 @@
+ Scope::TemplateParamScope, /*EnteredScope*/true));
+ Actions.ActOnReenterTemplateScope(getCurScope(), CTD);
+ ++CurTemplateDepthTracker;
+ }
+
+ bool HasTemplateParams = RD->getNumTemplateParameterLists() > 0;
+
TemplateParamScopeStack.push_back(
- new ParseScope(this, Scope::TemplateParamScope,
- /*ManageScope*/IsClassTemplate));
- Actions.ActOnReenterTemplateScope(getCurScope(),
- MD->getDescribedClassTemplate());
- if (IsClassTemplate)
+ new ParseScope(this, Scope::TemplateParamScope,
+ /*EnteredScope*/HasTemplateParams));
+ if (HasTemplateParams) {
+ Actions.ActOnReenterRecordTemplateScope(getCurScope(), RD);
++CurTemplateDepthTracker;
----------------
Richard Smith wrote:
> These steps seem backwards: we should reenter the surrounding template scopes for the class template before we reenter the class template itself.
You're right. I've changed the order.
================
Comment at: lib/Parse/ParseTemplate.cpp:1272
@@ -1266,1 +1271,3 @@
+ if (HasTemplateParams) {
+ Actions.ActOnReenterRecordTemplateScope(getCurScope(), RD);
++CurTemplateDepthTracker;
----------------
Richard Smith wrote:
> Why 'record' rather than 'class'? We're pretty consistent in using 'ClassTemplate' (even though we use the unfortunate name 'CXXRecordDecl').
ActOnReenterRecordTemplateScope has gone away now.
================
Comment at: lib/Sema/SemaDeclCXX.cpp:5983-6000
@@ -5982,20 +5982,20 @@
void Sema::ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D) {
if (!D)
return;
- int NumParamList = D->getNumTemplateParameterLists();
- for (int i = 0; i < NumParamList; i++) {
- TemplateParameterList* Params = D->getTemplateParameterList(i);
+ unsigned NumParamList = D->getNumTemplateParameterLists();
+ for (unsigned 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<NamedDecl>(*Param);
if (Named->getDeclName()) {
S->AddDecl(Named);
IdResolver.AddDecl(Named);
}
}
}
}
----------------
Richard Smith wrote:
> Maybe factor this out into a static helper template rather than essentially duplicating it?
Since I baked the three ActOnReenter*TemplateScope together, I think the code became simpler.
http://reviews.llvm.org/D3555
More information about the cfe-commits
mailing list