[llvm-branch-commits] [cfe-branch] r119250 - in /cfe/branches/Apple/whitney: include/clang/Sema/Template.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.decls/temp.class.spec/p6.cpp test/SemaTemplate/explicit-specialization-member.cpp

Daniel Dunbar daniel at zuster.org
Mon Nov 15 13:46:08 PST 2010


Author: ddunbar
Date: Mon Nov 15 15:46:08 2010
New Revision: 119250

URL: http://llvm.org/viewvc/llvm-project?rev=119250&view=rev
Log:
Merge r118704:
--
Author: Douglas Gregor <dgregor at apple.com>
Date:   Wed Nov 10 19:44:59 2010 +0000

    Instantiate class member template partial specialization declarations
    in the order they occur within the class template, delaying
    out-of-line member template partial specializations until after the
    class has been fully instantiated. This fixes a regression introduced
    by r118454 (itself a fix for PR8001).

Modified:
    cfe/branches/Apple/whitney/include/clang/Sema/Template.h
    cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/branches/Apple/whitney/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
    cfe/branches/Apple/whitney/test/SemaTemplate/explicit-specialization-member.cpp

Modified: cfe/branches/Apple/whitney/include/clang/Sema/Template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/include/clang/Sema/Template.h?rev=119250&r1=119249&r2=119250&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/include/clang/Sema/Template.h (original)
+++ cfe/branches/Apple/whitney/include/clang/Sema/Template.h Mon Nov 15 15:46:08 2010
@@ -13,8 +13,10 @@
 #define LLVM_CLANG_SEMA_TEMPLATE_H
 
 #include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
 #include "llvm/ADT/SmallVector.h"
 #include <cassert>
+#include <utility>
 
 namespace clang {
   /// \brief Data structure that captures multiple levels of template argument
@@ -239,6 +241,113 @@
 
     void InstantiatedLocal(const Decl *D, Decl *Inst);
   };
+
+  class TemplateDeclInstantiator
+    : public DeclVisitor<TemplateDeclInstantiator, Decl *> {
+    Sema &SemaRef;
+    DeclContext *Owner;
+    const MultiLevelTemplateArgumentList &TemplateArgs;
+
+    /// \brief A list of out-of-line class template partial
+    /// specializations that will need to be instantiated after the
+    /// enclosing class's instantiation is complete.
+    llvm::SmallVector<std::pair<ClassTemplateDecl *,
+                                ClassTemplatePartialSpecializationDecl *>, 4>
+      OutOfLinePartialSpecs;
+
+  public:
+    TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
+                             const MultiLevelTemplateArgumentList &TemplateArgs)
+      : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { }
+
+    // FIXME: Once we get closer to completion, replace these manually-written
+    // declarations with automatically-generated ones from
+    // clang/AST/DeclNodes.inc.
+    Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
+    Decl *VisitNamespaceDecl(NamespaceDecl *D);
+    Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+    Decl *VisitTypedefDecl(TypedefDecl *D);
+    Decl *VisitVarDecl(VarDecl *D);
+    Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
+    Decl *VisitFieldDecl(FieldDecl *D);
+    Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
+    Decl *VisitEnumDecl(EnumDecl *D);
+    Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
+    Decl *VisitFriendDecl(FriendDecl *D);
+    Decl *VisitFunctionDecl(FunctionDecl *D,
+                            TemplateParameterList *TemplateParams = 0);
+    Decl *VisitCXXRecordDecl(CXXRecordDecl *D);
+    Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
+                             TemplateParameterList *TemplateParams = 0);
+    Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
+    Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
+    Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
+    ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D);
+    Decl *VisitClassTemplateDecl(ClassTemplateDecl *D);
+    Decl *VisitClassTemplatePartialSpecializationDecl(
+                                    ClassTemplatePartialSpecializationDecl *D);
+    Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+    Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
+    Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+    Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+    Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+    Decl *VisitUsingDecl(UsingDecl *D);
+    Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
+    Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+    Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+
+    // Base case. FIXME: Remove once we can instantiate everything.
+    Decl *VisitDecl(Decl *D) {
+      unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID(
+                                                            Diagnostic::Error,
+                                                   "cannot instantiate %0 yet");
+      SemaRef.Diag(D->getLocation(), DiagID)
+        << D->getDeclKindName();
+      
+      return 0;
+    }
+    
+    typedef 
+      llvm::SmallVectorImpl<std::pair<ClassTemplateDecl *,
+                                     ClassTemplatePartialSpecializationDecl *> >
+        ::iterator
+      delayed_partial_spec_iterator;
+
+    /// \brief Return an iterator to the beginning of the set of
+    /// "delayed" partial specializations, which must be passed to
+    /// InstantiateClassTemplatePartialSpecialization once the class
+    /// definition has been completed.
+    delayed_partial_spec_iterator delayed_partial_spec_begin() {
+      return OutOfLinePartialSpecs.begin();
+    }
+
+    /// \brief Return an iterator to the end of the set of
+    /// "delayed" partial specializations, which must be passed to
+    /// InstantiateClassTemplatePartialSpecialization once the class
+    /// definition has been completed.
+    delayed_partial_spec_iterator delayed_partial_spec_end() {
+      return OutOfLinePartialSpecs.end();
+    }
+
+    // Helper functions for instantiating methods.
+    TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
+                             llvm::SmallVectorImpl<ParmVarDecl *> &Params);
+    bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
+    bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
+
+    TemplateParameterList *
+      SubstTemplateParams(TemplateParameterList *List);
+
+    bool SubstQualifier(const DeclaratorDecl *OldDecl,
+                        DeclaratorDecl *NewDecl);
+    bool SubstQualifier(const TagDecl *OldDecl,
+                        TagDecl *NewDecl);
+      
+    ClassTemplatePartialSpecializationDecl *
+    InstantiateClassTemplatePartialSpecialization(
+                                              ClassTemplateDecl *ClassTemplate,
+                           ClassTemplatePartialSpecializationDecl *PartialSpec);
+  };
 }
 
 #endif // LLVM_CLANG_SEMA_TEMPLATE_H

