]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/25185 (deep typedef substitution in error message)
authorJason Merrill <jason@redhat.com>
Sat, 4 Apr 2009 19:19:30 +0000 (15:19 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 4 Apr 2009 19:19:30 +0000 (15:19 -0400)
        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.

From-SVN: r145550

gcc/cp/ChangeLog
gcc/cp/error.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/error38.C

index 9bc48b6baf4364593c209973680db433433a48c2..688b1a8441e5504244038fd6d04b0609603ba596 100644 (file)
@@ -1,5 +1,12 @@
 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.
+
        PR c++/39608
        * semantics.c (finish_id_expression): Don't assume a dependent
        member of the current instantiation isn't a valid integral
index a3d6cc7326279fdb14a4c86d43a2fd5790ecacd9..8b31980331f1987199194905c6f9b8c11cf796b6 100644 (file)
@@ -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;
 }
 
index 90be6bcf9c05560d7905877bb8079cf098224e57..3e3d4f250f28862c0ac86f3c011a29602e138be6 100644 (file)
@@ -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
index be66288f75f62560a410f2f9f9545d962d7f3d8b..57947f5ad6571f976187e0184827c7058bb0b8fd 100644 (file)
@@ -1,3 +1,8 @@
+2009-04-04  Jason Merrill  <jason@redhat.com>
+
+       PR c++/25185
+       * g++.dg/template/error38.C: Add more tests.
+
 2009-04-04  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/37614
index a444b1a233f3296d47cf9e26b3acf829d2428ceb..e26345f29a3ae4d720667865c1fe2ea6844f0c59 100644 (file)
@@ -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 "" }
 }