/* Call-backs for C++ error reporting. This code is non-reentrant. Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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" enum pad { none, before, after }; #define pp_template_argument_list_start(PP) \ pp_non_consecutive_character (PP, '<') #define pp_template_argument_list_end(PP) \ pp_non_consecutive_character (PP, '>') #define pp_separate_with_comma(PP) pp_string (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))) #define reinit_global_formatting_buffer() \ output_clear_message_text (scratch_buffer) 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 enum pad 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 enum pad dump_qualifiers (tree, enum pad); static void dump_parameters (tree, int); static void dump_exception_spec (tree, int); static const char *class_key_or_enum (tree); 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 *); static void pp_non_consecutive_character (cxx_pretty_printer *, int); static tree locate_error (const char *, va_list); 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_colon_colon (cxx_pp); } } else if (AGGREGATE_TYPE_P (scope)) { dump_type (scope, f); pp_colon_colon (cxx_pp); } else if ((flags & TFF_SCOPE) && TREE_CODE (scope) == FUNCTION_DECL) { dump_function_decl (scope, f); pp_colon_colon (cxx_pp); } } /* Dump type qualifiers, providing padding as requested. Return an indication of whether we dumped something. */ static enum pad dump_qualifiers (tree t, enum pad p) { static const int masks[] = {TYPE_QUAL_CONST, TYPE_QUAL_VOLATILE, TYPE_QUAL_RESTRICT}; static const char *const names[] = {"const", "volatile", "__restrict"}; int ix; int quals = TYPE_QUALS (t); int do_after = p == after; if (quals) { for (ix = 0; ix != 3; ix++) if (masks[ix] & quals) { if (p == before) pp_space (cxx_pp); p = before; pp_identifier (cxx_pp, names[ix]); } if (do_after) pp_space (cxx_pp); } else p = none; return p; } /* 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_VALUE (parm); tree a = TREE_PURPOSE (parm); if (TREE_CODE (p) == TYPE_DECL) { if (flags & TFF_DECL_SPECIFIERS) { pp_identifier (cxx_pp, "class"); if (DECL_NAME (p)) { pp_space (cxx_pp); pp_tree_identifier (cxx_pp, DECL_NAME (p)); } } else if (DECL_NAME (p)) pp_tree_identifier (cxx_pp, DECL_NAME (p)); else pp_identifier (cxx_pp, "