X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcp%2Ferror.c;h=de45efe37d48e8bbcef2effdec5d8326eabd6f82;hp=1854fd6888cf7536ee3580c8554daacf75c3737d;hb=e8b065281040f9e3f6bed9b7f633139ad930f9f5;hpb=f0f59ea4c8f02d157dcd38ed61229245b21e6360 diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 1854fd6888c..de45efe37d4 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1,7 +1,7 @@ /* 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. + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, + 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify @@ -24,12 +24,15 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "cp-tree.h" -#include "real.h" #include "toplev.h" #include "flags.h" #include "diagnostic.h" +#include "tree-diagnostic.h" #include "langhooks-def.h" +#include "intl.h" #include "cxx-pretty-print.h" +#include "tree-pretty-print.h" +#include "pointer-set.h" #define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',') @@ -39,6 +42,10 @@ along with GCC; see the file COPYING3. If not see 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); @@ -74,11 +81,12 @@ 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_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 get_non_default_template_args_count (tree, int); static const char *function_category (tree); +static void maybe_print_constexpr_context (diagnostic_context *); static void maybe_print_instantiation_context (diagnostic_context *); static void print_instantiation_full_context (diagnostic_context *); static void print_instantiation_partial_context (diagnostic_context *, @@ -108,7 +116,7 @@ init_error (void) static void dump_scope (tree scope, int flags) { - int f = ~TFF_RETURN_TYPE & (flags & (TFF_SCOPE | TFF_CHASE_TYPEDEF)); + int f = flags & (TFF_SCOPE | TFF_CHASE_TYPEDEF); if (scope == NULL_TREE) return; @@ -143,7 +151,32 @@ dump_template_argument (tree arg, int 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 +get_non_default_template_args_count (tree args, int flags) +{ + int n = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS (args)); + + if (/* We use this flag when generating debug information. We don't + want to expand templates at this point, for this may generate + new decls, which gets decl counts out of sync, which may in + turn cause codegen differences between compilations with and + without -g. */ + (flags & TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS) != 0 + || !flag_pretty_templates) + return n; + + return GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (INNERMOST_TEMPLATE_ARGS (args)); } /* Dump a template-argument-list ARGS (always a TREE_VEC) under control @@ -152,11 +185,11 @@ dump_template_argument (tree arg, int flags) static void dump_template_argument_list (tree args, int flags) { - int n = TREE_VEC_LENGTH (args); + int n = get_non_default_template_args_count (args, flags); 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 +224,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 +255,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 +267,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); @@ -252,9 +288,15 @@ dump_template_bindings (tree parms, tree args) pp_equal (cxx_pp); pp_cxx_whitespace (cxx_pp); if (arg) - dump_template_argument (arg, TFF_PLAIN_IDENTIFIER); + { + if (ARGUMENT_PACK_P (arg)) + pp_cxx_left_brace (cxx_pp); + dump_template_argument (arg, TFF_PLAIN_IDENTIFIER); + if (ARGUMENT_PACK_P (arg)) + pp_cxx_right_brace (cxx_pp); + } else - pp_identifier (cxx_pp, ""); + pp_string (cxx_pp, M_("")); ++arg_idx; need_comma = 1; @@ -262,6 +304,21 @@ dump_template_bindings (tree parms, tree args) parms = TREE_CHAIN (parms); } + + FOR_EACH_VEC_ELT (tree, typenames, i, t) + { + 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 @@ -273,13 +330,40 @@ dump_type (tree t, int flags) if (t == NULL_TREE) return; + /* Don't print e.g. "struct mytypedef". */ + if (TYPE_P (t) && typedef_variant_p (t)) + { + tree decl = TYPE_NAME (t); + if ((flags & TFF_CHASE_TYPEDEF) + || DECL_SELF_REFERENCE_P (decl) + || (!flag_pretty_templates + && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))) + t = strip_typedefs (t); + else if (same_type_p (t, TREE_TYPE (decl))) + t = decl; + else + { + pp_cxx_cv_qualifier_seq (cxx_pp, t); + pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t)); + return; + } + } + if (TYPE_PTRMEMFUNC_P (t)) goto offset_type; switch (TREE_CODE (t)) { - case UNKNOWN_TYPE: - pp_identifier (cxx_pp, ""); + case LANG_TYPE: + if (t == init_list_type_node) + pp_string (cxx_pp, M_("")); + else if (t == unknown_type_node) + pp_string (cxx_pp, M_("")); + else + { + pp_cxx_cv_qualifier_seq (cxx_pp, t); + pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t)); + } break; case TREE_LIST: @@ -321,6 +405,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; @@ -367,8 +452,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"); @@ -376,14 +467,17 @@ dump_type (tree t, int flags) break; case UNBOUND_CLASS_TEMPLATE: - dump_type (TYPE_CONTEXT (t), flags); - pp_cxx_colon_colon (cxx_pp); - pp_cxx_identifier (cxx_pp, "template"); + if (! (flags & TFF_UNQUALIFIED_NAME)) + { + dump_type (TYPE_CONTEXT (t), flags); + pp_cxx_colon_colon (cxx_pp); + } + 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,36 +486,31 @@ 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_identifier (cxx_pp, "decltype"); + 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; + case NULLPTR_TYPE: + pp_string (cxx_pp, "std::nullptr_t"); + 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; } } @@ -447,8 +536,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)) @@ -471,16 +565,25 @@ 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)))) + || DECL_SELF_REFERENCE_P (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 @@ -505,9 +608,18 @@ 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 if (LAMBDANAME_P (name)) + { + /* A lambda's "type" is essentially its signature. */ + pp_string (cxx_pp, M_("'); } else pp_cxx_tree_identifier (cxx_pp, name); @@ -545,7 +657,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); @@ -580,12 +693,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: @@ -613,13 +724,16 @@ dump_type_prefix (tree t, int flags) case TYPE_DECL: case TREE_VEC: case UNION_TYPE: - case UNKNOWN_TYPE: + case LANG_TYPE: case VOID_TYPE: case TYPENAME_TYPE: case COMPLEX_TYPE: case VECTOR_TYPE: case TYPEOF_TYPE: case DECLTYPE_TYPE: + case TYPE_PACK_EXPANSION: + case FIXED_POINT_TYPE: + case NULLPTR_TYPE: dump_type (t, flags); pp_base (cxx_pp)->padding = pp_before; break; @@ -628,7 +742,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; } } @@ -647,17 +761,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); @@ -670,7 +786,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; @@ -689,7 +805,8 @@ dump_type_suffix (tree t, int flags) dump_expr (TREE_OPERAND (max, 0), flags & ~TFF_EXPR_IN_PARENS); else - dump_expr (fold_build2 (PLUS_EXPR, dtype, max, + dump_expr (fold_build2_loc (input_location, + PLUS_EXPR, dtype, max, build_int_cst (dtype, 1)), flags & ~TFF_EXPR_IN_PARENS); } @@ -710,13 +827,16 @@ dump_type_suffix (tree t, int flags) case TYPE_DECL: case TREE_VEC: case UNION_TYPE: - case UNKNOWN_TYPE: + case LANG_TYPE: case VOID_TYPE: case TYPENAME_TYPE: case COMPLEX_TYPE: case VECTOR_TYPE: case TYPEOF_TYPE: case DECLTYPE_TYPE: + case TYPE_PACK_EXPANSION: + case FIXED_POINT_TYPE: + case NULLPTR_TYPE: break; default: @@ -734,13 +854,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 @@ -748,18 +868,26 @@ dump_simple_decl (tree t, tree type, int flags) { if (flags & TFF_DECL_SPECIFIERS) { + if (TREE_CODE (t) == VAR_DECL + && DECL_DECLARED_CONSTEXPR_P (t)) + pp_cxx_ws_string (cxx_pp, "constexpr"); dump_type_prefix (type, flags & ~TFF_UNQUALIFIED_NAME); pp_maybe_space (cxx_pp); } if (! (flags & TFF_UNQUALIFIED_NAME) + && TREE_CODE (t) != PARM_DECL && (!DECL_INITIAL (t) || 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); } @@ -772,22 +900,41 @@ dump_decl (tree t, int flags) if (t == NULL_TREE) return; + /* If doing Objective-C++, give Objective-C a chance to demangle + Objective-C method names. */ + if (c_dialect_objc ()) + { + const char *demangled = objc_maybe_printable_name (t, flags); + if (demangled) + { + pp_string (cxx_pp, demangled); + return; + } + } + switch (TREE_CODE (t)) { 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"); + if ((flags & TFF_DECL_SPECIFIERS) + && !DECL_SELF_REFERENCE_P (t)) + pp_cxx_ws_string (cxx_pp, "typedef"); dump_simple_decl (t, DECL_ORIGINAL_TYPE (t) ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), flags); @@ -796,7 +943,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; @@ -808,7 +955,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; @@ -821,14 +968,16 @@ 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_cxx_ws_string (cxx_pp, M_("{anonymous}")); else pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t)); } break; case SCOPE_REF: - pp_expression (cxx_pp, t); + dump_type (TREE_OPERAND (t, 0), flags); + pp_string (cxx_pp, "::"); + dump_decl (TREE_OPERAND (t, 1), flags|TFF_UNQUALIFIED_NAME); break; case ARRAY_REF: @@ -861,7 +1010,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; @@ -895,7 +1044,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 @@ -934,11 +1083,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); @@ -964,6 +1113,8 @@ dump_decl (tree t, int flags) break; case UNBOUND_CLASS_TEMPLATE: + case TYPE_PACK_EXPANSION: + case TREE_BINFO: dump_type (t, flags); break; @@ -972,7 +1123,7 @@ dump_decl (tree t, int flags) /* Fall through to error. */ case ERROR_MARK: - pp_identifier (cxx_pp, ""); + pp_string (cxx_pp, M_("")); break; } } @@ -996,7 +1147,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 @@ -1015,15 +1166,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 { @@ -1044,6 +1203,54 @@ 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, decltypes 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 + || TREE_CODE (*tp) == DECLTYPE_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 @@ -1059,13 +1266,28 @@ 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; + + if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t)) + { + /* A lambda's signature is essentially its "type", so defer. */ + gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t))); + dump_type (DECL_CONTEXT (t), flags); + return; + } 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; @@ -1075,6 +1297,7 @@ dump_function_decl (tree t, int flags) { template_parms = DECL_TEMPLATE_PARMS (tmpl); t = tmpl; + typenames = find_typenames (t); } } @@ -1087,12 +1310,16 @@ dump_function_decl (tree t, int flags) else if (TREE_CODE (fntype) == METHOD_TYPE) cname = TREE_TYPE (TREE_VALUE (parmtypes)); - if (!(flags & TFF_DECL_SPECIFIERS)) - /* OK */; - else if (DECL_STATIC_FUNCTION_P (t)) - pp_cxx_identifier (cxx_pp, "static"); - else if (DECL_VIRTUAL_P (t)) - pp_cxx_identifier (cxx_pp, "virtual"); + if (flags & TFF_DECL_SPECIFIERS) + { + if (DECL_STATIC_FUNCTION_P (t)) + pp_cxx_ws_string (cxx_pp, "static"); + else if (DECL_VIRTUAL_P (t)) + pp_cxx_ws_string (cxx_pp, "virtual"); + + if (DECL_DECLARED_CONSTEXPR_P (STRIP_TEMPLATE (t))) + pp_cxx_ws_string (cxx_pp, "constexpr"); + } /* Print the return type? */ if (show_return) @@ -1128,7 +1355,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) @@ -1140,9 +1367,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); } } @@ -1155,6 +1382,7 @@ static void dump_parameters (tree parmtypes, int flags) { int first = 1; + flags &= ~TFF_SCOPE; pp_cxx_left_paren (cxx_pp); for (first = 1; parmtypes != void_list_node; @@ -1165,25 +1393,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)) { @@ -1202,9 +1416,17 @@ dump_parameters (tree parmtypes, int flags) static void dump_exception_spec (tree t, int flags) { - if (t) + if (t && TREE_PURPOSE (t)) + { + pp_cxx_ws_string (cxx_pp, "noexcept"); + pp_cxx_whitespace (cxx_pp); + pp_cxx_left_paren (cxx_pp); + dump_expr (TREE_PURPOSE (t), flags); + pp_cxx_right_paren (cxx_pp); + } + else 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) @@ -1245,7 +1467,12 @@ dump_function_name (tree t, int flags) /* Don't let the user see __comp_ctor et al. */ if (DECL_CONSTRUCTOR_P (t) || DECL_DESTRUCTOR_P (t)) - name = constructor_name (DECL_CONTEXT (t)); + { + if (LAMBDA_TYPE_P (DECL_CONTEXT (t))) + name = get_identifier (""); + else + name = constructor_name (DECL_CONTEXT (t)); + } if (DECL_DESTRUCTOR_P (t)) { @@ -1260,10 +1487,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); @@ -1292,16 +1519,13 @@ 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; + len = get_non_default_template_args_count (args, flags); - if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) - args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1); - - len = TREE_VEC_LENGTH (args); - + args = INNERMOST_TEMPLATE_ARGS (args); for (ix = 0; ix != len; ix++) { tree arg = TREE_VEC_ELT (args, ix); @@ -1315,7 +1539,7 @@ dump_template_parms (tree info, int primary, int flags) pp_separate_with_comma (cxx_pp); if (!arg) - pp_identifier (cxx_pp, "