Finish implementing checking of class template partial specializations

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73260 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 3315952..c54b594 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1950,6 +1950,7 @@
                                     ClassTemplateSpecializationDecl *PrevDecl,
                                              SourceLocation TemplateNameLoc,
                                              SourceRange ScopeSpecifierRange,
+                                             bool PartialSpecialization,
                                              bool ExplicitInstantiation);
 
   bool CheckClassTemplatePartialSpecializationArgs(
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index b1a8ef2..ec2907f 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1932,6 +1932,7 @@
                                    ClassTemplateSpecializationDecl *PrevDecl,
                                             SourceLocation TemplateNameLoc,
                                             SourceRange ScopeSpecifierRange,
+                                            bool PartialSpecialization,
                                             bool ExplicitInstantiation) {
   // C++ [temp.expl.spec]p2:
   //   An explicit specialization shall be declared in the namespace
@@ -1947,8 +1948,9 @@
   //   that encloses the one in which the explicit specialization was
   //   declared.
   if (CurContext->getLookupContext()->isFunctionOrMethod()) {
+    int Kind = ExplicitInstantiation? 2 : PartialSpecialization? 1 : 0;
     Diag(TemplateNameLoc, diag::err_template_spec_decl_function_scope)
-      << ExplicitInstantiation << ClassTemplate;
+      << Kind << ClassTemplate;
     return true;
   }
 
@@ -1963,11 +1965,12 @@
     if (DC != TemplateContext) {
       if (isa<TranslationUnitDecl>(TemplateContext))
         Diag(TemplateNameLoc, diag::err_template_spec_decl_out_of_scope_global)
+          << PartialSpecialization
           << ClassTemplate << ScopeSpecifierRange;
       else if (isa<NamespaceDecl>(TemplateContext))
         Diag(TemplateNameLoc, diag::err_template_spec_decl_out_of_scope)
-          << ClassTemplate << cast<NamedDecl>(TemplateContext) 
-          << ScopeSpecifierRange;
+          << PartialSpecialization << ClassTemplate 
+          << cast<NamedDecl>(TemplateContext) << ScopeSpecifierRange;
 
       Diag(ClassTemplate->getLocation(), diag::note_template_decl_here);
     }
@@ -1981,16 +1984,17 @@
     // FIXME:  In C++98,  we  would like  to  turn these  errors into  warnings,
     // dependent on a -Wc++0x flag.
     bool SuppressedDiag = false;
+    int Kind = ExplicitInstantiation? 2 : PartialSpecialization? 1 : 0;
     if (isa<TranslationUnitDecl>(TemplateContext)) {
       if (!ExplicitInstantiation || getLangOptions().CPlusPlus0x)
         Diag(TemplateNameLoc, diag::err_template_spec_redecl_global_scope)
-          << ExplicitInstantiation << ClassTemplate << ScopeSpecifierRange;
+          << Kind << ClassTemplate << ScopeSpecifierRange;
       else
         SuppressedDiag = true;
     } else if (isa<NamespaceDecl>(TemplateContext)) {
       if (!ExplicitInstantiation || getLangOptions().CPlusPlus0x)
         Diag(TemplateNameLoc, diag::err_template_spec_redecl_out_of_scope)
-          << ExplicitInstantiation << ClassTemplate
+          << Kind << ClassTemplate
           << cast<NamedDecl>(TemplateContext) << ScopeSpecifierRange;
       else 
         SuppressedDiag = true;
@@ -2285,6 +2289,7 @@
   if (CheckClassTemplateSpecializationScope(ClassTemplate, PrevDecl,
                                             TemplateNameLoc, 
                                             SS.getRange(),
+                                            isPartialSpecialization,
                                             /*ExplicitInstantiation=*/false))
     return true;
 
@@ -2440,6 +2445,7 @@
   if (CheckClassTemplateSpecializationScope(ClassTemplate, 0,
                                             TemplateNameLoc, 
                                             SS.getRange(),
+                                            /*PartialSpecialization=*/false,
                                             /*ExplicitInstantiation=*/true))
     return true;
 
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index e5a9675..936df1e 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -854,8 +854,11 @@
   const TemplateArgumentList *TemplateArgs 
     = &ClassTemplateSpec->getTemplateArgs();
 
-  // Determine whether any class template partial specializations
-  // match the given template arguments.
+  // C++ [temp.class.spec]p7:
+  //   Partial specialization declarations themselves are not found by
+  //   name lookup. Rather, when the primary template name is used,
+  //   any previously declared partial specializations of the primary
+  //   template are also considered.
   typedef std::pair<ClassTemplatePartialSpecializationDecl *,
                     TemplateArgumentList *> MatchResult;
   llvm::SmallVector<MatchResult, 4> Matched;