r207822 - Handle -fdelayed-template-parsing of out-of-line definitions of

Hans Wennborg hans at hanshq.net
Thu May 1 19:01:07 PDT 2014


Author: hans
Date: Thu May  1 21:01:07 2014
New Revision: 207822

URL: http://llvm.org/viewvc/llvm-project?rev=207822&view=rev
Log:
Handle -fdelayed-template-parsing of out-of-line definitions of
class template member classes (PR19613)

Also improve this code in general by implementing suggestions
from Richard.

Differential Revision: http://reviews.llvm.org/D3555?id=9020

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/Parser/DelayedTemplateParsing.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=207822&r1=207821&r2=207822&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu May  1 21:01:07 2014
@@ -4884,8 +4884,7 @@ public:
   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);

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=207822&r1=207821&r2=207822&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Thu May  1 21:01:07 2014
@@ -1239,7 +1239,7 @@ void Parser::ParseLateTemplatedFuncDef(L
 
   // Get the list of DeclContexts to reenter.
   SmallVector<DeclContext*, 4> DeclContextsToReenter;
-  DeclContext *DD = FunD->getLexicalParent();
+  DeclContext *DD = FunD;
   while (DD && !DD->isTranslationUnit()) {
     DeclContextsToReenter.push_back(DD);
     DD = DD->getLexicalParent();
@@ -1249,37 +1249,16 @@ void Parser::ParseLateTemplatedFuncDef(L
   SmallVectorImpl<DeclContext *>::reverse_iterator II =
       DeclContextsToReenter.rbegin();
   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;
+    TemplateParamScopeStack.push_back(new ParseScope(this,
+          Scope::TemplateParamScope));
+    unsigned NumParamLists =
+      Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II));
+    CurTemplateDepthTracker.addDepth(NumParamLists);
+    if (*II != FunD) {
+      TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
+      Actions.PushDeclContext(Actions.getCurScope(), *II);
     }
-    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<DeclaratorDecl>(FunD);
-  const unsigned DeclaratorNumTemplateParameterLists = 
-      (Declarator ? Declarator->getNumTemplateParameterLists() : 0);
-  if (Declarator && DeclaratorNumTemplateParameterLists != 0) {
-    Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
-    CurTemplateDepthTracker.addDepth(DeclaratorNumTemplateParameterLists);
-  }
-  Actions.ActOnReenterTemplateScope(getCurScope(), LPT.D);
-  ++CurTemplateDepthTracker;
 
   assert(!LPT.Toks.empty() && "Empty body!");
 
@@ -1314,7 +1293,7 @@ void Parser::ParseLateTemplatedFuncDef(L
       assert((!isa<FunctionTemplateDecl>(LPT.D) ||
               cast<FunctionTemplateDecl>(LPT.D)
                       ->getTemplateParameters()
-                      ->getDepth() < TemplateParameterDepth) &&
+                      ->getDepth() == TemplateParameterDepth - 1) &&
              "TemplateParameterDepth should be greater than the depth of "
              "current template being instantiated!");
       ParseFunctionStatementBody(LPT.D, FnScope);

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=207822&r1=207821&r2=207822&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu May  1 21:01:07 2014
@@ -5980,47 +5980,55 @@ void Sema::AddImplicitlyDeclaredMembersT
   }
 }
 
-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<NamedDecl>(*Param);
-      if (Named->getDeclName()) {
-        S->AddDecl(Named);
-        IdResolver.AddDecl(Named);
-      }
+  // The order of template parameters is not important here. All names
+  // get added to the same scope.
+  SmallVector<TemplateParameterList *, 4> ParameterLists;
+
+  if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
+    D = TD->getTemplatedDecl();
+
+  if (auto *PSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
+    ParameterLists.push_back(PSD->getTemplateParameters());
+
+  if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
+    for (unsigned i = 0; i < DD->getNumTemplateParameterLists(); ++i)
+      ParameterLists.push_back(DD->getTemplateParameterList(i));
+
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+      if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
+        ParameterLists.push_back(FTD->getTemplateParameters());
     }
   }
-}
 
-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;
-
-  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);
+  if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+    for (unsigned i = 0; i < TD->getNumTemplateParameterLists(); ++i)
+      ParameterLists.push_back(TD->getTemplateParameterList(i));
+
+    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) {
+      if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
+        ParameterLists.push_back(CTD->getTemplateParameters());
+    }
+  }
+
+  unsigned Count = 0;
+  for (TemplateParameterList *Params : ParameterLists) {
+    if (Params->size() > 0)
+      // Ignore explicit specializations; they don't contribute to the template
+      // depth.
+      ++Count;
+    for (NamedDecl *Param : *Params) {
+      if (Param->getDeclName()) {
+        S->AddDecl(Param);
+        IdResolver.AddDecl(Param);
+      }
     }
   }
+
+  return Count;
 }
 
 void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) {

Modified: cfe/trunk/test/Parser/DelayedTemplateParsing.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/DelayedTemplateParsing.cpp?rev=207822&r1=207821&r2=207822&view=diff
==============================================================================
--- cfe/trunk/test/Parser/DelayedTemplateParsing.cpp (original)
+++ cfe/trunk/test/Parser/DelayedTemplateParsing.cpp Thu May  1 21:01:07 2014
@@ -123,3 +123,61 @@ constexpr int Var = Fun(20);
 
 template <typename T>
 auto invalidTrailingRetType() -> Bogus {} // expected-error {{unknown type name 'Bogus'}}
+
+namespace PR19613 {
+
+struct HeapTypeConfig {
+  static void from_bitset();
+};
+
+template <class Config>
+struct TypeImpl  {
+  struct BitsetType;
+
+  static void Any() {
+    BitsetType::New();
+  }
+};
+
+template<class Config>
+struct TypeImpl<Config>::BitsetType {
+  static void New() {
+    Config::from_bitset();
+  }
+};
+
+static void f() {
+  TypeImpl<HeapTypeConfig>::Any();
+}
+
+template<typename A> struct S {
+  template<typename B> struct T;
+};
+template<typename A> template<typename B> struct S<A>::T {
+  template<typename C, typename D> struct U;
+  template<typename C> struct U<C, C> {
+    template<typename E> static int f() {
+      return sizeof(A) + sizeof(B) + sizeof(C) + sizeof(E);
+    }
+  };
+};
+
+static void g() {
+  S<int>::T<int>::U<int,int>::f<int>();
+}
+
+template<typename T> struct SS {
+  template<typename U> struct X;
+  template<typename U> struct X<U*>;
+};
+template<typename T> template<typename U> struct SS<T>::X<U*> {
+  static int f() {
+    return sizeof(T) + sizeof(U);
+  }
+};
+
+static void h() {
+  SS<int>::X<int*>::f();
+}
+
+}





More information about the cfe-commits mailing list