[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)

Richard Smith richard at metafoo.co.uk
Wed Apr 30 18:09:58 PDT 2014


================
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);
----------------
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.

================
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;
----------------
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() {}
  };

================
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;
----------------
These steps seem backwards: we should reenter the surrounding template scopes for the class template before we reenter the class template itself.

================
Comment at: lib/Parse/ParseTemplate.cpp:1272
@@ -1266,1 +1271,3 @@
+      if (HasTemplateParams) {
+        Actions.ActOnReenterRecordTemplateScope(getCurScope(), RD);
         ++CurTemplateDepthTracker;
----------------
Why 'record' rather than 'class'? We're pretty consistent in using 'ClassTemplate' (even though we use the unfortunate name 'CXXRecordDecl').

================
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);
       }
     }
   }
 }
 
----------------
Maybe factor this out into a static helper template rather than essentially duplicating it?

http://reviews.llvm.org/D3555






More information about the cfe-commits mailing list