aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-04-04 15:19:30 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-04-04 15:19:30 -0400
commita4d674fc530e3a274c86887967eb820a664787da (patch)
tree7b4bc71795218eb2c8c2cae02b63194fbc85ad9c
parent63787194e1a9a90650caf40922dc09b31a0501bd (diff)
downloadgcc-a4d674fc530e3a274c86887967eb820a664787da.zip
gcc-a4d674fc530e3a274c86887967eb820a664787da.tar.gz
gcc-a4d674fc530e3a274c86887967eb820a664787da.tar.bz2
re PR c++/25185 (deep typedef substitution in error message)
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
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/error.c47
-rw-r--r--gcc/cp/pt.c3
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/error38.C20
5 files changed, 63 insertions, 19 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9bc48b6..688b1a8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
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/ChangeLog b/gcc/testsuite/ChangeLog
index be66288..57947f5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
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 "" }
}