[cfe-commits] r122508 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp

Douglas Gregor dgregor at apple.com
Thu Dec 23 09:13:55 PST 2010


Author: dgregor
Date: Thu Dec 23 11:13:55 2010
New Revision: 122508

URL: http://llvm.org/viewvc/llvm-project?rev=122508&view=rev
Log:
Reimplement the comparison of a class template partial
specialization's template arguments against the primary template's
template arguments using the obvious, correct method of checking the
injected-class-name type (C++ [temp.class.spec]p9b3). The previous
incarnation of this comparison attempted to use its own formulation of
the injected-class-name, which is redudant and, with the introduction
of variadic templates, became wrong (again).

Added:
    cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp   (with props)
Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=122508&r1=122507&r2=122508&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Dec 23 11:13:55 2010
@@ -2912,8 +2912,7 @@
 
   bool CheckClassTemplatePartialSpecializationArgs(
                                         TemplateParameterList *TemplateParams,
-                        llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs,
-                                        bool &MirrorsPrimaryTemplate);
+                        llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs);
 
   DeclResult
   ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=122508&r1=122507&r2=122508&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Dec 23 11:13:55 2010
@@ -3915,71 +3915,25 @@
 /// \param TemplateArg the template arguments of the class template
 /// partial specialization.
 ///
-/// \param MirrorsPrimaryTemplate will be set true if the class
-/// template partial specialization arguments are identical to the
-/// implicit template arguments of the primary template. This is not
-/// necessarily an error (C++0x), and it is left to the caller to diagnose
-/// this condition when it is an error.
-///
 /// \returns true if there was an error, false otherwise.
 bool Sema::CheckClassTemplatePartialSpecializationArgs(
                                         TemplateParameterList *TemplateParams,
-                         llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs,
-                                        bool &MirrorsPrimaryTemplate) {
-  // FIXME: the interface to this function will have to change to
-  // accommodate variadic templates.
-  MirrorsPrimaryTemplate = true;
-
+                       llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs) {
   const TemplateArgument *ArgList = TemplateArgs.data();
 
   for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
-    // Determine whether the template argument list of the partial
-    // specialization is identical to the implicit argument list of
-    // the primary template. The caller may need to diagnostic this as
-    // an error per C++ [temp.class.spec]p9b3.
-    TemplateArgument MirrorArg = ArgList[I];
-    if (MirrorsPrimaryTemplate && 
-        MirrorArg.getKind() == TemplateArgument::Pack) {
-      if (MirrorArg.pack_size() == 1)
-        MirrorArg = *MirrorArg.pack_begin();
-      else
-        MirrorsPrimaryTemplate = false;
-    }
-
-    if (MirrorsPrimaryTemplate) {
-      if (TemplateTypeParmDecl *TTP
-            = dyn_cast<TemplateTypeParmDecl>(TemplateParams->getParam(I))) {        
-        if (MirrorsPrimaryTemplate &&
-            !Context.hasSameType(Context.getTypeDeclType(TTP), 
-                                 MirrorArg.getAsType()))
-          MirrorsPrimaryTemplate = false;
-      } else if (TemplateTemplateParmDecl *TTP
-                   = dyn_cast<TemplateTemplateParmDecl>(
-                                                 TemplateParams->getParam(I))) {
-        // FIXME: Variadic templates pack expansion/parameter pack
-        TemplateName Name = MirrorArg.getAsTemplate();
-        TemplateTemplateParmDecl *ArgDecl
-          = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl());
-        if (!ArgDecl ||
-            ArgDecl->getIndex() != TTP->getIndex() ||
-            ArgDecl->getDepth() != TTP->getDepth())
-          MirrorsPrimaryTemplate = false;
-      }
-    }
-
     NonTypeTemplateParmDecl *Param
       = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
-    if (!Param) {
+    if (!Param)
       continue;
-    }
 
     Expr *ArgExpr = ArgList[I].getAsExpr();
     if (!ArgExpr) {
-      // FIXME: Variadic templates pack expansion/parameter pack
-      MirrorsPrimaryTemplate = false;
       continue;
     }
 
+    // FIXME: Variadic templates. Unwrap argument packs.
+    
     // C++ [temp.class.spec]p8:
     //   A non-type argument is non-specialized if it is the name of a
     //   non-type parameter. All other non-type arguments are
@@ -3989,16 +3943,9 @@
     // specialized non-type arguments, so skip any non-specialized
     // arguments.
     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr))
-      if (NonTypeTemplateParmDecl *NTTP
-            = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl())) {
-        if (MirrorsPrimaryTemplate &&
-            (Param->getIndex() != NTTP->getIndex() ||
-             Param->getDepth() != NTTP->getDepth()))
-          MirrorsPrimaryTemplate = false;
-
+      if (llvm::isa<NonTypeTemplateParmDecl>(DRE->getDecl()))
         continue;
-      }
-
+    
     // C++ [temp.class.spec]p9:
     //   Within the argument list of a class template partial
     //   specialization, the following restrictions apply:
@@ -4024,8 +3971,6 @@
       Diag(Param->getLocation(), diag::note_template_param_here);
       return true;
     }
-
-    MirrorsPrimaryTemplate = false;
   }
 
   return false;
@@ -4184,30 +4129,11 @@
   // Find the class template (partial) specialization declaration that
   // corresponds to these arguments.
   if (isPartialSpecialization) {
-    bool MirrorsPrimaryTemplate;
     if (CheckClassTemplatePartialSpecializationArgs(
                                          ClassTemplate->getTemplateParameters(),
-                                         Converted, MirrorsPrimaryTemplate))
+                                         Converted))
       return true;
 
-    if (MirrorsPrimaryTemplate) {
-      // C++ [temp.class.spec]p9b3:
-      //
-      //   -- The argument list of the specialization shall not be identical
-      //      to the implicit argument list of the primary template.
-      Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
-        << (TUK == TUK_Definition)
-        << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
-      return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS,
-                                ClassTemplate->getIdentifier(),
-                                TemplateNameLoc,
-                                Attr,
-                                TemplateParams,
-                                AS_none);
-    }
-
-    // FIXME: Diagnose friend partial specializations
-
     if (!Name.isDependent() && 
         !TemplateSpecializationType::anyDependentTemplateArguments(
                                              TemplateArgs.getArgumentArray(), 
@@ -4261,8 +4187,25 @@
     // arguments of the class template partial specialization.
     TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
     CanonType = Context.getTemplateSpecializationType(CanonTemplate,
-                                                  Converted.data(),
-                                                  Converted.size());
+                                                      Converted.data(),
+                                                      Converted.size());
+    
+    if (Context.hasSameType(CanonType, 
+                        ClassTemplate->getInjectedClassNameSpecialization())) {
+      // C++ [temp.class.spec]p9b3:
+      //
+      //   -- The argument list of the specialization shall not be identical
+      //      to the implicit argument list of the primary template.
+      Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
+      << (TUK == TUK_Definition)
+      << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
+      return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS,
+                                ClassTemplate->getIdentifier(),
+                                TemplateNameLoc,
+                                Attr,
+                                TemplateParams,
+                                AS_none);
+    }
 
     // Create a new class template partial specialization declaration node.
     ClassTemplatePartialSpecializationDecl *PrevPartial

Added: cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp?rev=122508&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp Thu Dec 23 11:13:55 2010
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// -- The argument list of the specialization shall not be identical
+//    to the implicit argument list of the primary template.
+
+template<typename T, typename ...Types>
+struct X1; 
+
+template<typename T, typename ...Types>
+struct X1<T, Types...> // expected-error{{class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}}
+{ };
+
+

Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list