diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/error.c | 47 | ||||
-rw-r--r-- | gcc/cp/pt.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/error38.C | 20 |
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 "" } } |