From 3c56f697e112c79fb5457538fdc373e348beca24 Mon Sep 17 00:00:00 2001 From: Andrew Hsieh Date: Thu, 8 Nov 2012 09:43:39 -0800 Subject: Initial checkin of unmodified gcc-5666.3.tar.gz This is the source to build gcc-4.2 for MacOSX gcc version 4.2.1 (Apple Inc. build 5666) (dot 3) http://opensource.apple.com/tarballs/gcc/gcc-5666.3.tar.gz Change-Id: I69540223f018e9d07f861fca04bd3833fc138f8b --- gcc-4.2.1-5666.3/gcc/cp/error.c | 2415 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 2415 insertions(+) create mode 100644 gcc-4.2.1-5666.3/gcc/cp/error.c (limited to 'gcc-4.2.1-5666.3/gcc/cp/error.c') diff --git a/gcc-4.2.1-5666.3/gcc/cp/error.c b/gcc-4.2.1-5666.3/gcc/cp/error.c new file mode 100644 index 000000000..3c461d06b --- /dev/null +++ b/gcc-4.2.1-5666.3/gcc/cp/error.c @@ -0,0 +1,2415 @@ +/* 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 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) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +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. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "cp-tree.h" +#include "real.h" +#include "toplev.h" +#include "flags.h" +#include "diagnostic.h" +#include "langhooks-def.h" +#include "cxx-pretty-print.h" + +#define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',') + +/* The global buffer where we dump everything. It is there only for + transitional purpose. It is expected, in the near future, to be + completely removed. */ +static cxx_pretty_printer scratch_pretty_printer; +#define cxx_pp (&scratch_pretty_printer) + +# define NEXT_CODE(T) (TREE_CODE (TREE_TYPE (T))) + +static const char *args_to_string (tree, int); +static const char *assop_to_string (enum tree_code); +static const char *code_to_string (enum tree_code); +static const char *cv_to_string (tree, int); +static const char *decl_to_string (tree, int); +static const char *expr_to_string (tree); +static const char *fndecl_to_string (tree, int); +static const char *op_to_string (enum tree_code); +static const char *parm_to_string (int); +static const char *type_to_string (tree, int); + +static void dump_type (tree, int); +static void dump_typename (tree, int); +static void dump_simple_decl (tree, tree, int); +static void dump_decl (tree, int); +static void dump_template_decl (tree, int); +static void dump_function_decl (tree, int); +static void dump_expr (tree, int); +static void dump_unary_op (const char *, tree, int); +static void dump_binary_op (const char *, tree, int); +static void dump_aggr_type (tree, int); +static void dump_type_prefix (tree, int); +static void dump_type_suffix (tree, int); +static void dump_function_name (tree, int); +static void dump_expr_list (tree, int); +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_parameter (tree, int); +static void dump_template_bindings (tree, tree); +static void dump_scope (tree, int); +static void dump_template_parms (tree, int, int); + +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); +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 *); + +static bool cp_printer (pretty_printer *, text_info *, const char *, + int, bool, bool, bool); +static location_t location_of (tree); + +void +init_error (void) +{ + diagnostic_starter (global_dc) = cp_diagnostic_starter; + diagnostic_finalizer (global_dc) = cp_diagnostic_finalizer; + diagnostic_format_decoder (global_dc) = cp_printer; + + pp_construct (pp_base (cxx_pp), NULL, 0); + pp_cxx_pretty_printer_init (cxx_pp); +} + +/* Dump a scope, if deemed necessary. */ + +static void +dump_scope (tree scope, int flags) +{ + int f = ~TFF_RETURN_TYPE & (flags & (TFF_SCOPE | TFF_CHASE_TYPEDEF)); + + if (scope == NULL_TREE) + return; + + if (TREE_CODE (scope) == NAMESPACE_DECL) + { + if (scope != global_namespace) + { + dump_decl (scope, f); + pp_cxx_colon_colon (cxx_pp); + } + } + else if (AGGREGATE_TYPE_P (scope)) + { + dump_type (scope, f); + pp_cxx_colon_colon (cxx_pp); + } + else if ((flags & TFF_SCOPE) && TREE_CODE (scope) == FUNCTION_DECL) + { + dump_function_decl (scope, f); + pp_cxx_colon_colon (cxx_pp); + } +} + +/* Dump the template ARGument under control of FLAGS. */ + +static void +dump_template_argument (tree arg, int flags) +{ + 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); +} + +/* Dump a template-argument-list ARGS (always a TREE_VEC) under control + of FLAGS. */ + +static void +dump_template_argument_list (tree args, int flags) +{ + int n = TREE_VEC_LENGTH (args); + int need_comma = 0; + int i; + + for (i = 0; i< n; ++i) + { + if (need_comma) + pp_separate_with_comma (cxx_pp); + dump_template_argument (TREE_VEC_ELT (args, i), flags); + need_comma = 1; + } +} + +/* Dump a template parameter PARM (a TREE_LIST) under control of FLAGS. */ + +static void +dump_template_parameter (tree parm, int flags) +{ + tree p; + tree a; + + if (parm == error_mark_node) + return; + + p = TREE_VALUE (parm); + a = TREE_PURPOSE (parm); + + if (TREE_CODE (p) == TYPE_DECL) + { + if (flags & TFF_DECL_SPECIFIERS) + { + pp_cxx_identifier (cxx_pp, "class"); + if (DECL_NAME (p)) + pp_cxx_tree_identifier (cxx_pp, DECL_NAME (p)); + } + else if (DECL_NAME (p)) + pp_cxx_tree_identifier (cxx_pp, DECL_NAME (p)); + else + pp_cxx_canonical_template_parameter (cxx_pp, TREE_TYPE (p)); + } + else + dump_decl (p, flags | TFF_DECL_SPECIFIERS); + + if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && a != NULL_TREE) + { + pp_cxx_whitespace (cxx_pp); + pp_equal (cxx_pp); + pp_cxx_whitespace (cxx_pp); + if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL) + dump_type (a, flags & ~TFF_CHASE_TYPEDEF); + else + dump_expr (a, flags | TFF_EXPR_IN_PARENS); + } +} + +/* Dump, under control of FLAGS, a template-parameter-list binding. + PARMS is a TREE_LIST of TREE_VEC of TREE_LIST and ARGS is a + TREE_VEC. */ + +static void +dump_template_bindings (tree parms, tree args) +{ + int need_comma = 0; + + while (parms) + { + tree p = TREE_VALUE (parms); + int lvl = TMPL_PARMS_DEPTH (parms); + int arg_idx = 0; + int i; + + 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 (need_comma) + pp_separate_with_comma (cxx_pp); + dump_template_parameter (TREE_VEC_ELT (p, i), TFF_PLAIN_IDENTIFIER); + pp_cxx_whitespace (cxx_pp); + pp_equal (cxx_pp); + pp_cxx_whitespace (cxx_pp); + if (arg) + dump_template_argument (arg, TFF_PLAIN_IDENTIFIER); + else + pp_identifier (cxx_pp, ""); + + ++arg_idx; + need_comma = 1; + } + + parms = TREE_CHAIN (parms); + } +} + +/* Dump a human-readable equivalent of TYPE. FLAGS controls the + format. */ + +static void +dump_type (tree t, int flags) +{ + if (t == NULL_TREE) + return; + + if (TYPE_PTRMEMFUNC_P (t)) + goto offset_type; + + switch (TREE_CODE (t)) + { + case UNKNOWN_TYPE: + pp_identifier (cxx_pp, ""); + break; + + case TREE_LIST: + /* A list of function parms. */ + dump_parameters (t, flags); + break; + + case IDENTIFIER_NODE: + pp_cxx_tree_identifier (cxx_pp, t); + break; + + case TREE_BINFO: + dump_type (BINFO_TYPE (t), flags); + break; + + case RECORD_TYPE: + case UNION_TYPE: + case ENUMERAL_TYPE: + dump_aggr_type (t, flags); + break; + + case TYPE_DECL: + if (flags & TFF_CHASE_TYPEDEF) + { + dump_type (DECL_ORIGINAL_TYPE (t) + ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), flags); + break; + } + /* Else fall through. */ + + case TEMPLATE_DECL: + case NAMESPACE_DECL: + dump_decl (t, flags & ~TFF_DECL_SPECIFIERS); + break; + + case INTEGER_TYPE: + case REAL_TYPE: + case VOID_TYPE: + case BOOLEAN_TYPE: + case COMPLEX_TYPE: + case VECTOR_TYPE: + pp_type_specifier_seq (cxx_pp, t); + break; + + case TEMPLATE_TEMPLATE_PARM: + /* For parameters inside template signature. */ + if (TYPE_IDENTIFIER (t)) + pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t)); + else + pp_cxx_canonical_template_parameter (cxx_pp, t); + break; + + case BOUND_TEMPLATE_TEMPLATE_PARM: + { + tree args = TYPE_TI_ARGS (t); + 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); + pp_cxx_end_template_argument_list (cxx_pp); + } + break; + + case TEMPLATE_TYPE_PARM: + pp_cxx_cv_qualifier_seq (cxx_pp, t); + if (TYPE_IDENTIFIER (t)) + pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t)); + else + pp_cxx_canonical_template_parameter + (cxx_pp, TEMPLATE_TYPE_PARM_INDEX (t)); + break; + + /* This is not always necessary for pointers and such, but doing this + reduces code size. */ + case ARRAY_TYPE: + case POINTER_TYPE: + /* APPLE LOCAL blocks 6040305 */ + case BLOCK_POINTER_TYPE: + case REFERENCE_TYPE: + case OFFSET_TYPE: + offset_type: + case FUNCTION_TYPE: + case METHOD_TYPE: + { + dump_type_prefix (t, flags); + dump_type_suffix (t, flags); + break; + } + case TYPENAME_TYPE: + pp_cxx_cv_qualifier_seq (cxx_pp, t); + pp_cxx_identifier (cxx_pp, + TYPENAME_IS_ENUM_P (t) ? "enum" + : TYPENAME_IS_CLASS_P (t) ? "class" + : "typename"); + dump_typename (t, flags); + break; + + case UNBOUND_CLASS_TEMPLATE: + dump_type (TYPE_CONTEXT (t), flags); + pp_cxx_colon_colon (cxx_pp); + pp_cxx_identifier (cxx_pp, "template"); + dump_type (DECL_NAME (TYPE_NAME (t)), flags); + break; + + case TYPEOF_TYPE: + pp_cxx_identifier (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); + pp_cxx_right_paren (cxx_pp); + break; + + default: + pp_unsupported_tree (cxx_pp, t); + /* Fall through to error. */ + + case ERROR_MARK: + pp_identifier (cxx_pp, ""); + break; + } +} + +/* Dump a TYPENAME_TYPE. We need to notice when the context is itself + a TYPENAME_TYPE. */ + +static void +dump_typename (tree t, int flags) +{ + tree ctx = TYPE_CONTEXT (t); + + if (TREE_CODE (ctx) == TYPENAME_TYPE) + dump_typename (ctx, flags); + else + dump_type (ctx, flags & ~TFF_CLASS_KEY_OR_ENUM); + pp_cxx_colon_colon (cxx_pp); + dump_decl (TYPENAME_TYPE_FULLNAME (t), flags); +} + +/* Return the name of the supplied aggregate, or enumeral type. */ + +const char * +class_key_or_enum_as_string (tree t) +{ + if (TREE_CODE (t) == ENUMERAL_TYPE) + return "enum"; + else if (TREE_CODE (t) == UNION_TYPE) + return "union"; + else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t)) + return "class"; + else + return "struct"; +} + +/* Print out a class declaration T under the control of FLAGS, + in the form `class foo'. */ + +static void +dump_aggr_type (tree t, int flags) +{ + tree name; + const char *variety = class_key_or_enum_as_string (t); + int typdef = 0; + int tmplate = 0; + + 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); + + name = TYPE_NAME (t); + + if (name) + { + typdef = !DECL_ARTIFICIAL (name); + tmplate = !typdef && TREE_CODE (t) != ENUMERAL_TYPE + && TYPE_LANG_SPECIFIC (t) && CLASSTYPE_TEMPLATE_INFO (t) + && (TREE_CODE (CLASSTYPE_TI_TEMPLATE (t)) != TEMPLATE_DECL + || PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t))); + dump_scope (CP_DECL_CONTEXT (name), flags | TFF_SCOPE); + if (tmplate) + { + /* Because the template names are mangled, we have to locate + the most general template, and use that name. */ + tree tpl = CLASSTYPE_TI_TEMPLATE (t); + + while (DECL_TEMPLATE_INFO (tpl)) + tpl = DECL_TI_TEMPLATE (tpl); + name = tpl; + } + name = DECL_NAME (name); + } + + if (name == 0 || ANON_AGGRNAME_P (name)) + { + if (flags & TFF_CLASS_KEY_OR_ENUM) + pp_identifier (cxx_pp, ""); + else + pp_printf (pp_base (cxx_pp), "", variety); + } + else + pp_cxx_tree_identifier (cxx_pp, name); + if (tmplate) + dump_template_parms (TYPE_TEMPLATE_INFO (t), + !CLASSTYPE_USE_TEMPLATE (t), + flags & ~TFF_TEMPLATE_HEADER); +} + +/* Dump into the obstack the initial part of the output for a given type. + This is necessary when dealing with things like functions returning + functions. Examples: + + return type of `int (* fee ())()': pointer -> function -> int. Both + pointer (and reference and offset) and function (and member) types must + deal with prefix and suffix. + + Arrays must also do this for DECL nodes, like int a[], and for things like + int *[]&. */ + +static void +dump_type_prefix (tree t, int flags) +{ + if (TYPE_PTRMEMFUNC_P (t)) + { + t = TYPE_PTRMEMFUNC_FN_TYPE (t); + goto offset_type; + } + + switch (TREE_CODE (t)) + { + case POINTER_TYPE: + /* APPLE LOCAL blocks 6040305 */ + case BLOCK_POINTER_TYPE: + case REFERENCE_TYPE: + { + tree sub = TREE_TYPE (t); + + dump_type_prefix (sub, flags); + if (TREE_CODE (sub) == ARRAY_TYPE) + { + pp_cxx_whitespace (cxx_pp); + pp_cxx_left_paren (cxx_pp); + } + /* APPLE LOCAL begin blocks 6040305 */ + pp_character (cxx_pp, "&*^"[(TREE_CODE (t) == POINTER_TYPE) + + (TREE_CODE (t) == BLOCK_POINTER_TYPE)*2]); + /* APPLE LOCAL end blocks 6040305 */ + pp_base (cxx_pp)->padding = pp_before; + pp_cxx_cv_qualifier_seq (cxx_pp, t); + } + break; + + case OFFSET_TYPE: + offset_type: + dump_type_prefix (TREE_TYPE (t), flags); + if (TREE_CODE (t) == OFFSET_TYPE) /* pmfs deal with this in d_t_p */ + { + pp_maybe_space (cxx_pp); + if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) + pp_cxx_left_paren (cxx_pp); + dump_type (TYPE_OFFSET_BASETYPE (t), flags); + pp_cxx_colon_colon (cxx_pp); + } + pp_cxx_star (cxx_pp); + pp_cxx_cv_qualifier_seq (cxx_pp, t); + 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. */ + 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: + dump_type_prefix (TREE_TYPE (t), flags); + pp_maybe_space (cxx_pp); + pp_cxx_left_paren (cxx_pp); + dump_aggr_type (TYPE_METHOD_BASETYPE (t), flags); + pp_cxx_colon_colon (cxx_pp); + break; + + case ARRAY_TYPE: + dump_type_prefix (TREE_TYPE (t), flags); + break; + + case ENUMERAL_TYPE: + case IDENTIFIER_NODE: + case INTEGER_TYPE: + case BOOLEAN_TYPE: + case REAL_TYPE: + case RECORD_TYPE: + case TEMPLATE_TYPE_PARM: + case TEMPLATE_TEMPLATE_PARM: + case BOUND_TEMPLATE_TEMPLATE_PARM: + case TREE_LIST: + case TYPE_DECL: + case TREE_VEC: + case UNION_TYPE: + case UNKNOWN_TYPE: + case VOID_TYPE: + case TYPENAME_TYPE: + case COMPLEX_TYPE: + case VECTOR_TYPE: + case TYPEOF_TYPE: + dump_type (t, flags); + pp_base (cxx_pp)->padding = pp_before; + break; + + default: + pp_unsupported_tree (cxx_pp, t); + /* fall through. */ + case ERROR_MARK: + pp_identifier (cxx_pp, ""); + break; + } +} + +/* Dump the suffix of type T, under control of FLAGS. This is the part + which appears after the identifier (or function parms). */ + +static void +dump_type_suffix (tree t, int flags) +{ + if (TYPE_PTRMEMFUNC_P (t)) + t = TYPE_PTRMEMFUNC_FN_TYPE (t); + + switch (TREE_CODE (t)) + { + case POINTER_TYPE: + /* APPLE LOCAL blocks 6040305 */ + case BLOCK_POINTER_TYPE: + case REFERENCE_TYPE: + case OFFSET_TYPE: + if (TREE_CODE (TREE_TYPE (t)) == ARRAY_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); + arg = TYPE_ARG_TYPES (t); + if (TREE_CODE (t) == METHOD_TYPE) + arg = TREE_CHAIN (arg); + + /* Function pointers don't have default args. Not in standard C++, + anyway; they may in g++, but we'll just pretend otherwise. */ + dump_parameters (arg, flags & ~TFF_FUNCTION_DEFAULT_ARGUMENTS); + + if (TREE_CODE (t) == METHOD_TYPE) + pp_cxx_cv_qualifier_seq + (cxx_pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t)))); + else + pp_cxx_cv_qualifier_seq(cxx_pp, t); + dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags); + dump_type_suffix (TREE_TYPE (t), flags); + break; + } + + case ARRAY_TYPE: + pp_maybe_space (cxx_pp); + pp_cxx_left_bracket (cxx_pp); + if (TYPE_DOMAIN (t)) + { + if (host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0)) + pp_wide_integer + (cxx_pp, tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0) + 1); + else if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == MINUS_EXPR) + dump_expr (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0), + flags & ~TFF_EXPR_IN_PARENS); + else + dump_expr (fold (cp_build_binary_op + (PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (t)), + integer_one_node)), + flags & ~TFF_EXPR_IN_PARENS); + } + pp_cxx_right_bracket (cxx_pp); + dump_type_suffix (TREE_TYPE (t), flags); + break; + + case ENUMERAL_TYPE: + case IDENTIFIER_NODE: + case INTEGER_TYPE: + case BOOLEAN_TYPE: + case REAL_TYPE: + case RECORD_TYPE: + case TEMPLATE_TYPE_PARM: + case TEMPLATE_TEMPLATE_PARM: + case BOUND_TEMPLATE_TEMPLATE_PARM: + case TREE_LIST: + case TYPE_DECL: + case TREE_VEC: + case UNION_TYPE: + case UNKNOWN_TYPE: + case VOID_TYPE: + case TYPENAME_TYPE: + case COMPLEX_TYPE: + case VECTOR_TYPE: + case TYPEOF_TYPE: + break; + + default: + pp_unsupported_tree (cxx_pp, t); + case ERROR_MARK: + /* Don't mark it here, we should have already done in + dump_type_prefix. */ + break; + } +} + +static void +dump_global_iord (tree t) +{ + const char *p = NULL; + + if (DECL_GLOBAL_CTOR_P (t)) + p = "initializers"; + else if (DECL_GLOBAL_DTOR_P (t)) + p = "destructors"; + else + gcc_unreachable (); + + pp_printf (pp_base (cxx_pp), "(static %s for %s)", p, input_filename); +} + +static void +dump_simple_decl (tree t, tree type, int flags) +{ + if (flags & TFF_DECL_SPECIFIERS) + { + dump_type_prefix (type, flags); + pp_maybe_space (cxx_pp); + } + if (!DECL_INITIAL (t) || TREE_CODE (DECL_INITIAL (t)) != TEMPLATE_PARM_INDEX) + dump_scope (CP_DECL_CONTEXT (t), flags); + if (DECL_NAME (t)) + dump_decl (DECL_NAME (t), flags); + else + pp_identifier (cxx_pp, ""); + if (flags & TFF_DECL_SPECIFIERS) + dump_type_suffix (type, flags); +} + +/* Dump a human readable string for the decl T under control of FLAGS. */ + +static void +dump_decl (tree t, int flags) +{ + if (t == NULL_TREE) + return; + + switch (TREE_CODE (t)) + { + case TYPE_DECL: + /* Don't say 'typedef class A' */ + if (DECL_ARTIFICIAL (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"); + + dump_type (TREE_TYPE (t), flags); + break; + } + if (flags & TFF_DECL_SPECIFIERS) + pp_cxx_identifier (cxx_pp, "typedef"); + dump_simple_decl (t, DECL_ORIGINAL_TYPE (t) + ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), + flags); + break; + + case VAR_DECL: + if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t))) + { + pp_string (cxx_pp, "vtable for "); + gcc_assert (TYPE_P (DECL_CONTEXT (t))); + dump_type (DECL_CONTEXT (t), flags); + break; + } + /* Else fall through. */ + case FIELD_DECL: + case PARM_DECL: + dump_simple_decl (t, TREE_TYPE (t), flags); + break; + + case RESULT_DECL: + pp_string (cxx_pp, " "); + dump_simple_decl (t, TREE_TYPE (t), flags); + break; + + case NAMESPACE_DECL: + if (flags & TFF_DECL_SPECIFIERS) + pp_cxx_declaration (cxx_pp, t); + else + { + dump_scope (CP_DECL_CONTEXT (t), flags); + if (DECL_NAME (t) == NULL_TREE) + pp_identifier (cxx_pp, ""); + else + pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t)); + } + break; + + case SCOPE_REF: + pp_expression (cxx_pp, t); + break; + + case ARRAY_REF: + dump_decl (TREE_OPERAND (t, 0), flags); + pp_cxx_left_bracket (cxx_pp); + dump_decl (TREE_OPERAND (t, 1), flags); + pp_cxx_right_bracket (cxx_pp); + break; + + /* So that we can do dump_decl on an aggr type. */ + case RECORD_TYPE: + case UNION_TYPE: + case ENUMERAL_TYPE: + dump_type (t, flags); + break; + + case BIT_NOT_EXPR: + /* This is a pseudo destructor call which has not been folded into + a PSEUDO_DTOR_EXPR yet. */ + pp_cxx_complement (cxx_pp); + dump_type (TREE_OPERAND (t, 0), flags); + break; + + case TYPE_EXPR: + gcc_unreachable (); + break; + + /* These special cases are duplicated here so that other functions + can feed identifiers to error and get them demangled properly. */ + case IDENTIFIER_NODE: + if (IDENTIFIER_TYPENAME_P (t)) + { + pp_cxx_identifier (cxx_pp, "operator"); + /* Not exactly IDENTIFIER_TYPE_VALUE. */ + dump_type (TREE_TYPE (t), flags); + break; + } + else + pp_cxx_tree_identifier (cxx_pp, t); + break; + + case OVERLOAD: + if (OVL_CHAIN (t)) + { + t = OVL_CURRENT (t); + if (DECL_CLASS_SCOPE_P (t)) + { + dump_type (DECL_CONTEXT (t), flags); + pp_cxx_colon_colon (cxx_pp); + } + else if (DECL_CONTEXT (t)) + { + dump_decl (DECL_CONTEXT (t), flags); + pp_cxx_colon_colon (cxx_pp); + } + dump_decl (DECL_NAME (t), flags); + break; + } + + /* If there's only one function, just treat it like an ordinary + FUNCTION_DECL. */ + t = OVL_CURRENT (t); + /* Fall through. */ + + case FUNCTION_DECL: + if (! DECL_LANG_SPECIFIC (t)) + pp_identifier (cxx_pp, ""); + else if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t)) + dump_global_iord (t); + else + dump_function_decl (t, flags); + break; + + case TEMPLATE_DECL: + dump_template_decl (t, flags); + break; + + case TEMPLATE_ID_EXPR: + { + tree name = TREE_OPERAND (t, 0); + + if (is_overloaded_fn (name)) + name = DECL_NAME (get_first_fn (name)); + 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); + pp_cxx_end_template_argument_list (cxx_pp); + } + break; + + case LABEL_DECL: + pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t)); + break; + + case CONST_DECL: + if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE) + || (DECL_INITIAL (t) && + TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX)) + dump_simple_decl (t, TREE_TYPE (t), flags); + else if (DECL_NAME (t)) + dump_decl (DECL_NAME (t), flags); + else if (DECL_INITIAL (t)) + dump_expr (DECL_INITIAL (t), flags | TFF_EXPR_IN_PARENS); + else + pp_identifier (cxx_pp, ""); + break; + + case USING_DECL: + pp_cxx_identifier (cxx_pp, "using"); + dump_type (USING_DECL_SCOPE (t), flags); + pp_cxx_colon_colon (cxx_pp); + dump_decl (DECL_NAME (t), flags); + break; + + case BASELINK: + dump_decl (BASELINK_FUNCTIONS (t), flags); + break; + + case NON_DEPENDENT_EXPR: + dump_expr (t, flags); + break; + + case TEMPLATE_TYPE_PARM: + if (flags & TFF_DECL_SPECIFIERS) + pp_cxx_declaration (cxx_pp, t); + else + pp_type_id (cxx_pp, t); + break; + + default: + pp_unsupported_tree (cxx_pp, t); + /* Fall through to error. */ + + case ERROR_MARK: + pp_identifier (cxx_pp, ""); + break; + } +} + +/* Dump a template declaration T under control of FLAGS. This means the + 'template <...> leaders plus the 'class X' or 'void fn(...)' part. */ + +static void +dump_template_decl (tree t, int flags) +{ + tree orig_parms = DECL_TEMPLATE_PARMS (t); + tree parms; + int i; + + if (flags & TFF_TEMPLATE_HEADER) + { + for (parms = orig_parms = nreverse (orig_parms); + parms; + parms = TREE_CHAIN (parms)) + { + tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms); + int len = TREE_VEC_LENGTH (inner_parms); + + pp_cxx_identifier (cxx_pp, "template"); + pp_cxx_begin_template_argument_list (cxx_pp); + + /* If we've shown the template prefix, we'd better show the + parameters' and decl's type too. */ + flags |= TFF_DECL_SPECIFIERS; + + for (i = 0; i < len; i++) + { + if (i) + pp_separate_with_comma (cxx_pp); + dump_template_parameter (TREE_VEC_ELT (inner_parms, i), flags); + } + pp_cxx_end_template_argument_list (cxx_pp); + pp_cxx_whitespace (cxx_pp); + } + nreverse(orig_parms); + + if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)) + /* Say `template class TT' not just `template TT'. */ + pp_cxx_identifier (cxx_pp, "class"); + } + + if (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) + dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME); + else + { + gcc_assert (TREE_TYPE (t)); + switch (NEXT_CODE (t)) + { + case METHOD_TYPE: + case FUNCTION_TYPE: + dump_function_decl (t, flags | TFF_TEMPLATE_NAME); + break; + default: + /* This case can occur with some invalid code. */ + dump_type (TREE_TYPE (t), + (flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME + | (flags & TFF_DECL_SPECIFIERS + ? TFF_CLASS_KEY_OR_ENUM : 0)); + } + } +} + +/* 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 + is %D which doesn't print the throw specs, and %F which does. */ + +static void +dump_function_decl (tree t, int flags) +{ + tree fntype; + tree parmtypes; + tree cname = NULL_TREE; + tree template_args = NULL_TREE; + tree template_parms = NULL_TREE; + int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS; + + if (TREE_CODE (t) == TEMPLATE_DECL) + t = DECL_TEMPLATE_RESULT (t); + + /* Pretty print template instantiations only. */ + if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t)) + { + tree tmpl; + + template_args = DECL_TI_ARGS (t); + tmpl = most_general_template (t); + if (tmpl && TREE_CODE (tmpl) == TEMPLATE_DECL) + { + template_parms = DECL_TEMPLATE_PARMS (tmpl); + t = tmpl; + } + } + + fntype = TREE_TYPE (t); + parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t); + + if (DECL_CLASS_SCOPE_P (t)) + cname = DECL_CONTEXT (t); + /* This is for partially instantiated template methods. */ + 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"); + + /* Print the return type? */ + if (show_return) + show_return = !DECL_CONV_FN_P (t) && !DECL_CONSTRUCTOR_P (t) + && !DECL_DESTRUCTOR_P (t); + if (show_return) + dump_type_prefix (TREE_TYPE (fntype), flags); + + /* Print the function name. */ + if (cname) + { + dump_type (cname, flags); + pp_cxx_colon_colon (cxx_pp); + } + else + dump_scope (CP_DECL_CONTEXT (t), flags); + + dump_function_name (t, flags); + + if (!(flags & TFF_NO_FUNCTION_ARGUMENTS)) + { + dump_parameters (parmtypes, flags); + + if (TREE_CODE (fntype) == METHOD_TYPE) + { + pp_base (cxx_pp)->padding = pp_before; + pp_cxx_cv_qualifier_seq + (cxx_pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype)))); + } + + if (flags & TFF_EXCEPTION_SPECIFICATION) + { + pp_base (cxx_pp)->padding = pp_before; + dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags); + } + + if (show_return) + dump_type_suffix (TREE_TYPE (fntype), flags); + } + + /* If T is a template instantiation, dump the parameter binding. */ + if (template_parms != NULL_TREE && template_args != NULL_TREE) + { + pp_cxx_whitespace (cxx_pp); + pp_cxx_left_bracket (cxx_pp); + pp_cxx_identifier (cxx_pp, "with"); + pp_cxx_whitespace (cxx_pp); + dump_template_bindings (template_parms, template_args); + pp_cxx_right_bracket (cxx_pp); + } +} + +/* Print a parameter list. If this is for a member function, the + member object ptr (and any other hidden args) should have + already been removed. */ + +static void +dump_parameters (tree parmtypes, int flags) +{ + int first; + + pp_cxx_left_paren (cxx_pp); + + for (first = 1; parmtypes != void_list_node; + parmtypes = TREE_CHAIN (parmtypes)) + { + if (!first) + pp_separate_with_comma (cxx_pp); + first = 0; + if (!parmtypes) + { + pp_cxx_identifier (cxx_pp, "..."); + break; + } + dump_type (TREE_VALUE (parmtypes), flags); + + if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes)) + { + pp_cxx_whitespace (cxx_pp); + pp_equal (cxx_pp); + pp_cxx_whitespace (cxx_pp); + dump_expr (TREE_PURPOSE (parmtypes), flags | TFF_EXPR_IN_PARENS); + } + } + + pp_cxx_right_paren (cxx_pp); +} + +/* Print an exception specification. T is the exception specification. */ + +static void +dump_exception_spec (tree t, int flags) +{ + if (t) + { + pp_cxx_identifier (cxx_pp, "throw"); + pp_cxx_whitespace (cxx_pp); + pp_cxx_left_paren (cxx_pp); + if (TREE_VALUE (t) != NULL_TREE) + while (1) + { + dump_type (TREE_VALUE (t), flags); + t = TREE_CHAIN (t); + if (!t) + break; + pp_separate_with_comma (cxx_pp); + } + pp_cxx_right_paren (cxx_pp); + } +} + +/* Handle the function name for a FUNCTION_DECL node, grokking operators + and destructors properly. */ + +static void +dump_function_name (tree t, int flags) +{ + tree name = DECL_NAME (t); + + /* We can get here with a decl that was synthesized by language- + independent machinery (e.g. coverage.c) in which case it won't + have a lang_specific structure attached and DECL_CONSTRUCTOR_P + will crash. In this case it is safe just to print out the + literal name. */ + if (!DECL_LANG_SPECIFIC (t)) + { + pp_cxx_tree_identifier (cxx_pp, name); + return; + } + + if (TREE_CODE (t) == TEMPLATE_DECL) + t = DECL_TEMPLATE_RESULT (t); + + /* 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 (DECL_DESTRUCTOR_P (t)) + { + pp_cxx_complement (cxx_pp); + dump_decl (name, TFF_PLAIN_IDENTIFIER); + } + else if (DECL_CONV_FN_P (t)) + { + /* This cannot use the hack that the operator's return + type is stashed off of its name because it may be + used for error reporting. In the case of conflicting + 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"); + dump_type (TREE_TYPE (TREE_TYPE (t)), flags); + } + else if (IDENTIFIER_OPNAME_P (name)) + pp_cxx_tree_identifier (cxx_pp, name); + else + dump_decl (name, flags); + + if (DECL_TEMPLATE_INFO (t) + && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t) + && (TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL + || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t)))) + dump_template_parms (DECL_TEMPLATE_INFO (t), !DECL_USE_TEMPLATE (t), flags); +} + +/* Dump the template parameters from the template info INFO under control of + FLAGS. PRIMARY indicates whether this is a primary template decl, or + specialization (partial or complete). For partial specializations we show + the specialized parameter values. For a primary template we show no + decoration. */ + +static void +dump_template_parms (tree info, int primary, int flags) +{ + tree args = info ? TI_ARGS (info) : NULL_TREE; + + if (primary && flags & TFF_TEMPLATE_NAME) + return; + flags &= ~(TFF_CLASS_KEY_OR_ENUM | TFF_TEMPLATE_NAME); + 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. */ + if (args && !primary) + { + int len, ix; + + if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) + args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1); + + len = TREE_VEC_LENGTH (args); + + for (ix = 0; ix != len; ix++) + { + tree arg = TREE_VEC_ELT (args, ix); + + if (ix) + pp_separate_with_comma (cxx_pp); + + if (!arg) + pp_identifier (cxx_pp, "