]> granicus.if.org Git - clang/commitdiff
Finish implementing checking of class template partial specializations
authorDouglas Gregor <dgregor@apple.com>
Fri, 12 Jun 2009 22:21:45 +0000 (22:21 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 12 Jun 2009 22:21:45 +0000 (22:21 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73260 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/Sema.h
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiate.cpp
test/SemaTemplate/temp_class_spec.cpp
test/SemaTemplate/temp_class_spec_neg.cpp
www/cxx_status.html

index 16d490f09b2658dae9c50d77ce8717b6d47c3dbc..899fd768dcaa17a9065ceda1afcb28bc360d1c88 100644 (file)
@@ -743,18 +743,19 @@ def err_template_spec_needs_header : Error<
 def err_template_spec_extra_headers : Error<
   "template specialization must have a single 'template<>' header">;
 def err_template_spec_decl_out_of_scope_global : Error<
-  "class template specialization of %0 must occur in the global scope">;
+  "class template %select{|partial }0specialization of %1 must occur in the "
+  "global scope">;
 def err_template_spec_decl_out_of_scope : Error<
-  "class template specialization of %0 not in namespace %1">;
+  "class template %select{|partial }0specialization of %1 not in namespace %2">;
 def err_template_spec_decl_function_scope : Error<
-  "%select{class template specialization|explicit instantiation}0 of %1 "
-  "in function scope">;
+  "%select{class template specialization|class template partial specialization|"
+  "explicit instantiation}0 of %1 in function scope">;
 def err_template_spec_redecl_out_of_scope : Error<
-  "%select{class template specialization|explicit instantiation}0 of %1 "
-  "not in a namespace enclosing %2">;
+  "%select{class template specialization|class template partial specialization|"
+  "explicit instantiation}0 of %1 not in a namespace enclosing %2">;
 def err_template_spec_redecl_global_scope : Error<
-  "%select{class template specialization|explicit instantiation}0 of %1 must "
-  "occur at global scope">;
+  "%select{class template specialization|class template partial specialization|"
+  "explicit instantiation}0 of %1 must occur at global scope">;
 
 // C++ Class Template Partial Specialization
 def err_default_arg_in_partial_spec : Error<
index 3315952723cb6029a6f887f70c5fc334840c2ef4..c54b5947f16b5733084156c1314de93f2a7b87bb 100644 (file)
@@ -1950,6 +1950,7 @@ public:
                                     ClassTemplateSpecializationDecl *PrevDecl,
                                              SourceLocation TemplateNameLoc,
                                              SourceRange ScopeSpecifierRange,
+                                             bool PartialSpecialization,
                                              bool ExplicitInstantiation);
 
   bool CheckClassTemplatePartialSpecializationArgs(
index b1a8ef2f7fcabfffe6e9a76107238b46d4a4831a..ec2907f65a76e66ba7c5e30c5fc66c5a072229d3 100644 (file)
@@ -1932,6 +1932,7 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
                                    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 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
   //   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 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
     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 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
     // 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 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
   if (CheckClassTemplateSpecializationScope(ClassTemplate, PrevDecl,
                                             TemplateNameLoc, 
                                             SS.getRange(),
+                                            isPartialSpecialization,
                                             /*ExplicitInstantiation=*/false))
     return true;
 
@@ -2440,6 +2445,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
   if (CheckClassTemplateSpecializationScope(ClassTemplate, 0,
                                             TemplateNameLoc, 
                                             SS.getRange(),
+                                            /*PartialSpecialization=*/false,
                                             /*ExplicitInstantiation=*/true))
     return true;
 
index e5a9675a03515f0def8296945580ed4b7b6d952e..936df1e97decfce80381a2702c0e49476fe329cf 100644 (file)
@@ -854,8 +854,11 @@ Sema::InstantiateClassTemplateSpecialization(
   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;
index ce1459b1d2bb4162d5d352140bc3cc1eea712f8b..6fedce76ae05f85b5f05d41a62240d4169a5a252 100644 (file)
@@ -255,3 +255,10 @@ int is_nested_value_type_identity1[
 //int is_nested_value_type_identity2[
 //                   is_nested_value_type_identity<NoValueType>::value? -1 : 1];
 
+
+// C++ [temp.class.spec]p4:
+template<class T1, class T2, int I> class A { }; //#1 
+template<class T, int I> class A<T, T*, I> { }; //#2 
+template<class T1, class T2, int I> class A<T1*, T2, I> { }; //#3 
+template<class T> class A<int, T*, 5> { }; //#4 
+template<class T1, class T2, int I> class A<T1, T2*, I> { }; //#5 
index d303146dceaffb20d338af26c4faca7ad05c33c2..b9a12cb4de4033b747a43f84a4e4a62741ac5d91 100644 (file)
@@ -1,8 +1,17 @@
 // RUN: clang-cc -fsyntax-only -verify %s
 template<typename T> struct vector;
 
-// C++ [temp.class.spec]p9
+// C++ [temp.class.spec]p6:
+namespace N {
+  namespace M {
+    template<typename T> struct A; // expected-note{{here}}
+  }
+}
+
+template<typename T>
+struct N::M::A<T*> { }; // expected-error{{not in namespace}}
 
+// C++ [temp.class.spec]p9
 //   bullet 1
 template <int I, int J> struct A {}; 
 template <int I> struct A<I+5, I*2> {}; // expected-error{{depends on}} 
index 3a9a7290fc8662b187dadf8efa2b91d272ad2c4b..06f541b5347fabd75e3a91ea7157fd9a748be0c6 100644 (file)
@@ -1887,7 +1887,7 @@ welcome!</p>
   <td>&nbsp;&nbsp;&nbsp;&nbsp;14.5.4 [temp.class.spec]</td>
   <td class="complete" align="center"></td>  
   <td class="complete" align="center"></td>
-  <td class="medium" align="center"></td>
+  <td class="complete" align="center"></td>
   <td class="na" align="center">N/A</td>
   <td></td>
 </tr>