This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: C++ PATCH for c++/25185 (unhelpful diagnostics)


Apparently Dodji's patch to create typedef variants in classes caused more typedefs to show up, so we need to either look through them or add them to the list of bindings. I decided to do both: leave them in the template signature, add them to the bindings list, and look through them at that point. And if we're doing that, we might as well print typedefs for typenames as well as classes.

Incidentally, our typedef handling is pretty haphazard currently; doing it for some types and not others doesn't make a lot of sense. And some types get handed off to c-pretty-print.c, which doesn't respect TFF_CHASE_TYPEDEF. I thought about regularizing it to print typedef names for all types, but I think that might make error messages less helpful rather than more, so I limited my change to TYPENAME_TYPEs, where I know that we're going to explain what they mean anyway.

We also weren't canonicalizing deduced types at all, so
I added code to unify to do that. The canonical_type_variant code predates TYPE_CANONICAL, so it doesn't fully canonicalize the type; I tried changing it to use TYPE_CANONICAL, but that ran into problems with losing template parameter names and attributes, so I backed off. We'll just have to accept for now that a template argument that is, say, pointer to typedef doesn't have the typedef stripped.


Tested x86_64-pc-linux-gnu, applied to trunk.
2009-04-03  Jason Merrill  <jason@redhat.com>

 	PR c++/25185
	* error.c (dump_template_bindings): Look through typedefs in
	typename results.
	(dump_type) [TYPENAME_TYPE]: Print the typedef name if any.
	(find_typenames_r): Also collect typedefs.
	* pt.c (unify): Strip typedefs.

diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index a3d6cc7..8b31980 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -275,11 +275,15 @@ dump_template_bindings (tree parms, tree args, VEC(tree,gc)* typenames)
     {
       if (need_comma)
 	pp_separate_with_comma (cxx_pp);
-      dump_type (t, 0);
+      dump_type (t, TFF_PLAIN_IDENTIFIER);
       pp_cxx_whitespace (cxx_pp);
       pp_equal (cxx_pp);
       pp_cxx_whitespace (cxx_pp);
-      dump_type (tsubst (t, args, tf_none, NULL_TREE), 0);
+      t = tsubst (t, args, tf_none, NULL_TREE);
+      /* Strip typedefs.  We can't just use TFF_CHASE_TYPEDEF because
+	 pp_simple_type_specifier doesn't know about it.  */
+      t = canonical_type_variant (t);
+      dump_type (t, TFF_PLAIN_IDENTIFIER);
     }
 }
 
@@ -390,6 +394,12 @@ dump_type (tree t, int flags)
       break;
     }
     case TYPENAME_TYPE:
+      if (! (flags & TFF_CHASE_TYPEDEF)
+	  && DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
+	{
+	  dump_decl (TYPE_NAME (t), TFF_PLAIN_IDENTIFIER);
+	  break;
+	}
       pp_cxx_cv_qualifier_seq (cxx_pp, t);
       pp_cxx_identifier (cxx_pp,
 			 TYPENAME_IS_ENUM_P (t) ? "enum"
@@ -1089,7 +1099,7 @@ dump_template_decl (tree t, int flags)
 }
 
 /* find_typenames looks through the type of the function template T
-   and returns a VEC containing any TYPENAME_TYPEs it finds.  */
+   and returns a VEC containing any typedefs or TYPENAME_TYPEs it finds.  */
 
 struct find_typenames_t
 {
@@ -1098,26 +1108,27 @@ struct find_typenames_t
 };
 
 static tree
-find_typenames_r (tree *tp, int *walk_subtrees, void *data)
+find_typenames_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
 {
   struct find_typenames_t *d = (struct find_typenames_t *)data;
+  tree mv = NULL_TREE;
+
+  if (TYPE_P (*tp) && is_typedef_decl (TYPE_NAME (*tp)))
+    /* Add the type of the typedef without any additional cv-quals.  */
+    mv = TREE_TYPE (TYPE_NAME (*tp));
+  else if (TREE_CODE (*tp) == TYPENAME_TYPE)
+    /* Add the typename without any cv-qualifiers.  */
+    mv = TYPE_MAIN_VARIANT (*tp);
+
+  if (mv && (mv == *tp || !pointer_set_insert (d->p_set, mv)))
+    VEC_safe_push (tree, gc, d->typenames, mv);
 
-  if (TREE_CODE (*tp) == TYPENAME_TYPE)
-    {
-      /* Discard any cv-qualifiers.  */
-      tree mv = TYPE_MAIN_VARIANT (*tp);
-      if (mv == *tp || !pointer_set_insert (d->p_set, mv))
-	VEC_safe_push (tree, gc, d->typenames, mv);
-      *walk_subtrees = 0;
-    }
   /* Search into class template arguments, which cp_walk_subtrees
      doesn't do.  */
-  else if (CLASS_TYPE_P (*tp) && CLASSTYPE_TEMPLATE_INFO (*tp))
-    {
-      cp_walk_tree (&CLASSTYPE_TI_ARGS (*tp), find_typenames_r,
-		    data, d->p_set);
-      *walk_subtrees = 0;
-    }
+  if (CLASS_TYPE_P (*tp) && CLASSTYPE_TEMPLATE_INFO (*tp))
+    cp_walk_tree (&CLASSTYPE_TI_ARGS (*tp), find_typenames_r,
+		  data, d->p_set);
+
   return NULL_TREE;
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 90be6bc..3e3d4f2 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13538,6 +13538,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	     ISO C++, so we can do as we please here.  */
 	  if (variably_modified_type_p (arg, NULL_TREE))
 	    return 1;
+
+	  /* Strip typedefs as in convert_template_argument.  */
+	  arg = canonical_type_variant (arg);
 	}
 
       /* If ARG is a parameter pack or an expansion, we cannot unify
diff --git a/gcc/testsuite/g++.dg/template/error38.C b/gcc/testsuite/g++.dg/template/error38.C
index a444b1a..e26345f 100644
--- a/gcc/testsuite/g++.dg/template/error38.C
+++ b/gcc/testsuite/g++.dg/template/error38.C
@@ -1,10 +1,14 @@
-// Testcase for printing typename bindings as well as template args
+// Testcase for printing typename/typedef bindings as well as template args
 // in diagnostics (PR c++/25185)
 
 template <class T>
 struct A {
   typename T::type f();		// { dg-message "typename T::type = void*" }
   void f(int i = 0);		// { dg-message "" }
+
+  typedef typename T::type mytype;
+  mytype g();			// { dg-message "mytype = void*" }
+  void g(int i = 0);		// { dg-message "" }
 };
 
 struct B
@@ -12,8 +16,22 @@ struct B
   typedef void* type;
 };
 
+// Also make sure that deduced template arguments get canonicalized.
+
+template <class T>
+void f (T &t);			// { dg-message "T = int" }
+
+template <class T>
+void f (T &t, int = 0);		// { dg-message "" }
+
+typedef int myint;
+myint i;
+
 int main()
 {
   A<B> a;
   a.f();			// { dg-error "" }
+  a.g();			// { dg-error "" }
+
+  f(i);				// { dg-error "" }
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]