Modified: cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiate.cpp?rev=119250&r1=119249&r2=119250&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiate.cpp Mon Nov 15 15:46:08 2010
@@ -1219,6 +1219,7 @@
   if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs))
     Invalid = true;
 
+  TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
   llvm::SmallVector<Decl*, 4> Fields;
   for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
          MemberEnd = Pattern->decls_end();
@@ -1235,7 +1236,12 @@
     if ((*Member)->getDeclContext() != Pattern)
       continue;
 
-    Decl *NewMember = SubstDecl(*Member, Instantiation, TemplateArgs);
+    if ((*Member)->isInvalidDecl()) {
+      Invalid = true; 
+      continue;
+    }
+
+    Decl *NewMember = Instantiator.Visit(*Member);
     if (NewMember) {
       if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
         Fields.push_back(Field);
@@ -1255,7 +1261,22 @@
   CheckCompletedCXXClass(Instantiation);
   if (Instantiation->isInvalidDecl())
     Invalid = true;
-  
+  else {
+    // Instantiate any out-of-line class template partial
+    // specializations now.
+    for (TemplateDeclInstantiator::delayed_partial_spec_iterator 
+              P = Instantiator.delayed_partial_spec_begin(),
+           PEnd = Instantiator.delayed_partial_spec_end();
+         P != PEnd; ++P) {
+      if (!Instantiator.InstantiateClassTemplatePartialSpecialization(
+                                                                P->first,
+                                                                P->second)) {
+        Invalid = true;
+        break;
+      }
+    }
+  }
+
   // Exit the scope of this instantiation.
   SavedContext.pop();
 

Modified: cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=119250&r1=119249&r2=119250&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Nov 15 15:46:08 2010
@@ -25,85 +25,6 @@
 
 using namespace clang;
 
-namespace {
-  class TemplateDeclInstantiator
-    : public DeclVisitor<TemplateDeclInstantiator, Decl *> {
-    Sema &SemaRef;
-    DeclContext *Owner;
-    const MultiLevelTemplateArgumentList &TemplateArgs;
-
-  public:
-    TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
-                             const MultiLevelTemplateArgumentList &TemplateArgs)
-      : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { }
-
-    // FIXME: Once we get closer to completion, replace these manually-written
-    // declarations with automatically-generated ones from
-    // clang/AST/DeclNodes.inc.
-    Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
-    Decl *VisitNamespaceDecl(NamespaceDecl *D);
-    Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
-    Decl *VisitTypedefDecl(TypedefDecl *D);
-    Decl *VisitVarDecl(VarDecl *D);
-    Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
-    Decl *VisitFieldDecl(FieldDecl *D);
-    Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
-    Decl *VisitEnumDecl(EnumDecl *D);
-    Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
-    Decl *VisitFriendDecl(FriendDecl *D);
-    Decl *VisitFunctionDecl(FunctionDecl *D,
-                            TemplateParameterList *TemplateParams = 0);
-    Decl *VisitCXXRecordDecl(CXXRecordDecl *D);
-    Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
-                             TemplateParameterList *TemplateParams = 0);
-    Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
-    Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
-    Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
-    ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D);
-    Decl *VisitClassTemplateDecl(ClassTemplateDecl *D);
-    Decl *VisitClassTemplatePartialSpecializationDecl(
-                                    ClassTemplatePartialSpecializationDecl *D);
-    Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
-    Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
-    Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
-    Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
-    Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
-    Decl *VisitUsingDecl(UsingDecl *D);
-    Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
-    Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
-    Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
-
-    // Base case. FIXME: Remove once we can instantiate everything.
-    Decl *VisitDecl(Decl *D) {
-      unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID(
-                                                            Diagnostic::Error,
-                                                   "cannot instantiate %0 yet");
-      SemaRef.Diag(D->getLocation(), DiagID)
-        << D->getDeclKindName();
-      
-      return 0;
-    }
-
-    // Helper functions for instantiating methods.
-    TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
-                             llvm::SmallVectorImpl<ParmVarDecl *> &Params);
-    bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
-    bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
-
-    TemplateParameterList *
-      SubstTemplateParams(TemplateParameterList *List);
-
-    bool SubstQualifier(const DeclaratorDecl *OldDecl,
-                        DeclaratorDecl *NewDecl);
-    bool SubstQualifier(const TagDecl *OldDecl,
-                        TagDecl *NewDecl);
-      
-    bool InstantiateClassTemplatePartialSpecialization(
-                                              ClassTemplateDecl *ClassTemplate,
-                           ClassTemplatePartialSpecializationDecl *PartialSpec);
-  };
-}
-
 bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
                                               DeclaratorDecl *NewDecl) {
   NestedNameSpecifier *OldQual = OldDecl->getQualifier();
@@ -860,14 +781,18 @@
   }
   
   Owner->addDecl(Inst);
