X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Ferror.c;h=a0ba51a6cebd31eee0482aee6b8888e8b23d9151;hb=abc9203d05ba4144a884af0d6f786e21da7b9315;hp=6121436a7949b53ca01cd9bf0a2041e56f847394;hpb=63949b3873397c4a0ee63894e2a164a1cc534989;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 6121436a794..a0ba51a6ceb 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1,12 +1,12 @@ /* Call-backs for C++ error reporting. This code is non-reentrant. Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, - 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) +the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, @@ -15,9 +15,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -30,7 +29,9 @@ Boston, MA 02110-1301, USA. */ #include "flags.h" #include "diagnostic.h" #include "langhooks-def.h" +#include "intl.h" #include "cxx-pretty-print.h" +#include "pointer-set.h" #define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',') @@ -40,6 +41,10 @@ Boston, MA 02110-1301, USA. */ static cxx_pretty_printer scratch_pretty_printer; #define cxx_pp (&scratch_pretty_printer) +/* Translate if being used for diagnostics, but not for dump files or + __PRETTY_FUNCTION. */ +#define M_(msgid) (pp_translate_identifiers (cxx_pp) ? _(msgid) : (msgid)) + # define NEXT_CODE(T) (TREE_CODE (TREE_TYPE (T))) static const char *args_to_string (tree, int); @@ -73,17 +78,20 @@ static void dump_global_iord (tree); static void dump_parameters (tree, int); static void dump_exception_spec (tree, int); static void dump_template_argument (tree, int); -static void dump_template_argument_list (tree, int); +static void dump_template_argument_list (tree, tree, int); static void dump_template_parameter (tree, int); -static void dump_template_bindings (tree, tree); +static void dump_template_bindings (tree, tree, VEC(tree,gc) *); static void dump_scope (tree, int); static void dump_template_parms (tree, int, int); +static int count_non_default_template_args (tree, tree); + static const char *function_category (tree); static void maybe_print_instantiation_context (diagnostic_context *); static void print_instantiation_full_context (diagnostic_context *); static void print_instantiation_partial_context (diagnostic_context *, - tree, location_t); + struct tinst_level *, + location_t); static void cp_diagnostic_starter (diagnostic_context *, diagnostic_info *); static void cp_diagnostic_finalizer (diagnostic_context *, diagnostic_info *); static void cp_print_error_function (diagnostic_context *, diagnostic_info *); @@ -139,24 +147,62 @@ static void dump_template_argument (tree arg, int flags) { if (ARGUMENT_PACK_P (arg)) - dump_template_argument_list (ARGUMENT_PACK_ARGS (arg), flags); + dump_template_argument_list (ARGUMENT_PACK_ARGS (arg), NULL_TREE, flags); else if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL) dump_type (arg, flags & ~TFF_CLASS_KEY_OR_ENUM); else - dump_expr (arg, (flags | TFF_EXPR_IN_PARENS) & ~TFF_CLASS_KEY_OR_ENUM); + { + if (TREE_CODE (arg) == TREE_LIST) + arg = TREE_VALUE (arg); + + dump_expr (arg, (flags | TFF_EXPR_IN_PARENS) & ~TFF_CLASS_KEY_OR_ENUM); + } +} + +/* Count the number of template arguments ARGS whose value does not + match the (optional) default template parameter in PARAMS */ + +static int +count_non_default_template_args (tree args, tree params) +{ + tree inner_args = INNERMOST_TEMPLATE_ARGS (args); + int n = TREE_VEC_LENGTH (inner_args); + int last; + + if (params == NULL_TREE || !flag_pretty_templates) + return n; + + for (last = n - 1; last >= 0; --last) + { + tree param = TREE_VEC_ELT (params, last); + tree def = TREE_PURPOSE (param); + + if (!def) + break; + if (uses_template_parms (def)) + { + ++processing_template_decl; + def = tsubst_copy_and_build (def, args, tf_none, NULL_TREE, false, true); + --processing_template_decl; + } + if (!cp_tree_equal (TREE_VEC_ELT (inner_args, last), def)) + break; + } + + return last + 1; } /* Dump a template-argument-list ARGS (always a TREE_VEC) under control of FLAGS. */ static void -dump_template_argument_list (tree args, int flags) +dump_template_argument_list (tree args, tree parms, int flags) { - int n = TREE_VEC_LENGTH (args); + int n = count_non_default_template_args (args, parms); int need_comma = 0; int i; - for (i = 0; i< n; ++i) + for (i = 0; i < n; ++i) { tree arg = TREE_VEC_ELT (args, i); @@ -191,9 +237,9 @@ dump_template_parameter (tree parm, int flags) { if (flags & TFF_DECL_SPECIFIERS) { - pp_cxx_identifier (cxx_pp, "class"); + pp_cxx_ws_string (cxx_pp, "class"); if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (p))) - pp_cxx_identifier (cxx_pp, "..."); + pp_cxx_ws_string (cxx_pp, "..."); if (DECL_NAME (p)) pp_cxx_tree_identifier (cxx_pp, DECL_NAME (p)); } @@ -222,9 +268,11 @@ dump_template_parameter (tree parm, int flags) TREE_VEC. */ static void -dump_template_bindings (tree parms, tree args) +dump_template_bindings (tree parms, tree args, VEC(tree,gc)* typenames) { int need_comma = 0; + int i; + tree t; while (parms) { @@ -232,18 +280,19 @@ dump_template_bindings (tree parms, tree args) int lvl = TMPL_PARMS_DEPTH (parms); int arg_idx = 0; int i; + tree lvl_args = NULL_TREE; + + /* Don't crash if we had an invalid argument list. */ + if (TMPL_ARGS_DEPTH (args) >= lvl) + lvl_args = TMPL_ARGS_LEVEL (args, lvl); for (i = 0; i < TREE_VEC_LENGTH (p); ++i) { tree arg = NULL_TREE; /* Don't crash if we had an invalid argument list. */ - if (TMPL_ARGS_DEPTH (args) >= lvl) - { - tree lvl_args = TMPL_ARGS_LEVEL (args, lvl); - if (NUM_TMPL_ARGS (lvl_args) > arg_idx) - arg = TREE_VEC_ELT (lvl_args, arg_idx); - } + if (lvl_args && NUM_TMPL_ARGS (lvl_args) > arg_idx) + arg = TREE_VEC_ELT (lvl_args, arg_idx); if (need_comma) pp_separate_with_comma (cxx_pp); @@ -254,7 +303,7 @@ dump_template_bindings (tree parms, tree args) if (arg) dump_template_argument (arg, TFF_PLAIN_IDENTIFIER); else - pp_identifier (cxx_pp, ""); + pp_string (cxx_pp, M_("")); ++arg_idx; need_comma = 1; @@ -262,6 +311,21 @@ dump_template_bindings (tree parms, tree args) parms = TREE_CHAIN (parms); } + + for (i = 0; VEC_iterate (tree, typenames, i, t); ++i) + { + if (need_comma) + pp_separate_with_comma (cxx_pp); + dump_type (t, TFF_PLAIN_IDENTIFIER); + pp_cxx_whitespace (cxx_pp); + pp_equal (cxx_pp); + pp_cxx_whitespace (cxx_pp); + 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 = strip_typedefs (t); + dump_type (t, TFF_PLAIN_IDENTIFIER); + } } /* Dump a human-readable equivalent of TYPE. FLAGS controls the @@ -279,7 +343,10 @@ dump_type (tree t, int flags) switch (TREE_CODE (t)) { case UNKNOWN_TYPE: - pp_identifier (cxx_pp, ""); + if (t == init_list_type_node) + pp_string (cxx_pp, M_("")); + else + pp_string (cxx_pp, M_("")); break; case TREE_LIST: @@ -321,6 +388,7 @@ dump_type (tree t, int flags) case BOOLEAN_TYPE: case COMPLEX_TYPE: case VECTOR_TYPE: + case FIXED_POINT_TYPE: pp_type_specifier_seq (cxx_pp, t); break; @@ -338,7 +406,7 @@ dump_type (tree t, int flags) pp_cxx_cv_qualifier_seq (cxx_pp, t); pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t)); pp_cxx_begin_template_argument_list (cxx_pp); - dump_template_argument_list (args, flags); + dump_template_argument_list (args, NULL_TREE, flags); pp_cxx_end_template_argument_list (cxx_pp); } break; @@ -367,8 +435,14 @@ 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, + pp_cxx_ws_string (cxx_pp, TYPENAME_IS_ENUM_P (t) ? "enum" : TYPENAME_IS_CLASS_P (t) ? "class" : "typename"); @@ -378,12 +452,12 @@ dump_type (tree t, int flags) case UNBOUND_CLASS_TEMPLATE: dump_type (TYPE_CONTEXT (t), flags); pp_cxx_colon_colon (cxx_pp); - pp_cxx_identifier (cxx_pp, "template"); + pp_cxx_ws_string (cxx_pp, "template"); dump_type (DECL_NAME (TYPE_NAME (t)), flags); break; case TYPEOF_TYPE: - pp_cxx_identifier (cxx_pp, "__typeof__"); + pp_cxx_ws_string (cxx_pp, "__typeof__"); pp_cxx_whitespace (cxx_pp); pp_cxx_left_paren (cxx_pp); dump_expr (TYPEOF_TYPE_EXPR (t), flags & ~TFF_EXPR_IN_PARENS); @@ -392,20 +466,19 @@ dump_type (tree t, int flags) case TYPE_PACK_EXPANSION: dump_type (PACK_EXPANSION_PATTERN (t), flags); - pp_cxx_identifier (cxx_pp, "..."); + pp_cxx_ws_string (cxx_pp, "..."); break; case TYPE_ARGUMENT_PACK: - { - tree args = ARGUMENT_PACK_ARGS (t); - int i; - for (i = 0; i < TREE_VEC_LENGTH (args); ++i) - { - if (i) - pp_separate_with_comma (cxx_pp); - dump_type (TREE_VEC_ELT (args, i), flags); - } - } + dump_template_argument (t, flags); + break; + + case DECLTYPE_TYPE: + pp_cxx_ws_string (cxx_pp, "decltype"); + pp_cxx_whitespace (cxx_pp); + pp_cxx_left_paren (cxx_pp); + dump_expr (DECLTYPE_TYPE_EXPR (t), flags & ~TFF_EXPR_IN_PARENS); + pp_cxx_right_paren (cxx_pp); break; default: @@ -413,7 +486,7 @@ dump_type (tree t, int flags) /* Fall through to error. */ case ERROR_MARK: - pp_identifier (cxx_pp, ""); + pp_string (cxx_pp, M_("")); break; } } @@ -439,8 +512,13 @@ dump_typename (tree t, int flags) const char * class_key_or_enum_as_string (tree t) { - if (TREE_CODE (t) == ENUMERAL_TYPE) - return "enum"; + if (TREE_CODE (t) == ENUMERAL_TYPE) + { + if (SCOPED_ENUM_P (t)) + return "enum class"; + else + return "enum"; + } else if (TREE_CODE (t) == UNION_TYPE) return "union"; else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t)) @@ -463,16 +541,24 @@ dump_aggr_type (tree t, int flags) pp_cxx_cv_qualifier_seq (cxx_pp, t); if (flags & TFF_CLASS_KEY_OR_ENUM) - pp_cxx_identifier (cxx_pp, variety); - - if (flags & TFF_CHASE_TYPEDEF) - t = TYPE_MAIN_VARIANT (t); + pp_cxx_ws_string (cxx_pp, variety); name = TYPE_NAME (t); if (name) { typdef = !DECL_ARTIFICIAL (name); + + if (typdef + && ((flags & TFF_CHASE_TYPEDEF) + || (!flag_pretty_templates && DECL_LANG_SPECIFIC (name) + && DECL_TEMPLATE_INFO (name)))) + { + t = TYPE_MAIN_VARIANT (t); + name = TYPE_NAME (t); + typdef = 0; + } + tmplate = !typdef && TREE_CODE (t) != ENUMERAL_TYPE && TYPE_LANG_SPECIFIC (t) && CLASSTYPE_TEMPLATE_INFO (t) && (TREE_CODE (CLASSTYPE_TI_TEMPLATE (t)) != TEMPLATE_DECL @@ -497,9 +583,9 @@ dump_aggr_type (tree t, int flags) if (name == 0 || ANON_AGGRNAME_P (name)) { if (flags & TFF_CLASS_KEY_OR_ENUM) - pp_identifier (cxx_pp, ""); + pp_string (cxx_pp, M_("")); else - pp_printf (pp_base (cxx_pp), "", variety); + pp_printf (pp_base (cxx_pp), M_(""), variety); } else pp_cxx_tree_identifier (cxx_pp, name); @@ -537,7 +623,8 @@ dump_type_prefix (tree t, int flags) tree sub = TREE_TYPE (t); dump_type_prefix (sub, flags); - if (TREE_CODE (sub) == ARRAY_TYPE) + if (TREE_CODE (sub) == ARRAY_TYPE + || TREE_CODE (sub) == FUNCTION_TYPE) { pp_cxx_whitespace (cxx_pp); pp_cxx_left_paren (cxx_pp); @@ -572,12 +659,10 @@ dump_type_prefix (tree t, int flags) pp_base (cxx_pp)->padding = pp_before; break; - /* Can only be reached through function pointer -- this would not be - correct if FUNCTION_DECLs used it. */ + /* This can be reached without a pointer when dealing with + templates, e.g. std::is_function. */ case FUNCTION_TYPE: dump_type_prefix (TREE_TYPE (t), flags); - pp_maybe_space (cxx_pp); - pp_cxx_left_paren (cxx_pp); break; case METHOD_TYPE: @@ -611,6 +696,9 @@ dump_type_prefix (tree t, int flags) case COMPLEX_TYPE: case VECTOR_TYPE: case TYPEOF_TYPE: + case DECLTYPE_TYPE: + case TYPE_PACK_EXPANSION: + case FIXED_POINT_TYPE: dump_type (t, flags); pp_base (cxx_pp)->padding = pp_before; break; @@ -619,7 +707,7 @@ dump_type_prefix (tree t, int flags) pp_unsupported_tree (cxx_pp, t); /* fall through. */ case ERROR_MARK: - pp_identifier (cxx_pp, ""); + pp_string (cxx_pp, M_("")); break; } } @@ -638,17 +726,19 @@ dump_type_suffix (tree t, int flags) case POINTER_TYPE: case REFERENCE_TYPE: case OFFSET_TYPE: - if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) + if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE + || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) pp_cxx_right_paren (cxx_pp); dump_type_suffix (TREE_TYPE (t), flags); break; - /* Can only be reached through function pointer. */ case FUNCTION_TYPE: case METHOD_TYPE: { tree arg; - pp_cxx_right_paren (cxx_pp); + if (TREE_CODE (t) == METHOD_TYPE) + /* Can only be reached through a pointer. */ + pp_cxx_right_paren (cxx_pp); arg = TYPE_ARG_TYPES (t); if (TREE_CODE (t) == METHOD_TYPE) arg = TREE_CHAIN (arg); @@ -661,7 +751,7 @@ dump_type_suffix (tree t, int flags) pp_cxx_cv_qualifier_seq (cxx_pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t)))); else - pp_cxx_cv_qualifier_seq(cxx_pp, t); + pp_cxx_cv_qualifier_seq (cxx_pp, t); dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags); dump_type_suffix (TREE_TYPE (t), flags); break; @@ -707,6 +797,9 @@ dump_type_suffix (tree t, int flags) case COMPLEX_TYPE: case VECTOR_TYPE: case TYPEOF_TYPE: + case DECLTYPE_TYPE: + case TYPE_PACK_EXPANSION: + case FIXED_POINT_TYPE: break; default: @@ -724,13 +817,13 @@ dump_global_iord (tree t) const char *p = NULL; if (DECL_GLOBAL_CTOR_P (t)) - p = "initializers"; + p = M_("(static initializers for %s)"); else if (DECL_GLOBAL_DTOR_P (t)) - p = "destructors"; + p = M_("(static destructors for %s)"); else gcc_unreachable (); - pp_printf (pp_base (cxx_pp), "(static %s for %s)", p, input_filename); + pp_printf (pp_base (cxx_pp), p, input_filename); } static void @@ -746,10 +839,14 @@ dump_simple_decl (tree t, tree type, int flags) || TREE_CODE (DECL_INITIAL (t)) != TEMPLATE_PARM_INDEX)) dump_scope (CP_DECL_CONTEXT (t), flags); flags &= ~TFF_UNQUALIFIED_NAME; + if ((flags & TFF_DECL_SPECIFIERS) + && DECL_TEMPLATE_PARM_P (t) + && TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (t))) + pp_string (cxx_pp, "..."); if (DECL_NAME (t)) dump_decl (DECL_NAME (t), flags); else - pp_identifier (cxx_pp, ""); + pp_string (cxx_pp, M_("")); if (flags & TFF_DECL_SPECIFIERS) dump_type_suffix (type, flags); } @@ -766,18 +863,24 @@ dump_decl (tree t, int flags) { case TYPE_DECL: /* Don't say 'typedef class A' */ - if (DECL_ARTIFICIAL (t)) + if (DECL_ARTIFICIAL (t) && !DECL_SELF_REFERENCE_P (t)) { if ((flags & TFF_DECL_SPECIFIERS) && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM) - /* Say `class T' not just `T'. */ - pp_cxx_identifier (cxx_pp, "class"); + { + /* Say `class T' not just `T'. */ + pp_cxx_ws_string (cxx_pp, "class"); + + /* Emit the `...' for a parameter pack. */ + if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t))) + pp_cxx_ws_string (cxx_pp, "..."); + } dump_type (TREE_TYPE (t), flags); break; } if (flags & TFF_DECL_SPECIFIERS) - pp_cxx_identifier (cxx_pp, "typedef"); + pp_cxx_ws_string (cxx_pp, "typedef"); dump_simple_decl (t, DECL_ORIGINAL_TYPE (t) ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), flags); @@ -786,7 +889,7 @@ dump_decl (tree t, int flags) case VAR_DECL: if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t))) { - pp_string (cxx_pp, "vtable for "); + pp_string (cxx_pp, M_("vtable for ")); gcc_assert (TYPE_P (DECL_CONTEXT (t))); dump_type (DECL_CONTEXT (t), flags); break; @@ -798,7 +901,7 @@ dump_decl (tree t, int flags) break; case RESULT_DECL: - pp_string (cxx_pp, " "); + pp_string (cxx_pp, M_(" ")); dump_simple_decl (t, TREE_TYPE (t), flags); break; @@ -811,7 +914,7 @@ dump_decl (tree t, int flags) dump_scope (CP_DECL_CONTEXT (t), flags); flags &= ~TFF_UNQUALIFIED_NAME; if (DECL_NAME (t) == NULL_TREE) - pp_identifier (cxx_pp, ""); + pp_string (cxx_pp, M_("")); else pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t)); } @@ -851,7 +954,7 @@ dump_decl (tree t, int flags) case IDENTIFIER_NODE: if (IDENTIFIER_TYPENAME_P (t)) { - pp_cxx_identifier (cxx_pp, "operator"); + pp_cxx_ws_string (cxx_pp, "operator"); /* Not exactly IDENTIFIER_TYPE_VALUE. */ dump_type (TREE_TYPE (t), flags); break; @@ -885,7 +988,7 @@ dump_decl (tree t, int flags) case FUNCTION_DECL: if (! DECL_LANG_SPECIFIC (t)) - pp_identifier (cxx_pp, ""); + pp_string (cxx_pp, M_("")); else if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t)) dump_global_iord (t); else @@ -905,7 +1008,7 @@ dump_decl (tree t, int flags) dump_decl (name, flags); pp_cxx_begin_template_argument_list (cxx_pp); if (TREE_OPERAND (t, 1)) - dump_template_argument_list (TREE_OPERAND (t, 1), flags); + dump_template_argument_list (TREE_OPERAND (t, 1), NULL_TREE, flags); pp_cxx_end_template_argument_list (cxx_pp); } break; @@ -924,11 +1027,11 @@ dump_decl (tree t, int flags) else if (DECL_INITIAL (t)) dump_expr (DECL_INITIAL (t), flags | TFF_EXPR_IN_PARENS); else - pp_identifier (cxx_pp, ""); + pp_string (cxx_pp, M_("")); break; case USING_DECL: - pp_cxx_identifier (cxx_pp, "using"); + pp_cxx_ws_string (cxx_pp, "using"); dump_type (USING_DECL_SCOPE (t), flags); pp_cxx_colon_colon (cxx_pp); dump_decl (DECL_NAME (t), flags); @@ -953,12 +1056,18 @@ dump_decl (tree t, int flags) pp_type_id (cxx_pp, t); break; + case UNBOUND_CLASS_TEMPLATE: + case TYPE_PACK_EXPANSION: + case TREE_BINFO: + dump_type (t, flags); + break; + default: pp_unsupported_tree (cxx_pp, t); /* Fall through to error. */ case ERROR_MARK: - pp_identifier (cxx_pp, ""); + pp_string (cxx_pp, M_("")); break; } } @@ -982,7 +1091,7 @@ dump_template_decl (tree t, int flags) tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms); int len = TREE_VEC_LENGTH (inner_parms); - pp_cxx_identifier (cxx_pp, "template"); + pp_cxx_ws_string (cxx_pp, "template"); pp_cxx_begin_template_argument_list (cxx_pp); /* If we've shown the template prefix, we'd better show the @@ -1001,15 +1110,23 @@ dump_template_decl (tree t, int flags) nreverse(orig_parms); if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)) - /* Say `template class TT' not just `template TT'. */ - pp_cxx_identifier (cxx_pp, "class"); + { + /* Say `template class TT' not just `template TT'. */ + pp_cxx_ws_string (cxx_pp, "class"); + + /* If this is a parameter pack, print the ellipsis. */ + if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t))) + pp_cxx_ws_string (cxx_pp, "..."); + } } - if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL) + if (DECL_TEMPLATE_RESULT (t) + && TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL) dump_type (TREE_TYPE (t), ((flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME | (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0))); - else if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL) + else if (DECL_TEMPLATE_RESULT (t) + && TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL) dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME); else { @@ -1030,6 +1147,52 @@ dump_template_decl (tree t, int flags) } } +/* find_typenames looks through the type of the function template T + and returns a VEC containing any typedefs or TYPENAME_TYPEs it finds. */ + +struct find_typenames_t +{ + struct pointer_set_t *p_set; + VEC (tree,gc) *typenames; +}; + +static tree +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); + + /* Search into class template arguments, which cp_walk_subtrees + doesn't do. */ + 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; +} + +static VEC(tree,gc) * +find_typenames (tree t) +{ + struct find_typenames_t ft; + ft.p_set = pointer_set_create (); + ft.typenames = NULL; + cp_walk_tree (&TREE_TYPE (DECL_TEMPLATE_RESULT (t)), + find_typenames_r, &ft, ft.p_set); + pointer_set_destroy (ft.p_set); + return ft.typenames; +} + /* Pretty print a function decl. There are several ways we want to print a function declaration. The TFF_ bits in FLAGS tells us how to behave. As error can only apply the '#' flag once to give 0 and 1 for V, there @@ -1045,13 +1208,20 @@ dump_function_decl (tree t, int flags) tree template_parms = NULL_TREE; int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS; int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME); + tree exceptions; + VEC(tree,gc) *typenames = NULL; flags &= ~TFF_UNQUALIFIED_NAME; if (TREE_CODE (t) == TEMPLATE_DECL) t = DECL_TEMPLATE_RESULT (t); + /* Save the exceptions, in case t is a specialization and we are + emitting an error about incompatible specifications. */ + exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (t)); + /* Pretty print template instantiations only. */ - if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t)) + if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t) + && flag_pretty_templates) { tree tmpl; @@ -1061,6 +1231,7 @@ dump_function_decl (tree t, int flags) { template_parms = DECL_TEMPLATE_PARMS (tmpl); t = tmpl; + typenames = find_typenames (t); } } @@ -1076,9 +1247,9 @@ dump_function_decl (tree t, int flags) if (!(flags & TFF_DECL_SPECIFIERS)) /* OK */; else if (DECL_STATIC_FUNCTION_P (t)) - pp_cxx_identifier (cxx_pp, "static"); + pp_cxx_ws_string (cxx_pp, "static"); else if (DECL_VIRTUAL_P (t)) - pp_cxx_identifier (cxx_pp, "virtual"); + pp_cxx_ws_string (cxx_pp, "virtual"); /* Print the return type? */ if (show_return) @@ -1114,7 +1285,7 @@ dump_function_decl (tree t, int flags) if (flags & TFF_EXCEPTION_SPECIFICATION) { pp_base (cxx_pp)->padding = pp_before; - dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags); + dump_exception_spec (exceptions, flags); } if (show_return) @@ -1126,9 +1297,9 @@ dump_function_decl (tree t, int flags) { pp_cxx_whitespace (cxx_pp); pp_cxx_left_bracket (cxx_pp); - pp_cxx_identifier (cxx_pp, "with"); + pp_cxx_ws_string (cxx_pp, M_("with")); pp_cxx_whitespace (cxx_pp); - dump_template_bindings (template_parms, template_args); + dump_template_bindings (template_parms, template_args, typenames); pp_cxx_right_bracket (cxx_pp); } } @@ -1151,25 +1322,11 @@ dump_parameters (tree parmtypes, int flags) first = 0; if (!parmtypes) { - pp_cxx_identifier (cxx_pp, "..."); + pp_cxx_ws_string (cxx_pp, "..."); break; } - if (ARGUMENT_PACK_P (TREE_VALUE (parmtypes))) - { - tree types = ARGUMENT_PACK_ARGS (TREE_VALUE (parmtypes)); - int i, len = TREE_VEC_LENGTH (types); - first = 1; - for (i = 0; i < len; ++i) - { - if (!first) - pp_separate_with_comma (cxx_pp); - first = 0; - - dump_type (TREE_VEC_ELT (types, i), flags); - } - } - else - dump_type (TREE_VALUE (parmtypes), flags); + + dump_type (TREE_VALUE (parmtypes), flags); if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes)) { @@ -1190,7 +1347,7 @@ dump_exception_spec (tree t, int flags) { if (t) { - pp_cxx_identifier (cxx_pp, "throw"); + pp_cxx_ws_string (cxx_pp, "throw"); pp_cxx_whitespace (cxx_pp); pp_cxx_left_paren (cxx_pp); if (TREE_VALUE (t) != NULL_TREE) @@ -1246,10 +1403,10 @@ dump_function_name (tree t, int flags) declarations, both will have the same name, yet the types will be different, hence the TREE_TYPE field of the first name will be clobbered by the second. */ - pp_cxx_identifier (cxx_pp, "operator"); + pp_cxx_ws_string (cxx_pp, "operator"); dump_type (TREE_TYPE (TREE_TYPE (t)), flags); } - else if (IDENTIFIER_OPNAME_P (name)) + else if (name && IDENTIFIER_OPNAME_P (name)) pp_cxx_tree_identifier (cxx_pp, name); else dump_decl (name, flags); @@ -1278,16 +1435,18 @@ dump_template_parms (tree info, int primary, int flags) pp_cxx_begin_template_argument_list (cxx_pp); /* Be careful only to print things when we have them, so as not - to crash producing error messages. */ + to crash producing error messages. */ if (args && !primary) { int len, ix; + /* We don't know the parms for a friend template specialization. */ + tree params = (TREE_CODE (TI_TEMPLATE (info)) == TEMPLATE_DECL + ? DECL_INNERMOST_TEMPLATE_PARMS (TI_TEMPLATE (info)) + : NULL_TREE); - if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) - args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1); - - len = TREE_VEC_LENGTH (args); + len = count_non_default_template_args (args, params); + args = INNERMOST_TEMPLATE_ARGS (args); for (ix = 0; ix != len; ix++) { tree arg = TREE_VEC_ELT (args, ix); @@ -1301,7 +1460,7 @@ dump_template_parms (tree info, int primary, int flags) pp_separate_with_comma (cxx_pp); if (!arg) - pp_identifier (cxx_pp, "