/* Call-backs for C++ error reporting.
This code is non-reentrant.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002,
- 2003, 2004 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2008 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,
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. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
static void dump_type_prefix (tree, int);
static void dump_type_suffix (tree, int);
static void dump_function_name (tree, int);
+static void dump_call_expr_args (tree, int, bool);
+static void dump_aggr_init_expr_args (tree, int, bool);
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 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 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 *);
-static bool cp_printer (pretty_printer *, text_info *);
-static tree locate_error (const char *, va_list);
+static bool cp_printer (pretty_printer *, text_info *, const char *,
+ int, bool, bool, bool);
static location_t location_of (tree);
void
if (TREE_CODE (scope) == NAMESPACE_DECL)
{
if (scope != global_namespace)
- {
- dump_decl (scope, f);
- pp_cxx_colon_colon (cxx_pp);
- }
+ {
+ dump_decl (scope, f);
+ pp_cxx_colon_colon (cxx_pp);
+ }
}
else if (AGGREGATE_TYPE_P (scope))
{
static void
dump_template_argument (tree arg, int flags)
{
- if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL)
+ if (ARGUMENT_PACK_P (arg))
+ dump_template_argument_list (ARGUMENT_PACK_ARGS (arg), 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);
+ }
}
/* Dump a template-argument-list ARGS (always a TREE_VEC) under control
for (i = 0; i< n; ++i)
{
- if (need_comma)
- pp_separate_with_comma (cxx_pp);
- dump_template_argument (TREE_VEC_ELT (args, i), flags);
+ tree arg = TREE_VEC_ELT (args, i);
+
+ /* Only print a comma if we know there is an argument coming. In
+ the case of an empty template argument pack, no actual
+ argument will be printed. */
+ if (need_comma
+ && (!ARGUMENT_PACK_P (arg)
+ || TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg)) > 0))
+ pp_separate_with_comma (cxx_pp);
+
+ dump_template_argument (arg, flags);
need_comma = 1;
}
}
static void
dump_template_parameter (tree parm, int flags)
{
- tree p = TREE_VALUE (parm);
- tree a = TREE_PURPOSE (parm);
+ 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));
- }
+ {
+ pp_cxx_identifier (cxx_pp, "class");
+ if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (p)))
+ pp_cxx_identifier (cxx_pp, "...");
+ 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));
+ pp_cxx_tree_identifier (cxx_pp, DECL_NAME (p));
else
- pp_cxx_canonical_template_parameter (cxx_pp, TREE_TYPE (p));
+ pp_cxx_canonical_template_parameter (cxx_pp, TREE_TYPE (p));
}
else
dump_decl (p, flags | TFF_DECL_SPECIFIERS);
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);
+ dump_type (a, flags & ~TFF_CHASE_TYPEDEF);
else
- dump_expr (a, flags | TFF_EXPR_IN_PARENS);
+ dump_expr (a, flags | TFF_EXPR_IN_PARENS);
}
}
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);
+ pp_cxx_whitespace (cxx_pp);
+ pp_equal (cxx_pp);
+ pp_cxx_whitespace (cxx_pp);
if (arg)
dump_template_argument (arg, TFF_PLAIN_IDENTIFIER);
else
switch (TREE_CODE (t))
{
case UNKNOWN_TYPE:
- pp_identifier (cxx_pp, "<unknown type>");
+ pp_identifier (cxx_pp, "<unresolved overloaded function type>");
break;
case TREE_LIST:
pp_cxx_tree_identifier (cxx_pp, t);
break;
- case TREE_VEC:
+ case TREE_BINFO:
dump_type (BINFO_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;
- }
+ {
+ dump_type (DECL_ORIGINAL_TYPE (t)
+ ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), flags);
+ break;
+ }
/* Else fall through. */
case TEMPLATE_DECL:
if (TYPE_IDENTIFIER (t))
pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t));
else
- pp_cxx_canonical_template_parameter (cxx_pp, t);
+ pp_cxx_canonical_template_parameter (cxx_pp, t);
break;
case BOUND_TEMPLATE_TEMPLATE_PARM:
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, flags);
pp_cxx_end_template_argument_list (cxx_pp);
}
break;
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));
+ 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
}
case TYPENAME_TYPE:
pp_cxx_cv_qualifier_seq (cxx_pp, t);
- pp_cxx_identifier (cxx_pp, "typename");
+ pp_cxx_identifier (cxx_pp,
+ TYPENAME_IS_ENUM_P (t) ? "enum"
+ : TYPENAME_IS_CLASS_P (t) ? "class"
+ : "typename");
dump_typename (t, flags);
break;
pp_cxx_right_paren (cxx_pp);
break;
+ case TYPE_PACK_EXPANSION:
+ dump_type (PACK_EXPANSION_PATTERN (t), flags);
+ pp_cxx_identifier (cxx_pp, "...");
+ break;
+
+ case TYPE_ARGUMENT_PACK:
+ dump_template_argument (t, flags);
+ break;
+
+ case DECLTYPE_TYPE:
+ pp_cxx_identifier (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:
pp_unsupported_tree (cxx_pp, t);
/* Fall through to error. */
/* Return the name of the supplied aggregate, or enumeral type. */
-static const char *
-class_key_or_enum (tree t)
+const char *
+class_key_or_enum_as_string (tree t)
{
if (TREE_CODE (t) == ENUMERAL_TYPE)
return "enum";
dump_aggr_type (tree t, int flags)
{
tree name;
- const char *variety = class_key_or_enum (t);
+ const char *variety = class_key_or_enum_as_string (t);
int typdef = 0;
int tmplate = 0;
{
typdef = !DECL_ARTIFICIAL (name);
tmplate = !typdef && TREE_CODE (t) != ENUMERAL_TYPE
- && TYPE_LANG_SPECIFIC (t) && CLASSTYPE_TEMPLATE_INFO (t)
- && (CLASSTYPE_TEMPLATE_SPECIALIZATION (t)
- || TREE_CODE (CLASSTYPE_TI_TEMPLATE (t)) != TEMPLATE_DECL
- || DECL_TEMPLATE_SPECIALIZATION (CLASSTYPE_TI_TEMPLATE (t))
- || PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)));
- dump_scope (CP_DECL_CONTEXT (name), flags | TFF_SCOPE);
+ && TYPE_LANG_SPECIFIC (t) && CLASSTYPE_TEMPLATE_INFO (t)
+ && (TREE_CODE (CLASSTYPE_TI_TEMPLATE (t)) != TEMPLATE_DECL
+ || PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)));
+
+ if (! (flags & TFF_UNQUALIFIED_NAME))
+ dump_scope (CP_DECL_CONTEXT (name), flags | TFF_SCOPE);
+ flags &= ~TFF_UNQUALIFIED_NAME;
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;
- }
+ {
+ /* 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, "<anonymous>");
+ pp_identifier (cxx_pp, "<anonymous>");
else
- pp_printf (pp_base (cxx_pp), "<anonymous %s>", variety);
+ pp_printf (pp_base (cxx_pp), "<anonymous %s>", 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);
+ !CLASSTYPE_USE_TEMPLATE (t),
+ flags & ~TFF_TEMPLATE_HEADER);
}
/* Dump into the obstack the initial part of the output for a given type.
Arrays must also do this for DECL nodes, like int a[], and for things like
int *[]&. */
-static void
+static void
dump_type_prefix (tree t, int flags)
{
if (TYPE_PTRMEMFUNC_P (t))
pp_cxx_whitespace (cxx_pp);
pp_cxx_left_paren (cxx_pp);
}
- pp_character (cxx_pp, "&*"[TREE_CODE (t) == POINTER_TYPE]);
- pp_base (cxx_pp)->padding = pp_before;
- pp_cxx_cv_qualifier_seq (cxx_pp, t);
+ if (TREE_CODE (t) == POINTER_TYPE)
+ pp_character(cxx_pp, '*');
+ else if (TREE_CODE (t) == REFERENCE_TYPE)
+ {
+ if (TYPE_REF_IS_RVALUE (t))
+ pp_string (cxx_pp, "&&");
+ else
+ pp_character (cxx_pp, '&');
+ }
+ pp_base (cxx_pp)->padding = pp_before;
+ pp_cxx_cv_qualifier_seq (cxx_pp, t);
}
break;
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);
+ 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);
}
break;
/* Can only be reached through function pointer -- this would not be
- correct if FUNCTION_DECLs used it. */
+ correct if FUNCTION_DECLs used it. */
case FUNCTION_TYPE:
dump_type_prefix (TREE_TYPE (t), flags);
pp_maybe_space (cxx_pp);
case COMPLEX_TYPE:
case VECTOR_TYPE:
case TYPEOF_TYPE:
+ case DECLTYPE_TYPE:
+ case TYPE_PACK_EXPANSION:
dump_type (t, flags);
pp_base (cxx_pp)->padding = pp_before;
break;
case METHOD_TYPE:
{
tree arg;
- pp_cxx_right_paren (cxx_pp);
+ pp_cxx_right_paren (cxx_pp);
arg = TYPE_ARG_TYPES (t);
if (TREE_CODE (t) == METHOD_TYPE)
arg = TREE_CHAIN (arg);
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))));
+ 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;
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);
+ tree dtype = TYPE_DOMAIN (t);
+ tree max = TYPE_MAX_VALUE (dtype);
+ if (host_integerp (max, 0))
+ pp_wide_integer (cxx_pp, tree_low_cst (max, 0) + 1);
+ else if (TREE_CODE (max) == MINUS_EXPR)
+ dump_expr (TREE_OPERAND (max, 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);
+ dump_expr (fold_build2 (PLUS_EXPR, dtype, max,
+ build_int_cst (dtype, 1)),
+ flags & ~TFF_EXPR_IN_PARENS);
}
pp_cxx_right_bracket (cxx_pp);
dump_type_suffix (TREE_TYPE (t), flags);
case COMPLEX_TYPE:
case VECTOR_TYPE:
case TYPEOF_TYPE:
+ case DECLTYPE_TYPE:
+ case TYPE_PACK_EXPANSION:
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. */
+ dump_type_prefix. */
break;
}
}
else if (DECL_GLOBAL_DTOR_P (t))
p = "destructors";
else
- abort ();
+ gcc_unreachable ();
pp_printf (pp_base (cxx_pp), "(static %s for %s)", p, input_filename);
}
{
if (flags & TFF_DECL_SPECIFIERS)
{
- dump_type_prefix (type, flags);
+ dump_type_prefix (type, flags & ~TFF_UNQUALIFIED_NAME);
pp_maybe_space (cxx_pp);
}
- if (!DECL_INITIAL (t) || TREE_CODE (DECL_INITIAL (t)) != TEMPLATE_PARM_INDEX)
+ if (! (flags & TFF_UNQUALIFIED_NAME)
+ && (!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_identifier (cxx_pp, "...");
if (DECL_NAME (t))
dump_decl (DECL_NAME (t), flags);
else
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)
+ /* 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;
- }
- }
+ /* Emit the `...' for a parameter pack. */
+ if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t)))
+ pp_cxx_identifier (cxx_pp, "...");
+ }
+
+ 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);
+ flags);
break;
case VAR_DECL:
/* Else fall through. */
case FIELD_DECL:
case PARM_DECL:
- case ALIAS_DECL:
dump_simple_decl (t, TREE_TYPE (t), flags);
break;
case NAMESPACE_DECL:
if (flags & TFF_DECL_SPECIFIERS)
- pp_cxx_declaration (cxx_pp, t);
+ pp_cxx_declaration (cxx_pp, t);
else
- {
- dump_scope (CP_DECL_CONTEXT (t), flags);
- if (DECL_NAME (t) == NULL_TREE)
- pp_identifier (cxx_pp, "<unnamed>");
- else
- pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t));
- }
+ {
+ if (! (flags & TFF_UNQUALIFIED_NAME))
+ dump_scope (CP_DECL_CONTEXT (t), flags);
+ flags &= ~TFF_UNQUALIFIED_NAME;
+ if (DECL_NAME (t) == NULL_TREE)
+ pp_identifier (cxx_pp, "<unnamed>");
+ else
+ pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t));
+ }
break;
case SCOPE_REF:
case BIT_NOT_EXPR:
/* This is a pseudo destructor call which has not been folded into
- a PSEUDO_DTOR_EXPR yet. */
+ a PSEUDO_DTOR_EXPR yet. */
pp_cxx_complement (cxx_pp);
dump_type (TREE_OPERAND (t, 0), flags);
break;
case TYPE_EXPR:
- abort ();
+ gcc_unreachable ();
break;
/* These special cases are duplicated here so that other functions
if (DECL_CLASS_SCOPE_P (t))
{
dump_type (DECL_CONTEXT (t), flags);
- pp_cxx_colon_colon (cxx_pp);
+ pp_cxx_colon_colon (cxx_pp);
}
else if (DECL_CONTEXT (t))
{
dump_decl (DECL_CONTEXT (t), flags);
- pp_cxx_colon_colon (cxx_pp);
+ 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_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
- dump_global_iord (t);
- else if (! DECL_LANG_SPECIFIC (t))
+ if (! DECL_LANG_SPECIFIC (t))
pp_identifier (cxx_pp, "<built-in>");
+ else if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
+ dump_global_iord (t);
else
- dump_function_decl (t, flags);
+ dump_function_decl (t, flags);
break;
case TEMPLATE_DECL:
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);
case USING_DECL:
pp_cxx_identifier (cxx_pp, "using");
- dump_type (DECL_INITIAL (t), flags);
+ dump_type (USING_DECL_SCOPE (t), flags);
pp_cxx_colon_colon (cxx_pp);
dump_decl (DECL_NAME (t), flags);
break;
+ case STATIC_ASSERT:
+ pp_cxx_declaration (cxx_pp, t);
+ break;
+
case BASELINK:
dump_decl (BASELINK_FUNCTIONS (t), flags);
break;
case TEMPLATE_TYPE_PARM:
if (flags & TFF_DECL_SPECIFIERS)
- pp_cxx_declaration (cxx_pp, t);
+ pp_cxx_declaration (cxx_pp, t);
else
- pp_type_id (cxx_pp, t);
+ pp_type_id (cxx_pp, t);
+ break;
+
+ case UNBOUND_CLASS_TEMPLATE:
+ case TYPE_PACK_EXPANSION:
+ case TREE_BINFO:
+ dump_type (t, flags);
break;
default:
if (flags & TFF_TEMPLATE_HEADER)
{
for (parms = orig_parms = nreverse (orig_parms);
- parms;
- parms = TREE_CHAIN (parms))
- {
+ parms;
+ parms = TREE_CHAIN (parms))
+ {
tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms);
- int len = TREE_VEC_LENGTH (inner_parms);
+ int len = TREE_VEC_LENGTH (inner_parms);
- pp_cxx_identifier (cxx_pp, "template");
- pp_cxx_begin_template_argument_list (cxx_pp);
+ 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);
- }
+ 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<arg> class TT' not just `template<arg> TT'. */
- pp_cxx_identifier (cxx_pp, "class");
+ {
+ /* Say `template<arg> class TT' not just `template<arg> TT'. */
+ pp_cxx_identifier (cxx_pp, "class");
+
+ /* If this is a parameter pack, print the ellipsis. */
+ if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t)))
+ pp_cxx_identifier (cxx_pp, "...");
+ }
}
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)));
+ ((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 if (TREE_TYPE (t) == NULL_TREE)
- abort ();
else
- 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));
+ 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));
+ }
}
}
tree template_args = NULL_TREE;
tree template_parms = NULL_TREE;
int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
+ int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
+ flags &= ~TFF_UNQUALIFIED_NAME;
if (TREE_CODE (t) == TEMPLATE_DECL)
t = DECL_TEMPLATE_RESULT (t);
/* Print the return type? */
if (show_return)
show_return = !DECL_CONV_FN_P (t) && !DECL_CONSTRUCTOR_P (t)
- && !DECL_DESTRUCTOR_P (t);
+ && !DECL_DESTRUCTOR_P (t);
if (show_return)
dump_type_prefix (TREE_TYPE (fntype), flags);
/* Print the function name. */
- if (cname)
+ if (!do_outer_scope)
+ /* Nothing. */;
+ else if (cname)
{
dump_type (cname, flags);
pp_cxx_colon_colon (cxx_pp);
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))));
- }
+ {
+ 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);
- }
+ {
+ 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);
static void
dump_parameters (tree parmtypes, int flags)
{
- int first;
-
+ int first = 1;
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);
+ pp_separate_with_comma (cxx_pp);
first = 0;
if (!parmtypes)
- {
- pp_cxx_identifier (cxx_pp, "...");
- break;
- }
+ {
+ 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_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);
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);
- }
+ 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);
}
}
if (DECL_TEMPLATE_INFO (t)
&& !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t)
- && (DECL_TEMPLATE_SPECIALIZATION (t)
- || TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL
- || DECL_TEMPLATE_SPECIALIZATION (DECL_TI_TEMPLATE (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);
}
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)
+ {
+ tree arg = TREE_VEC_ELT (args, ix);
+
+ /* Only print a comma if we know there is an argument coming. In
+ the case of an empty template argument pack, no actual
+ argument will be printed. */
+ if (ix
+ && (!ARGUMENT_PACK_P (arg)
+ || TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg)) > 0))
pp_separate_with_comma (cxx_pp);
if (!arg)
len = parms ? TREE_VEC_LENGTH (parms) : 0;
for (ix = 0; ix != len; ix++)
- {
- tree parm = TREE_VALUE (TREE_VEC_ELT (parms, ix));
+ {
+ tree parm;
- if (ix)
- pp_separate_with_comma (cxx_pp);
+ if (TREE_VEC_ELT (parms, ix) == error_mark_node)
+ {
+ pp_identifier (cxx_pp, "<template parameter error>");
+ continue;
+ }
- dump_decl (parm, flags & ~TFF_DECL_SPECIFIERS);
- }
+ parm = TREE_VALUE (TREE_VEC_ELT (parms, ix));
+
+ if (ix)
+ pp_separate_with_comma (cxx_pp);
+
+ dump_decl (parm, flags & ~TFF_DECL_SPECIFIERS);
+ }
}
pp_cxx_end_template_argument_list (cxx_pp);
}
+/* Print out the arguments of CALL_EXPR T as a parenthesized list using
+ flags FLAGS. Skip over the first argument if SKIPFIRST is true. */
+
+static void
+dump_call_expr_args (tree t, int flags, bool skipfirst)
+{
+ tree arg;
+ call_expr_arg_iterator iter;
+
+ pp_cxx_left_paren (cxx_pp);
+ FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
+ {
+ if (skipfirst)
+ skipfirst = false;
+ else
+ {
+ dump_expr (arg, flags | TFF_EXPR_IN_PARENS);
+ if (more_call_expr_args_p (&iter))
+ pp_separate_with_comma (cxx_pp);
+ }
+ }
+ pp_cxx_right_paren (cxx_pp);
+}
+
+/* Print out the arguments of AGGR_INIT_EXPR T as a parenthesized list
+ using flags FLAGS. Skip over the first argument if SKIPFIRST is
+ true. */
+
+static void
+dump_aggr_init_expr_args (tree t, int flags, bool skipfirst)
+{
+ tree arg;
+ aggr_init_expr_arg_iterator iter;
+
+ pp_cxx_left_paren (cxx_pp);
+ FOR_EACH_AGGR_INIT_EXPR_ARG (arg, iter, t)
+ {
+ if (skipfirst)
+ skipfirst = false;
+ else
+ {
+ dump_expr (arg, flags | TFF_EXPR_IN_PARENS);
+ if (more_aggr_init_expr_args_p (&iter))
+ pp_separate_with_comma (cxx_pp);
+ }
+ }
+ pp_cxx_right_paren (cxx_pp);
+}
+
/* Print out a list of initializers (subr of dump_expr). */
static void
}
}
+/* Print out a vector of initializers (subr of dump_expr). */
+
+static void
+dump_expr_init_vec (VEC(constructor_elt,gc) *v, int flags)
+{
+ unsigned HOST_WIDE_INT idx;
+ tree value;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
+ {
+ dump_expr (value, flags | TFF_EXPR_IN_PARENS);
+ if (idx != VEC_length (constructor_elt, v) - 1)
+ pp_separate_with_comma (cxx_pp);
+ }
+}
+
+
+/* We've gotten an indirect REFERENCE (an OBJ_TYPE_REF) to a virtual
+ function. Resolve it to a close relative -- in the sense of static
+ type -- variant being overridden. That is close to what was written in
+ the source code. Subroutine of dump_expr. */
+
+static tree
+resolve_virtual_fun_from_obj_type_ref (tree ref)
+{
+ tree obj_type = TREE_TYPE (OBJ_TYPE_REF_OBJECT (ref));
+ HOST_WIDE_INT index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
+ tree fun = BINFO_VIRTUALS (TYPE_BINFO (TREE_TYPE (obj_type)));
+ while (index)
+ {
+ fun = TREE_CHAIN (fun);
+ index -= (TARGET_VTABLE_USES_DESCRIPTORS
+ ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
+ }
+
+ return BV_FN (fun);
+}
+
/* Print out an expression E under control of FLAGS. */
static void
{
if (t == 0)
return;
-
+
+ if (STATEMENT_CLASS_P (t))
+ {
+ pp_cxx_identifier (cxx_pp, "<statement>");
+ return;
+ }
+
switch (TREE_CODE (t))
{
case VAR_DECL:
case FUNCTION_DECL:
case TEMPLATE_DECL:
case NAMESPACE_DECL:
+ case LABEL_DECL:
case OVERLOAD:
case IDENTIFIER_NODE:
dump_decl (t, (flags & ~TFF_DECL_SPECIFIERS) | TFF_NO_FUNCTION_ARGUMENTS);
break;
case INTEGER_CST:
- case STRING_CST:
case REAL_CST:
- pp_c_constant (pp_c_base (cxx_pp), t);
+ case STRING_CST:
+ case COMPLEX_CST:
+ pp_constant (cxx_pp, t);
break;
case THROW_EXPR:
if (TREE_HAS_CONSTRUCTOR (t))
{
pp_cxx_identifier (cxx_pp, "new");
- pp_cxx_whitespace (cxx_pp);
+ pp_cxx_whitespace (cxx_pp);
dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
}
else
- dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
+ dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
break;
case AGGR_INIT_EXPR:
{
tree fn = NULL_TREE;
- if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
- fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+ if (TREE_CODE (AGGR_INIT_EXPR_FN (t)) == ADDR_EXPR)
+ fn = TREE_OPERAND (AGGR_INIT_EXPR_FN (t), 0);
if (fn && TREE_CODE (fn) == FUNCTION_DECL)
{
if (DECL_CONSTRUCTOR_P (fn))
- pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (TREE_TYPE (t)));
+ dump_type (DECL_CONTEXT (fn), flags);
else
dump_decl (fn, 0);
}
else
- dump_expr (TREE_OPERAND (t, 0), 0);
+ dump_expr (AGGR_INIT_EXPR_FN (t), 0);
}
- pp_cxx_left_paren (cxx_pp);
- if (TREE_OPERAND (t, 1))
- dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
- pp_cxx_right_paren (cxx_pp);
+ dump_aggr_init_expr_args (t, flags, true);
break;
case CALL_EXPR:
{
- tree fn = TREE_OPERAND (t, 0);
- tree args = TREE_OPERAND (t, 1);
+ tree fn = CALL_EXPR_FN (t);
+ bool skipfirst = false;
if (TREE_CODE (fn) == ADDR_EXPR)
fn = TREE_OPERAND (fn, 0);
+ /* Nobody is interested in seeing the guts of vcalls. */
+ if (TREE_CODE (fn) == OBJ_TYPE_REF)
+ fn = resolve_virtual_fun_from_obj_type_ref (fn);
+
if (TREE_TYPE (fn) != NULL_TREE && NEXT_CODE (fn) == METHOD_TYPE)
{
- tree ob = TREE_VALUE (args);
+ tree ob = CALL_EXPR_ARG (t, 0);
if (TREE_CODE (ob) == ADDR_EXPR)
{
dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
- pp_dot (cxx_pp);
+ pp_cxx_dot (cxx_pp);
}
else if (TREE_CODE (ob) != PARM_DECL
|| strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
{
dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
- pp_arrow (cxx_pp);
+ pp_cxx_arrow (cxx_pp);
}
- args = TREE_CHAIN (args);
+ skipfirst = true;
}
dump_expr (fn, flags | TFF_EXPR_IN_PARENS);
- pp_cxx_left_paren (cxx_pp);
- dump_expr_list (args, flags);
- pp_cxx_right_paren (cxx_pp);
+ dump_call_expr_args (t, flags, skipfirst);
}
break;
tree type = TREE_OPERAND (t, 1);
tree init = TREE_OPERAND (t, 2);
if (NEW_EXPR_USE_GLOBAL (t))
- pp_cxx_colon_colon (cxx_pp);
+ pp_cxx_colon_colon (cxx_pp);
pp_cxx_identifier (cxx_pp, "new");
if (TREE_OPERAND (t, 0))
{
pp_cxx_left_paren (cxx_pp);
dump_expr_list (TREE_OPERAND (t, 0), flags);
- pp_cxx_right_paren (cxx_pp);
- pp_cxx_whitespace (cxx_pp);
+ pp_cxx_right_paren (cxx_pp);
+ pp_cxx_whitespace (cxx_pp);
}
if (TREE_CODE (type) == ARRAY_REF)
type = build_cplus_array_type
(TREE_OPERAND (type, 0),
- build_index_type (fold (build2 (MINUS_EXPR, integer_type_node,
- TREE_OPERAND (type, 1),
- integer_one_node))));
+ build_index_type (fold_build2 (MINUS_EXPR, integer_type_node,
+ TREE_OPERAND (type, 1),
+ integer_one_node)));
dump_type (type, flags);
if (init)
{
dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
break;
+ case POINTER_PLUS_EXPR:
+ dump_binary_op ("+", t, flags);
+ break;
+
case INIT_EXPR:
case MODIFY_EXPR:
case PLUS_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
+ case RDIV_EXPR:
dump_binary_op ("/", t, flags);
break;
{
ob = TREE_OPERAND (ob, 0);
if (TREE_CODE (ob) != PARM_DECL
- || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
+ || (DECL_NAME (ob)
+ && strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this")))
{
dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
pp_cxx_arrow (cxx_pp);
pp_cxx_right_bracket (cxx_pp);
break;
- case CONVERT_EXPR:
- if (TREE_TYPE (t) && VOID_TYPE_P (TREE_TYPE (t)))
- {
- pp_cxx_left_paren (cxx_pp);
- dump_type (TREE_TYPE (t), flags);
- pp_cxx_right_paren (cxx_pp);
- dump_expr (TREE_OPERAND (t, 0), flags);
- }
- else
- dump_unary_op ("+", t, flags);
+ case UNARY_PLUS_EXPR:
+ dump_unary_op ("+", t, flags);
break;
case ADDR_EXPR:
|| (TREE_TYPE (t)
&& TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE))
dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
+ else if (TREE_CODE (TREE_OPERAND (t, 0)) == LABEL_DECL)
+ dump_unary_op ("&&", t, flags);
else
dump_unary_op ("&", t, flags);
break;
{
t = TREE_OPERAND (t, 0);
gcc_assert (TREE_CODE (t) == CALL_EXPR);
- dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
- pp_cxx_left_paren (cxx_pp);
- dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
- pp_cxx_right_paren (cxx_pp);
+ dump_expr (CALL_EXPR_FN (t), flags | TFF_EXPR_IN_PARENS);
+ dump_call_expr_args (t, flags, true);
}
else
{
if (TREE_CODE (next) == FUNCTION_TYPE)
{
if (flags & TFF_EXPR_IN_PARENS)
- pp_cxx_left_paren (cxx_pp);
+ pp_cxx_left_paren (cxx_pp);
pp_cxx_star (cxx_pp);
dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
if (flags & TFF_EXPR_IN_PARENS)
- pp_cxx_right_paren (cxx_pp);
+ pp_cxx_right_paren (cxx_pp);
break;
}
/* Else fall through. */
break;
case NOP_EXPR:
+ case CONVERT_EXPR:
+ case VIEW_CONVERT_EXPR:
{
tree op = TREE_OPERAND (t, 0);
-
+
if (!same_type_p (TREE_TYPE (op), TREE_TYPE (t)))
{
/* It is a cast, but we cannot tell whether it is a
dump_expr (op, flags);
break;
}
-
+
case CONSTRUCTOR:
if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
{
if (integer_zerop (idx))
{
/* A NULL pointer-to-member constant. */
- pp_cxx_left_paren (cxx_pp);
- pp_cxx_left_paren (cxx_pp);
+ pp_cxx_left_paren (cxx_pp);
+ pp_cxx_left_paren (cxx_pp);
dump_type (TREE_TYPE (t), flags);
- pp_cxx_right_paren (cxx_pp);
- pp_character (cxx_pp, '0');
- pp_cxx_right_paren (cxx_pp);
+ pp_cxx_right_paren (cxx_pp);
+ pp_character (cxx_pp, '0');
+ pp_cxx_right_paren (cxx_pp);
break;
}
else if (host_integerp (idx, 0))
if (virtuals)
{
dump_expr (BV_FN (virtuals),
- flags | TFF_EXPR_IN_PARENS);
+ flags | TFF_EXPR_IN_PARENS);
break;
}
}
}
- if (TREE_TYPE (t) && !CONSTRUCTOR_ELTS (t))
+ if (TREE_TYPE (t) && EMPTY_CONSTRUCTOR_P (t))
{
dump_type (TREE_TYPE (t), 0);
- pp_cxx_left_paren (cxx_pp);
- pp_cxx_right_paren (cxx_pp);
+ pp_cxx_left_paren (cxx_pp);
+ pp_cxx_right_paren (cxx_pp);
}
else
{
- pp_cxx_left_brace (cxx_pp);
- dump_expr_list (CONSTRUCTOR_ELTS (t), flags);
- pp_cxx_right_brace (cxx_pp);
+ pp_cxx_left_brace (cxx_pp);
+ dump_expr_init_vec (CONSTRUCTOR_ELTS (t), flags);
+ pp_cxx_right_brace (cxx_pp);
}
-
+
break;
case OFFSET_REF:
/* A::f */
dump_expr (t, flags | TFF_EXPR_IN_PARENS);
else if (BASELINK_P (t))
- dump_expr (OVL_CURRENT (BASELINK_FUNCTIONS (t)),
+ dump_expr (OVL_CURRENT (BASELINK_FUNCTIONS (t)),
flags | TFF_EXPR_IN_PARENS);
else
dump_decl (t, flags);
if (TREE_CODE (ob) == INDIRECT_REF)
{
dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
- pp_cxx_arrow (cxx_pp);
- pp_cxx_star (cxx_pp);
+ pp_cxx_arrow (cxx_pp);
+ pp_cxx_star (cxx_pp);
}
else
{
dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
- pp_cxx_dot (cxx_pp);
- pp_cxx_star (cxx_pp);
+ pp_cxx_dot (cxx_pp);
+ pp_cxx_star (cxx_pp);
}
dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
}
dump_decl (TEMPLATE_PARM_DECL (t), flags & ~TFF_DECL_SPECIFIERS);
break;
- case SCOPE_REF:
- pp_expression (cxx_pp, t);
- break;
-
case CAST_EXPR:
if (TREE_OPERAND (t, 0) == NULL_TREE
|| TREE_CHAIN (TREE_OPERAND (t, 0)))
{
pp_cxx_left_paren (cxx_pp);
dump_type (TREE_TYPE (t), flags);
- pp_cxx_right_paren (cxx_pp);
- pp_cxx_left_paren (cxx_pp);
+ pp_cxx_right_paren (cxx_pp);
+ pp_cxx_left_paren (cxx_pp);
dump_expr_list (TREE_OPERAND (t, 0), flags);
pp_cxx_right_paren (cxx_pp);
}
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
if (TREE_CODE (t) == SIZEOF_EXPR)
- pp_cxx_identifier (cxx_pp, "sizeof");
+ pp_cxx_identifier (cxx_pp, "sizeof");
else
{
gcc_assert (TREE_CODE (t) == ALIGNOF_EXPR);
if (TYPE_P (TREE_OPERAND (t, 0)))
dump_type (TREE_OPERAND (t, 0), flags);
else
- dump_expr (TREE_OPERAND (t, 0), flags);
+ dump_expr (TREE_OPERAND (t, 0), flags);
pp_cxx_right_paren (cxx_pp);
break;
dump_decl (t, flags);
break;
+ case BIND_EXPR:
case STMT_EXPR:
+ case STATEMENT_LIST:
/* We don't yet have a way of dumping statements in a
human-readable format. */
pp_string (cxx_pp, "({...})");
break;
- case BIND_EXPR:
- pp_cxx_left_brace (cxx_pp);
- dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS);
- pp_cxx_right_brace (cxx_pp);
- break;
-
case LOOP_EXPR:
pp_string (cxx_pp, "while (1) { ");
dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
dump_expr (TREE_OPERAND (t, 0), flags);
break;
+ case ARGUMENT_PACK_SELECT:
+ dump_template_argument (ARGUMENT_PACK_SELECT_FROM_PACK (t), flags);
+ break;
+
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ case REAL_TYPE:
+ case VOID_TYPE:
+ case BOOLEAN_TYPE:
+ case INTEGER_TYPE:
+ case COMPLEX_TYPE:
+ case VECTOR_TYPE:
+ pp_type_specifier_seq (cxx_pp, t);
+ break;
+
+ case TYPENAME_TYPE:
+ /* We get here when we want to print a dependent type as an
+ id-expression, without any disambiguator decoration. */
+ pp_id_expression (cxx_pp, t);
+ break;
+
+ case TEMPLATE_TYPE_PARM:
+ case BOUND_TEMPLATE_TEMPLATE_PARM:
+ dump_type (t, flags);
+ break;
+
+ case TRAIT_EXPR:
+ pp_cxx_trait_expression (cxx_pp, t);
+ break;
+
+ case VA_ARG_EXPR:
+ pp_cxx_va_arg_expression (cxx_pp, t);
+ break;
+
+ case OFFSETOF_EXPR:
+ pp_cxx_offsetof_expression (cxx_pp, t);
+ break;
+
+ case SCOPE_REF:
+ case EXPR_PACK_EXPANSION:
+ case TYPEID_EXPR:
+ case MEMBER_REF:
+ case DOTSTAR_EXPR:
+ case DELETE_EXPR:
+ case VEC_DELETE_EXPR:
+ case MODOP_EXPR:
+ case ABS_EXPR:
+ case VECTOR_CST:
+ pp_expression (cxx_pp, t);
+ break;
+
+ case OBJ_TYPE_REF:
+ dump_expr (resolve_virtual_fun_from_obj_type_ref (t), flags);
+ break;
+
/* This list is incomplete, but should suffice for now.
It is very important that `sorry' does not call
`report_error_function'. That could cause an infinite loop. */
pp_base (cxx_pp)->padding = pp_none;
pp_indentation (cxx_pp) = 0;
pp_needs_newline (cxx_pp) = false;
- cxx_pp->enclosing_scope = 0;
+ cxx_pp->enclosing_scope = current_function_decl;
}
return pp_formatted_text (cxx_pp);
}
-const char *
-context_as_string (tree context, int flags)
-{
- reinit_cxx_pp ();
- dump_scope (context, flags);
- return pp_formatted_text (cxx_pp);
-}
-
/* Generate the three forms of printable names for cxx_printable_name. */
const char *
return pp_formatted_text (cxx_pp);
}
+/* Return the location of a tree passed to %+ formats. */
+
static location_t
location_of (tree t)
{
t = TYPE_MAIN_DECL (t);
else if (TREE_CODE (t) == OVERLOAD)
t = OVL_FUNCTION (t);
-
+
return DECL_SOURCE_LOCATION (t);
}
{
int flags;
- flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS;
+ flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS
+ | TFF_TEMPLATE_HEADER;
if (verbose)
flags |= TFF_FUNCTION_DEFAULT_ARGUMENTS;
reinit_cxx_pp ();
return "Java";
default:
- abort ();
- return 0;
+ gcc_unreachable ();
}
+ return NULL;
}
/* Return the proper printed version of a parameter to a C++ function. */
/* Langhook for print_error_function. */
void
-cxx_print_error_function (diagnostic_context *context, const char *file)
+cxx_print_error_function (diagnostic_context *context, const char *file,
+ diagnostic_info *diagnostic)
{
- lhd_print_error_function (context, file);
+ lhd_print_error_function (context, file, diagnostic);
pp_base_set_prefix (context->printer, file);
maybe_print_instantiation_context (context);
}
static void
cp_diagnostic_starter (diagnostic_context *context,
- diagnostic_info *diagnostic)
+ diagnostic_info *diagnostic)
{
diagnostic_report_current_module (context);
cp_print_error_function (context, diagnostic);
static void
cp_diagnostic_finalizer (diagnostic_context *context,
- diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
+ diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
{
pp_base_destroy_prefix (context->printer);
}
a diagnostic message. Called from cp_diagnostic_starter. */
static void
cp_print_error_function (diagnostic_context *context,
- diagnostic_info *diagnostic)
+ diagnostic_info *diagnostic)
{
- if (diagnostic_last_function_changed (context))
+ if (diagnostic_last_function_changed (context, diagnostic))
{
const char *old_prefix = context->printer->prefix;
const char *file = LOCATION_FILE (diagnostic->location);
- char *new_prefix = file ? file_name_as_prefix (file) : NULL;
+ tree abstract_origin = diagnostic->abstract_origin;
+ char *new_prefix = (file && abstract_origin == NULL)
+ ? file_name_as_prefix (file) : NULL;
pp_base_set_prefix (context->printer, new_prefix);
if (current_function_decl == NULL)
- pp_base_string (context->printer, "At global scope:");
+ pp_base_string (context->printer, "At global scope:");
else
- pp_printf (context->printer, "In %s `%s':",
- function_category (current_function_decl),
- cxx_printable_name (current_function_decl, 2));
+ {
+ tree fndecl, ao;
+
+ if (abstract_origin)
+ {
+ ao = BLOCK_ABSTRACT_ORIGIN (abstract_origin);
+ while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao))
+ ao = BLOCK_ABSTRACT_ORIGIN (ao);
+ gcc_assert (TREE_CODE (ao) == FUNCTION_DECL);
+ fndecl = ao;
+ }
+ else
+ fndecl = current_function_decl;
+
+ pp_printf (context->printer, "In %s %qs",
+ function_category (fndecl),
+ cxx_printable_name (fndecl, 2));
+
+ while (abstract_origin)
+ {
+ location_t *locus;
+ tree block = abstract_origin;
+
+ locus = &BLOCK_SOURCE_LOCATION (block);
+ fndecl = NULL;
+ block = BLOCK_SUPERCONTEXT (block);
+ while (block && TREE_CODE (block) == BLOCK
+ && BLOCK_ABSTRACT_ORIGIN (block))
+ {
+ ao = BLOCK_ABSTRACT_ORIGIN (block);
+
+ while (TREE_CODE (ao) == BLOCK
+ && BLOCK_ABSTRACT_ORIGIN (ao)
+ && BLOCK_ABSTRACT_ORIGIN (ao) != ao)
+ ao = BLOCK_ABSTRACT_ORIGIN (ao);
+
+ if (TREE_CODE (ao) == FUNCTION_DECL)
+ {
+ fndecl = ao;
+ break;
+ }
+ else if (TREE_CODE (ao) != BLOCK)
+ break;
+
+ block = BLOCK_SUPERCONTEXT (block);
+ }
+ if (fndecl)
+ abstract_origin = block;
+ else
+ {
+ while (block && TREE_CODE (block) == BLOCK)
+ block = BLOCK_SUPERCONTEXT (block);
+
+ if (TREE_CODE (block) == FUNCTION_DECL)
+ fndecl = block;
+ abstract_origin = NULL;
+ }
+ if (fndecl)
+ {
+ expanded_location s = expand_location (*locus);
+ pp_base_character (context->printer, ',');
+ pp_base_newline (context->printer);
+ if (s.file != NULL)
+ {
+#ifdef USE_MAPPED_LOCATION
+ if (flag_show_column && s.column != 0)
+ pp_printf (context->printer,
+ " inlined from %qs at %s:%d:%d",
+ cxx_printable_name (fndecl, 2),
+ s.file, s.line, s.column);
+ else
+#endif
+ pp_printf (context->printer,
+ " inlined from %qs at %s:%d",
+ cxx_printable_name (fndecl, 2),
+ s.file, s.line);
+
+ }
+ else
+ pp_printf (context->printer, " inlined from %qs",
+ cxx_printable_name (fndecl, 2));
+ }
+ }
+ pp_base_character (context->printer, ':');
+ }
pp_base_newline (context->printer);
- diagnostic_set_last_function (context);
+ diagnostic_set_last_function (context, diagnostic);
pp_base_destroy_prefix (context->printer);
context->printer->prefix = old_prefix;
}
if (DECL_FUNCTION_MEMBER_P (fn))
{
if (DECL_STATIC_FUNCTION_P (fn))
- return "static member function";
+ return "static member function";
else if (DECL_COPY_CONSTRUCTOR_P (fn))
- return "copy constructor";
+ return "copy constructor";
else if (DECL_CONSTRUCTOR_P (fn))
- return "constructor";
+ return "constructor";
else if (DECL_DESTRUCTOR_P (fn))
- return "destructor";
+ return "destructor";
else
- return "member function";
+ return "member function";
}
else
return "function";
static void
print_instantiation_full_context (diagnostic_context *context)
{
- tree p = current_instantiation ();
+ struct tinst_level *p = current_instantiation ();
location_t location = input_location;
-
+
if (p)
{
- if (current_function_decl != TINST_DECL (p)
+ if (current_function_decl != p->decl
&& current_function_decl != NULL_TREE)
/* We can get here during the processing of some synthesized
- method. Then, TINST_DECL (p) will be the function that's causing
+ method. Then, P->DECL will be the function that's causing
the synthesis. */
;
else
{
- if (current_function_decl == TINST_DECL (p))
- /* Avoid redundancy with the the "In function" line. */;
+ if (current_function_decl == p->decl)
+ /* Avoid redundancy with the "In function" line. */;
else
pp_verbatim (context->printer,
- "%s: In instantiation of `%s':\n",
+ "%s: In instantiation of %qs:\n",
LOCATION_FILE (location),
- decl_as_string (TINST_DECL (p),
- TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
+ decl_as_string (p->decl,
+ TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
- location = TINST_LOCATION (p);
- p = TREE_CHAIN (p);
+ location = p->locus;
+ p = p->next;
}
}
/* Same as above but less verbose. */
static void
print_instantiation_partial_context (diagnostic_context *context,
- tree t, location_t loc)
+ struct tinst_level *t, location_t loc)
{
expanded_location xloc;
- for (; ; t = TREE_CHAIN (t))
+ for (; ; t = t->next)
{
xloc = expand_location (loc);
- if (t == NULL_TREE)
+ if (t == NULL)
break;
- pp_verbatim (context->printer, "%s:%d: instantiated from `%s'\n",
- xloc.file, xloc.line,
- decl_as_string (TINST_DECL (t),
- TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
- loc = TINST_LOCATION (t);
+ pp_verbatim (context->printer, "%s:%d: instantiated from %qs\n",
+ xloc.file, xloc.line,
+ decl_as_string (t->decl,
+ TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
+ loc = t->locus;
}
- pp_verbatim (context->printer, "%s:%d: instantiated from here\n",
- xloc.file, xloc.line);
+ pp_verbatim (context->printer, "%s:%d: instantiated from here",
+ xloc.file, xloc.line);
+ pp_base_newline (context->printer);
}
/* Called from cp_thing to print the template context for an error. */
%T type.
%V cv-qualifier. */
static bool
-cp_printer (pretty_printer *pp, text_info *text)
+cp_printer (pretty_printer *pp, text_info *text, const char *spec,
+ int precision, bool wide, bool set_locus, bool verbose)
{
- int verbose = 0;
const char *result;
-#define next_tree va_arg (*text->args_ptr, tree)
+ tree t = NULL;
+#define next_tree (t = va_arg (*text->args_ptr, tree))
#define next_tcode va_arg (*text->args_ptr, enum tree_code)
#define next_lang va_arg (*text->args_ptr, enum languages)
#define next_int va_arg (*text->args_ptr, int)
- if (*text->format_spec == '+')
- ++text->format_spec;
- if (*text->format_spec == '#')
- {
- verbose = 1;
- ++text->format_spec;
- }
+ if (precision != 0 || wide)
+ return false;
+
+ if (text->locus == NULL)
+ set_locus = false;
- switch (*text->format_spec)
+ switch (*spec)
{
case 'A': result = args_to_string (next_tree, verbose); break;
- case 'C': result = code_to_string (next_tcode); break;
- case 'D': result = decl_to_string (next_tree, verbose); break;
- case 'E': result = expr_to_string (next_tree); break;
+ case 'C': result = code_to_string (next_tcode); break;
+ case 'D':
+ {
+ tree temp = next_tree;
+ if (DECL_P (temp)
+ && DECL_DEBUG_EXPR_IS_FROM (temp) && DECL_DEBUG_EXPR (temp))
+ {
+ temp = DECL_DEBUG_EXPR (temp);
+ if (!DECL_P (temp))
+ {
+ result = expr_to_string (temp);
+ break;
+ }
+ }
+ result = decl_to_string (temp, verbose);
+ }
+ break;
+ case 'E': result = expr_to_string (next_tree); break;
case 'F': result = fndecl_to_string (next_tree, verbose); break;
- case 'L': result = language_to_string (next_lang); break;
- case 'O': result = op_to_string (next_tcode); break;
- case 'P': result = parm_to_string (next_int); break;
- case 'Q': result = assop_to_string (next_tcode); break;
+ case 'L': result = language_to_string (next_lang); break;
+ case 'O': result = op_to_string (next_tcode); break;
+ case 'P': result = parm_to_string (next_int); break;
+ case 'Q': result = assop_to_string (next_tcode); break;
case 'T': result = type_to_string (next_tree, verbose); break;
case 'V': result = cv_to_string (next_tree, verbose); break;
-
+
default:
return false;
}
pp_base_string (pp, result);
+ if (set_locus && t != NULL)
+ *text->locus = location_of (t);
return true;
#undef next_tree
#undef next_tcode
#undef next_lang
#undef next_int
}
-
-/* These are temporary wrapper functions which handle the historic
- behavior of cp_*_at. */
-
-static tree
-locate_error (const char *msgid, va_list ap)
-{
- tree here = 0, t;
- int plus = 0;
- const char *f;
-
- for (f = msgid; *f; f++)
- {
- plus = 0;
- if (*f == '%')
- {
- f++;
- if (*f == '+')
- f++, plus = 1;
- if (*f == '#')
- f++;
-
- switch (*f)
- {
- /* Just ignore these possibilities. */
- case '%': break;
- case 'P':
- case 'd': (void) va_arg (ap, int); break;
- case 's': (void) va_arg (ap, char *); break;
- case 'L': (void) va_arg (ap, enum languages); break;
- case 'C':
- case 'O':
- case 'Q': (void) va_arg (ap, enum tree_code); break;
-
- /* These take a tree, which may be where the error is
- located. */
- case 'A':
- case 'D':
- case 'E':
- case 'F':
- case 'T':
- case 'V':
- t = va_arg (ap, tree);
- if (!here || plus)
- here = t;
- break;
-
- default:
- errorcount = 0; /* damn ICE suppression */
- internal_error ("unexpected letter `%c' in locate_error\n", *f);
- }
- }
- }
-
- if (here == 0)
- here = va_arg (ap, tree);
-
- return here;
-}
-
-
-void
-cp_error_at (const char *msgid, ...)
-{
- tree here;
- diagnostic_info diagnostic;
- va_list ap;
-
- va_start (ap, msgid);
- here = locate_error (msgid, ap);
- va_end (ap);
-
- va_start (ap, msgid);
- diagnostic_set_info (&diagnostic, msgid, &ap,
- location_of (here), DK_ERROR);
- report_diagnostic (&diagnostic);
- va_end (ap);
-}
+\f
+/* Callback from cpp_error for PFILE to print diagnostics arising from
+ interpreting strings. The diagnostic is of type LEVEL; MSG is the
+ translated message and AP the arguments. */
void
-cp_warning_at (const char *msgid, ...)
+cp_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
+ const char *msg, va_list *ap)
{
- tree here;
diagnostic_info diagnostic;
- va_list ap;
-
- va_start (ap, msgid);
- here = locate_error (msgid, ap);
- va_end (ap);
-
- va_start (ap, msgid);
- diagnostic_set_info (&diagnostic, msgid, &ap,
- location_of (here), DK_WARNING);
+ diagnostic_t dlevel;
+ switch (level)
+ {
+ case CPP_DL_WARNING:
+ case CPP_DL_WARNING_SYSHDR:
+ dlevel = DK_WARNING;
+ break;
+ case CPP_DL_PEDWARN:
+ dlevel = pedantic_error_kind ();
+ break;
+ case CPP_DL_ERROR:
+ dlevel = DK_ERROR;
+ break;
+ case CPP_DL_ICE:
+ dlevel = DK_ICE;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ diagnostic_set_info_translated (&diagnostic, msg, ap,
+ input_location, dlevel);
report_diagnostic (&diagnostic);
- va_end (ap);
}
+/* Warn about the use of variadic templates when appropriate. */
void
-cp_pedwarn_at (const char *msgid, ...)
+maybe_warn_variadic_templates (void)
{
- tree here;
- diagnostic_info diagnostic;
- va_list ap;
-
- va_start (ap, msgid);
- here = locate_error (msgid, ap);
- va_end (ap);
-
- va_start (ap, msgid);
- diagnostic_set_info (&diagnostic, msgid, &ap,
- location_of (here), pedantic_error_kind());
- report_diagnostic (&diagnostic);
- va_end (ap);
+ if ((cxx_dialect == cxx98) && !in_system_header)
+ /* We really want to suppress this warning in system headers,
+ because libstdc++ uses variadic templates even when we aren't
+ in C++0x mode. */
+ pedwarn ("ISO C++ does not include variadic templates");
}