-  
-  // Instantiate all of the partial specializations of this member class 
-  // template.
-  llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
-  D->getPartialSpecializations(PartialSpecs);
-  for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
-    InstantiateClassTemplatePartialSpecialization(Inst, PartialSpecs[I]);
-  
+
+  if (!PrevClassTemplate) {
+    // Queue up any out-of-line partial specializations of this member
+    // class template; the client will force their instantiation once
+    // the enclosing class has been instantiated.
+    llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+    D->getPartialSpecializations(PartialSpecs);
+    for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
+      if (PartialSpecs[I]->isOutOfLine())
+        OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I]));
+  }
+
   return Inst;
 }
 
@@ -888,7 +813,11 @@
   if (!InstClassTemplate)
     return 0;
   
-  return InstClassTemplate->findPartialSpecInstantiatedFromMember(D);
+  if (ClassTemplatePartialSpecializationDecl *Result
+        = InstClassTemplate->findPartialSpecInstantiatedFromMember(D))
+    return Result;
+
+  return InstantiateClassTemplatePartialSpecialization(InstClassTemplate, D);
 }
 
 Decl *
@@ -1818,8 +1747,9 @@
 /// \param PartialSpec the (uninstantiated) class template partial 
 /// specialization that we are instantiating.
 ///
