[cfe-commits] r73254 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiateExpr.cpp test/SemaTemplate/temp_class_spec.cpp test/SemaTemplate/temp_class_spec_neg.cpp

Douglas Gregor dgregor at apple.com
Fri Jun 12 14:21:02 PDT 2009


Author: dgregor
Date: Fri Jun 12 16:21:02 2009
New Revision: 73254

URL: http://llvm.org/viewvc/llvm-project?rev=73254&view=rev
Log:
Diagnose the incorrect use of non-type template arguments for class
template partial specializations.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
    cfe/trunk/test/SemaTemplate/temp_class_spec.cpp
    cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=73254&r1=73253&r2=73254&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 12 16:21:02 2009
@@ -759,6 +759,12 @@
 // C++ Class Template Partial Specialization
 def err_default_arg_in_partial_spec : Error<
     "default template argument in a class template partial specialization">;
+def err_dependent_non_type_arg_in_partial_spec : Error<
+    "non-type template argument depends on a template parameter of the "
+    "partial specialization">;
+def err_dependent_typed_non_type_arg_in_partial_spec : Error<
+    "non-type template argument specializes a template parameter with "
+    "dependent type %0">;
 def unsup_template_partial_spec_ordering : Error<
   "partial ordering of class template partial specializations is not yet "
   "supported">;

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=73254&r1=73253&r2=73254&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Jun 12 16:21:02 2009
@@ -1952,6 +1952,10 @@
                                              SourceRange ScopeSpecifierRange,
                                              bool ExplicitInstantiation);
 
+  bool CheckClassTemplatePartialSpecializationArgs(
+                                        TemplateParameterList *TemplateParams,
+                                        const TemplateArgument *TemplateArgs);
+
   virtual DeclResult
   ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
                                    SourceLocation KWLoc, 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=73254&r1=73253&r2=73254&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Jun 12 16:21:02 2009
@@ -2003,6 +2003,68 @@
   return false;
 }
 
+/// \brief Check the non-type template arguments of a class template
+/// partial specialization according to C++ [temp.class.spec]p9.
+///
+/// \returns true if there was an error, false otherwise.
+bool Sema::CheckClassTemplatePartialSpecializationArgs(
+                                        TemplateParameterList *TemplateParams,
+                                        const TemplateArgument *TemplateArgs) {
+  // FIXME: the interface to this function will have to change to
+  // accommodate variadic templates.
+
+  for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+    NonTypeTemplateParmDecl *Param 
+      = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
+    if (!Param)
+      continue;
+    
+    Expr *ArgExpr = TemplateArgs[I].getAsExpr();
+    if (!ArgExpr)
+      continue;
+
+    // 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
+    //   specialized.
+    //
+    // Below, we check the two conditions that only apply to
+    // specialized non-type arguments, so skip any non-specialized
+    // arguments.
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr))
+      if (isa<NonTypeTemplateParmDecl>(DRE->getDecl()))
+        continue;
+
+    // C++ [temp.class.spec]p9:
+    //   Within the argument list of a class template partial
+    //   specialization, the following restrictions apply:
+    //     -- A partially specialized non-type argument expression
+    //        shall not involve a template parameter of the partial
+    //        specialization except when the argument expression is a
+    //        simple identifier.
+    if (ArgExpr->isTypeDependent() || ArgExpr->isValueDependent()) {
+      Diag(ArgExpr->getLocStart(), 
+           diag::err_dependent_non_type_arg_in_partial_spec)
+        << ArgExpr->getSourceRange();
+      return true;
+    }
+
+    //     -- The type of a template parameter corresponding to a
+    //        specialized non-type argument shall not be dependent on a
+    //        parameter of the specialization.
+    if (Param->getType()->isDependentType()) {
+      Diag(ArgExpr->getLocStart(), 
+           diag::err_dependent_typed_non_type_arg_in_partial_spec)
+        << Param->getType()
+        << ArgExpr->getSourceRange();
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+  }
+
+  return false;
+}
+
 Sema::DeclResult
 Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
                                        SourceLocation KWLoc, 
