[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 15:50:36 PDT 2014


================
Comment at: lib/Parse/ParseTemplate.cpp:1252
@@ -1251,17 +1251,3 @@
   for (; II != DeclContextsToReenter.rend(); ++II) {
-    if (ClassTemplatePartialSpecializationDecl *MD =
-            dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) {
-      TemplateParamScopeStack.push_back(
-          new ParseScope(this, Scope::TemplateParamScope));
-      Actions.ActOnReenterTemplateScope(getCurScope(), MD);
-      ++CurTemplateDepthTracker;
-    } else if (CXXRecordDecl *MD = dyn_cast_or_null<CXXRecordDecl>(*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<Decl>(*II);
+
----------------
Richard Smith wrote:
> `cast`, not `dyn_cast`, please.
Done.

================
Comment at: lib/Parse/ParseTemplate.cpp:1266-1270
@@ -1273,10 +1265,7 @@
 
-  DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(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;
----------------
Richard Smith wrote:
> Can you push the function template case into `ActOnReenterTemplateScope` too?
I can make Actions.ActOnReenterTemplateScope(getCurScope(), FunD); be covered by the loop above if I make sure not to call Actions.PushDeclContext() on it.

I have no idea why we then do an extra Actions.ActOnReenterTemplateScope(getCurScope(), LPT.D); since that should have the same effect. But if I remove that, we start failing tests, so I guess it needs to be there.

================
Comment at: lib/Sema/SemaDeclCXX.cpp:6000
@@ -6001,13 +5999,3 @@
 
-void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
-  if (!D)
-    return;
-  
-  TemplateParameterList *Params = 0;
-  if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
-    Params = Template->getTemplateParameters();
-  else if (ClassTemplatePartialSpecializationDecl *PartialSpec
-           = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
-    Params = PartialSpec->getTemplateParameters();
-  else
-    return;
+  if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+    for (unsigned i = 0; i < RD->getNumTemplateParameterLists(); ++i)
----------------
Richard Smith wrote:
> You should handle all `TagDecl`s here, not just `CXXRecordDecl`s. Under the resolution of DR1607, this is valid:
> 
>   template<typename T> struct A {
>     enum class E;
>   };
>   template<typename T> enum class A<T>::E {
>     n = (true ? 0 : [] {
>       struct Q { Q() { /* delay parsed */ } } q;
>       return 0;
>     }())
>   };
> 
> ... and instantiating `A<T>::E` will instantiate the default constructor of `Q` (note, we currently reject this because we went for a more conservative tentative fix for issue 1607).
"Done."

http://reviews.llvm.org/D3555






More information about the cfe-commits mailing list