-/// \returns true if there was an error, false otherwise.
-bool 
+/// \returns The instantiated partial specialization, if successful; otherwise,
+/// NULL to indicate an error.
+ClassTemplatePartialSpecializationDecl *
 TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
                                             ClassTemplateDecl *ClassTemplate,
                           ClassTemplatePartialSpecializationDecl *PartialSpec) {
@@ -1833,7 +1763,7 @@
   TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
   TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
   if (!InstParams)
-    return true;
+    return 0;
   
   // Substitute into the template arguments of the class template partial
   // specialization.
@@ -1845,7 +1775,7 @@
   for (unsigned I = 0; I != N; ++I) {
     TemplateArgumentLoc Loc;
     if (SemaRef.Subst(PartialSpecTemplateArgs[I], Loc, TemplateArgs))
-      return true;
+      return 0;
     InstTemplateArgs.addArgument(Loc);
   }
   
@@ -1859,7 +1789,7 @@
                                         InstTemplateArgs, 
                                         false,
                                         Converted))
-    return true;
+    return 0;
 
   // Figure out where to insert this class template partial specialization
   // in the member template's set of class template partial specializations.
@@ -1906,10 +1836,10 @@
     //   Outer<int, int> outer; // error: the partial specializations of Inner
     //                          // have the same signature.
     SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared)
-      << WrittenTy;
+      << WrittenTy->getType();
     SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here)
       << SemaRef.Context.getTypeDeclType(PrevDecl);
-    return true;
+    return 0;
   }
   
   
@@ -1936,7 +1866,7 @@
   // Add this partial specialization to the set of class template partial
   // specializations.
   ClassTemplate->AddPartialSpecialization(InstPartialSpec, InsertPos);
-  return false;
+  return InstPartialSpec;
 }
 
 TypeSourceInfo*

Modified: cfe/branches/Apple/whitney/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp?rev=119250&r1=119249&r2=119250&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp (original)
+++ cfe/branches/Apple/whitney/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp Mon Nov 15 15:46:08 2010
@@ -53,3 +53,24 @@
 int array3[X0<float>::Inner0<int>::value == 0? 1 : -1];
 int array4[X0<float>::Inner0<int*>::value == 3? 1 : -1];
 int array5[X0<float>::Inner0<const int*>::value == 2? 1 : -1];
+
+namespace rdar8651930 {
+  template<typename OuterT>
+  struct Outer {
+    template<typename T, typename U>
+    struct Inner;
+
+    template<typename T>
+    struct Inner<T, T> { 
+      static const bool value = true;
+    };
+
+    template<typename T, typename U>
+    struct Inner { 
+      static const bool value = false;
+    };
+  };
+
+  int array0[Outer<int>::Inner<int, int>::value? 1 : -1];
+  int array1[Outer<int>::Inner<int, float>::value? -1 : 1];
+}

Modified: cfe/branches/Apple/whitney/test/SemaTemplate/explicit-specialization-member.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/test/SemaTemplate/explicit-specialization-member.cpp?rev=119250&r1=119249&r2=119250&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/test/SemaTemplate/explicit-specialization-member.cpp (original)
+++ cfe/branches/Apple/whitney/test/SemaTemplate/explicit-specialization-member.cpp Mon Nov 15 15:46:08 2010
@@ -13,11 +13,9 @@
 namespace PR6161 {
   template<typename _CharT>
   class numpunct : public locale::facet // expected-error{{use of undeclared identifier 'locale'}} \
-              // expected-error{{expected class name}} \
-  // expected-note{{attempt to specialize declaration here}}
+              // expected-error{{expected class name}}
   {
     static locale::id id; // expected-error{{use of undeclared identifier}}
   };
-  numpunct<char>::~numpunct(); // expected-error{{template specialization requires 'template<>'}} \
-  // expected-error{{specialization of member 'PR6161::numpunct<char>::~numpunct' does not specialize an instantiated member}}
+  numpunct<char>::~numpunct(); // expected-error{{expected the class name after '~' to name a destructor}}
 }





More information about the llvm-branch-commits mailing list