[cfe-commits] r94953 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp

Chandler Carruth chandlerc at gmail.com
Sun Jan 31 02:01:20 PST 2010


Author: chandlerc
Date: Sun Jan 31 04:01:20 2010
New Revision: 94953

URL: http://llvm.org/viewvc/llvm-project?rev=94953&view=rev
Log:
Fix PR6159 and several other problems with value-dependent non-type template
arguments. This both prevents meaningless checks on these arguments and ensures
that they are represented as an expression by the instantiation.

Cleaned up and added standard text to the relevant test case. Also started
adding tests for *rejected* cases. At least one FIXME here where (I think) we
allow something we shouldn't. More to come in the area of rejecting crazy
arguments with decent diagnostics. Suggestions welcome for still better
diagnostics on these errors!

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Jan 31 04:01:20 2010
@@ -1128,6 +1128,8 @@
 def err_template_arg_ref_bind_ignores_quals : Error<
   "reference binding of non-type template parameter of type %0 to template "
   "argument of type %1 ignores qualifiers">;
+def err_template_arg_not_decl_ref : Error<
+  "non-type template argument does not refer to any declaration">;
 def err_template_arg_not_object_or_func_form : Error<
   "non-type template argument does not directly refer to an object or "
   "function">;

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sun Jan 31 04:01:20 2010
@@ -2307,7 +2307,17 @@
   } else
     DRE = dyn_cast<DeclRefExpr>(Arg);
 
-  if (!DRE || !isa<ValueDecl>(DRE->getDecl()))
+  if (!DRE)
+    return Diag(Arg->getSourceRange().getBegin(),
+                diag::err_template_arg_not_decl_ref)
+      << Arg->getSourceRange();
+
+  // Stop checking the precise nature of the argument if it is value dependent,
+  // it should be checked when instantiated.
+  if (Arg->isValueDependent())
+    return false;
+
+  if (!isa<ValueDecl>(DRE->getDecl()))
     return Diag(Arg->getSourceRange().getBegin(),
                 diag::err_template_arg_not_object_or_func_form)
       << Arg->getSourceRange();
@@ -2658,9 +2668,13 @@
     if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
       return true;
 
-    if (Entity)
-      Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
-    Converted = TemplateArgument(Entity);
+    if (Arg->isValueDependent()) {
+      Converted = TemplateArgument(Arg);
+    } else {
+      if (Entity)
+        Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
+      Converted = TemplateArgument(Entity);
+    }
     return false;
   }
 
@@ -2698,9 +2712,13 @@
     if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
       return true;
 
-    if (Entity)
-      Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
-    Converted = TemplateArgument(Entity);
+    if (Arg->isValueDependent()) {
+      Converted = TemplateArgument(Arg);
+    } else {
+      if (Entity)
+        Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
+      Converted = TemplateArgument(Entity);
+    }
     return false;
   }
 
@@ -2740,8 +2758,12 @@
     if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
       return true;
 
-    Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
-    Converted = TemplateArgument(Entity);
+    if (Arg->isValueDependent()) {
+      Converted = TemplateArgument(Arg);
+    } else {
+      Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
+      Converted = TemplateArgument(Entity);
+    }
     return false;
   }
 

Modified: cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp?rev=94953&r1=94952&r2=94953&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp Sun Jan 31 04:01:20 2010
@@ -1,10 +1,57 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-template <const int* p> struct X { };
+// C++0x [temp.arg.nontype]p1:
+//
+//   A template-argument for a non-type, non-template template-parameter shall
+//   be one of:
+//   -- an integral constant expression; or
+//   -- the name of a non-type template-parameter ; or
+namespace non_type_tmpl_param {
+  template <int N> struct X0 { X0(); };
+  template <int N> X0<N>::X0() { }
+  template <int* N> struct X1 { X1(); };
+  template <int* N> X1<N>::X1() { }
+  template <int& N> struct X3 { X3(); };
+  template <int& N> X3<N>::X3() { }
+  template <int (*F)(int)> struct X4 { X4(); };
+  template <int (*F)(int)> X4<F>::X4() { }
+  template <typename T, int (T::* M)(int)> struct X5 { X5(); };
+  template <typename T, int (T::* M)(int)> X5<T, M>::X5() { }
+}
+
+//   -- the address of an object or function with external linkage, including
+//      function templates and function template-ids but excluding non-static
+//      class members, expressed as & id-expression where the & is optional if
+//      the name refers to a function or array, or if the corresponding
+//      template-parameter is a reference; or
+namespace addr_of_obj_or_func {
+  template <int* p> struct X0 { };
+  template <int (*fp)(int)> struct X1 { };
+  // FIXME: Add reference template parameter tests.
+
+  int i = 42;
+  int iarr[10];
+  int f(int i);
+  template <typename T> T f_tmpl(T t);
+  void test() {
+    X0<&i> x0a;
+    X0<iarr> x0b;
+    X1<&f> x1a;
+    X1<f> x1b;
+    X1<f_tmpl> x1c;
+    X1<f_tmpl<int> > x1d;
+  }
+}
+
+//   -- a constant expression that evaluates to a null pointer value (4.10); or
+//   -- a constant expression that evaluates to a null member pointer value
+//      (4.11); or
+//   -- a pointer to member expressed as described in 5.3.1.
 
-int i = 42;
-int* iptr = &i;
-void test() {
-  X<&i> x1;
-  X<iptr> x2;
+namespace bad_args {
+  template <int* N> struct X0 { };
+  int i = 42;
+  X0<&i + 2> x0a; // expected-error{{non-type template argument does not refer to any declaration}}
+  int* iptr = &i;
+  X0<iptr> x0b; // FIXME: This should not be accepted.
 }





More information about the cfe-commits mailing list