@@ -2117,6 +2179,11 @@
   // corresponds to these arguments.
   llvm::FoldingSetNodeID ID;
   if (isPartialSpecialization) {
+    if (CheckClassTemplatePartialSpecializationArgs(
+                                         ClassTemplate->getTemplateParameters(),
+                                   ConvertedTemplateArgs.getFlatArgumentList()))
+      return true;
+
     // FIXME: Template parameter list matters, too
     ClassTemplatePartialSpecializationDecl::Profile(ID, 
                                     ConvertedTemplateArgs.getFlatArgumentList(),

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp?rev=73254&r1=73253&r2=73254&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Fri Jun 12 16:21:02 2009
@@ -112,6 +112,14 @@
   if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
     assert(NTTP->getDepth() == 0 && "No nested templates yet");
     const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()]; 
+
+    // The template argument itself might be an expression, in which
+    // case we just return that expression.
+    if (Arg.getKind() == TemplateArgument::Expression)
+      // FIXME: Clone the expression!
+      return SemaRef.Owned(Arg.getAsExpr());
+
+    assert(Arg.getKind() == TemplateArgument::Integral);
     QualType T = Arg.getIntegralType();
     if (T->isCharType() || T->isWideCharType())
       return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(

Modified: cfe/trunk/test/SemaTemplate/temp_class_spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_class_spec.cpp?rev=73254&r1=73253&r2=73254&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_class_spec.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_class_spec.cpp Fri Jun 12 16:21:02 2009
@@ -255,48 +255,3 @@
 //int is_nested_value_type_identity2[
 //                   is_nested_value_type_identity<NoValueType>::value? -1 : 1];
 
-// FIXME: The tests that follow are stress-tests for the substitution
-// of deduced template arguments into the template argument list of a
-// partial specialization. I believe that we'll need this code for
-// substitution into function templates, but note that the examples
-// below are ill-formed and should eventually be removed.
-template<typename T, int N>
-struct is_sizeof_T {
-  static const bool value = false;
-};
-
-template<typename T>
-struct is_sizeof_T<T, sizeof(T)> {
-  static const bool value = true;
-};
-
-int is_sizeof_T0[is_sizeof_T<int, sizeof(int)>::value? 1 : -1];
-int is_sizeof_T1[is_sizeof_T<int, sizeof(char)>::value? -1 : 1];
-
-template<typename T>
-struct HasStaticOfT {
-  static T value;
-  static T other_value;
-};
-
-struct DerivedStaticOfInt : HasStaticOfT<int> { };
-
-template<typename X, typename T, T *Ptr>
-struct is_static_int_val {
-  static const bool value = false;
-};
-
-template<typename X, typename T>
-struct is_static_int_val<X, T, &X::value> {
-  static const bool value = true;
-};
-
-int is_static_int_val0[
-                 is_static_int_val<HasStaticOfT<int>, int, 
-                                   &HasStaticOfT<int>::value>::value ? 1 : -1];
-int is_static_int_val1[
-            is_static_int_val<HasStaticOfT<int>, int, 
-                              &HasStaticOfT<int>::other_value>::value ? -1 : 1];
-int is_static_int_val2[
-                 is_static_int_val<DerivedStaticOfInt, int, 
-                                   &HasStaticOfT<int>::value>::value ? 1 : -1];

Modified: cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp?rev=73254&r1=73253&r2=73254&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp Fri Jun 12 16:21:02 2009
@@ -2,6 +2,24 @@
 
 template<typename T> struct vector;
 
+// 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}} 
+template <int I, int J> struct B {}; 
+template <int I> struct B<I, I> {}; //OK 
+
+//   bullet 2
+template <class T, T t> struct C {};  // expected-note{{declared here}}
+template <class T> struct C<T, 1>; // expected-error{{specializes}}
+template <class T, T* t> struct C<T*, t>; // okay
+
+template< int X, int (*array_ptr)[X] > class A2 {}; // expected-note{{here}}
+int array[5]; 
+template< int X > class A2<X,&array> { }; // expected-error{{specializes}}
+
+// C++ [temp.class.spec]p10
 template<typename T, int N, template<typename X> class TT>
 struct Test0;
 





More information about the cfe-commits mailing list