Commit a4d674fc by Jason Merrill Committed by Jason Merrill

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
parent 63787194
2009-04-03 Jason Merrill <jason@redhat.com> 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 PR c++/39608
* semantics.c (finish_id_expression): Don't assume a dependent * semantics.c (finish_id_expression): Don't assume a dependent
member of the current instantiation isn't a valid integral member of the current instantiation isn't a valid integral
......
...@@ -275,11 +275,15 @@ dump_template_bindings (tree parms, tree args, VEC(tree,gc)* typenames) ...@@ -275,11 +275,15 @@ dump_template_bindings (tree parms, tree args, VEC(tree,gc)* typenames)
{ {
if (need_comma) if (need_comma)
pp_separate_with_comma (cxx_pp); pp_separate_with_comma (cxx_pp);
dump_type (t, 0); dump_type (t, TFF_PLAIN_IDENTIFIER);
pp_cxx_whitespace (cxx_pp); pp_cxx_whitespace (cxx_pp);
pp_equal (cxx_pp); pp_equal (cxx_pp);
pp_cxx_whitespace (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) ...@@ -390,6 +394,12 @@ dump_type (tree t, int flags)
break; break;
} }
case TYPENAME_TYPE: 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_cv_qualifier_seq (cxx_pp, t);
pp_cxx_identifier (cxx_pp, pp_cxx_identifier (cxx_pp,
TYPENAME_IS_ENUM_P (t) ? "enum" TYPENAME_IS_ENUM_P (t) ? "enum"
...@@ -1089,7 +1099,7 @@ dump_template_decl (tree t, int flags) ...@@ -1089,7 +1099,7 @@ dump_template_decl (tree t, int flags)
} }
/* find_typenames looks through the type of the function template T /* 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 struct find_typenames_t
{ {
...@@ -1098,26 +1108,27 @@ struct find_typenames_t ...@@ -1098,26 +1108,27 @@ struct find_typenames_t
}; };
static tree 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; 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 /* Search into class template arguments, which cp_walk_subtrees
doesn't do. */ doesn't do. */
else if (CLASS_TYPE_P (*tp) && CLASSTYPE_TEMPLATE_INFO (*tp)) if (CLASS_TYPE_P (*tp) && CLASSTYPE_TEMPLATE_INFO (*tp))
{ cp_walk_tree (&CLASSTYPE_TI_ARGS (*tp), find_typenames_r,
cp_walk_tree (&CLASSTYPE_TI_ARGS (*tp), find_typenames_r, data, d->p_set);
data, d->p_set);
*walk_subtrees = 0;
}
return NULL_TREE; return NULL_TREE;
} }
......
...@@ -13538,6 +13538,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) ...@@ -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. */ ISO C++, so we can do as we please here. */
if (variably_modified_type_p (arg, NULL_TREE)) if (variably_modified_type_p (arg, NULL_TREE))
return 1; 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 /* If ARG is a parameter pack or an expansion, we cannot unify
......
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> 2009-04-04 Paul Thomas <pault@gcc.gnu.org>
PR fortran/37614 PR fortran/37614
......
// 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) // in diagnostics (PR c++/25185)
template <class T> template <class T>
struct A { struct A {
typename T::type f(); // { dg-message "typename T::type = void*" } typename T::type f(); // { dg-message "typename T::type = void*" }
void f(int i = 0); // { dg-message "" } 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 struct B
...@@ -12,8 +16,22 @@ struct B ...@@ -12,8 +16,22 @@ struct B
typedef void* type; 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() int main()
{ {
A<B> a; A<B> a;
a.f(); // { dg-error "" } a.f(); // { dg-error "" }
a.g(); // { dg-error "" }
f(i); // { dg-error "" }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment