/* 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.
+ 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, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, 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 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
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)
+ 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 (TREE_VEC_ELT (args, i), flags);
+
+ 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 (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));
}
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_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. */
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))
+ && (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 (! (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
pp_cxx_whitespace (cxx_pp);
pp_cxx_left_paren (cxx_pp);
}
- pp_character (cxx_pp, "&*"[TREE_CODE (t) == POINTER_TYPE]);
+ 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);
}
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;
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),
+ 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)),
+ dump_expr (fold_build2 (PLUS_EXPR, dtype, max,
+ build_int_cst (dtype, 1)),
flags & ~TFF_EXPR_IN_PARENS);
}
pp_cxx_right_bracket (cxx_pp);
case COMPLEX_TYPE:
case VECTOR_TYPE:
case TYPEOF_TYPE:
+ case DECLTYPE_TYPE:
+ case TYPE_PACK_EXPANSION:
break;
default:
{
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
{
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_identifier (cxx_pp, "class");
+
+ /* 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;
/* Else fall through. */
case FIELD_DECL:
case PARM_DECL:
- case ALIAS_DECL:
dump_simple_decl (t, TREE_TYPE (t), flags);
break;
pp_cxx_declaration (cxx_pp, t);
else
{
- dump_scope (CP_DECL_CONTEXT (t), flags);
+ 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
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;
pp_type_id (cxx_pp, t);
break;
+ case UNBOUND_CLASS_TEMPLATE:
+ case TYPE_PACK_EXPANSION:
+ case TREE_BINFO:
+ dump_type (t, flags);
+ break;
+
default:
pp_unsupported_tree (cxx_pp, t);
/* Fall through to error. */
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)
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);
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);
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;
pp_cxx_identifier (cxx_pp, "...");
break;
}
+
dump_type (TREE_VALUE (parmtypes), flags);
if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes))
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);
}
{
tree arg = TREE_VEC_ELT (args, ix);
- if (ix)
- pp_separate_with_comma (cxx_pp);
-
- if (!arg)
- pp_identifier (cxx_pp, "<template parameter error>");
- else
- dump_template_argument (arg, flags);
- }
+ /* 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)
+ pp_identifier (cxx_pp, "<template parameter error>");
+ else
+ dump_template_argument (arg, flags);
+ }
}
else if (primary)
{
for (ix = 0; ix != len; ix++)
{
- tree parm = TREE_VALUE (TREE_VEC_ELT (parms, ix));
+ tree parm;
+
+ if (TREE_VEC_ELT (parms, ix) == error_mark_node)
+ {
+ pp_identifier (cxx_pp, "<template parameter error>");
+ continue;
+ }
+
+ parm = TREE_VALUE (TREE_VEC_ELT (parms, ix));
if (ix)
pp_separate_with_comma (cxx_pp);
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 STRING_CST:
- if (PAREN_STRING_LITERAL_P (t))
- pp_cxx_left_paren (cxx_pp);
- pp_c_constant (pp_c_base (cxx_pp), t);
- if (PAREN_STRING_LITERAL_P (t))
- pp_cxx_right_paren (cxx_pp);
- break;
-
case INTEGER_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:
{
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)
{
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;
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:
|| (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
{
case NOP_EXPR:
case CONVERT_EXPR:
+ case VIEW_CONVERT_EXPR:
{
tree op = TREE_OPERAND (t, 0);
}
}
}
- 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);
else
{
pp_cxx_left_brace (cxx_pp);
- dump_expr_list (CONSTRUCTOR_ELTS (t), flags);
+ dump_expr_init_vec (CONSTRUCTOR_ELTS (t), flags);
pp_cxx_right_brace (cxx_pp);
}
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)))
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);
}
+/* Return the location of a tree passed to %+ formats. */
+
static location_t
location_of (tree 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 ();
default:
gcc_unreachable ();
}
- return 0;
+ 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);
}
cp_print_error_function (diagnostic_context *context,
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:");
else
- pp_printf (context->printer, "In %s %qs:",
- 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;
}
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))
+ if (current_function_decl == p->decl)
/* Avoid redundancy with the "In function" line. */;
else
pp_verbatim (context->printer,
"%s: In instantiation of %qs:\n",
LOCATION_FILE (location),
- decl_as_string (TINST_DECL (p),
+ 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 %qs\n",
xloc.file, xloc.line,
- decl_as_string (TINST_DECL (t),
+ decl_as_string (t->decl,
TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
- loc = TINST_LOCATION (t);
+ loc = t->locus;
}
- pp_verbatim (context->printer, "%s:%d: instantiated from here\n",
+ 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 '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;
}
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 *gmsgid, va_list ap)
-{
- tree here = 0, t;
- int plus = 0;
- const char *f;
-
- for (f = gmsgid; *f; f++)
- {
- plus = 0;
- if (*f == '%')
- {
- if (*++f == 'q')
- ++f; /* ignore quoting flag. */
-
- 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 %qc in locate_error\n", *f);
- }
- }
- }
-
- if (here == 0)
- here = va_arg (ap, tree);
-
- return here;
-}
-
-
-void
-cp_error_at (const char *gmsgid, ...)
-{
- tree here;
- diagnostic_info diagnostic;
- va_list ap;
-
- va_start (ap, gmsgid);
- here = locate_error (gmsgid, ap);
- va_end (ap);
-
- va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap,
- input_location, DK_ERROR);
- cp_diagnostic_starter (global_dc, &diagnostic);
- diagnostic_set_info (&diagnostic, gmsgid, &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 *gmsgid, ...)
+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, gmsgid);
- here = locate_error (gmsgid, ap);
- va_end (ap);
-
- va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &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 *gmsgid, ...)
+maybe_warn_variadic_templates (void)
{
- tree here;
- diagnostic_info diagnostic;
- va_list ap;
-
- va_start (ap, gmsgid);
- here = locate_error (gmsgid, ap);
- va_end (ap);
-
- va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &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");
}