/* Call-backs for C++ error reporting.
This code is non-reentrant.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002,
- 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 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
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
break;
case TYPE_ARGUMENT_PACK:
- {
- tree args = ARGUMENT_PACK_ARGS (t);
- int i;
- for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
- {
- if (i)
- pp_separate_with_comma (cxx_pp);
- dump_type (TREE_VEC_ELT (args, i), flags);
- }
- }
+ dump_template_argument (t, flags);
break;
case DECLTYPE_TYPE:
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 VECTOR_TYPE:
case TYPEOF_TYPE:
case DECLTYPE_TYPE:
+ case TYPE_PACK_EXPANSION:
break;
default:
|| 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;
break;
case UNBOUND_CLASS_TEMPLATE:
+ case TYPE_PACK_EXPANSION:
+ case TREE_BINFO:
dump_type (t, flags);
break;
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)
pp_cxx_identifier (cxx_pp, "...");
break;
}
- if (ARGUMENT_PACK_P (TREE_VALUE (parmtypes)))
- {
- tree types = ARGUMENT_PACK_ARGS (TREE_VALUE (parmtypes));
- int i, len = TREE_VEC_LENGTH (types);
- first = 1;
- for (i = 0; i < len; ++i)
- {
- if (!first)
- pp_separate_with_comma (cxx_pp);
- first = 0;
-
- dump_type (TREE_VEC_ELT (types, i), flags);
- }
- }
- else
- dump_type (TREE_VALUE (parmtypes), flags);
+
+ dump_type (TREE_VALUE (parmtypes), flags);
if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes))
{
if (t == 0)
return;
+ if (STATEMENT_CLASS_P (t))
+ {
+ pp_cxx_identifier (cxx_pp, "<statement>");
+ return;
+ }
+
switch (TREE_CODE (t))
{
case VAR_DECL:
case NOP_EXPR:
case CONVERT_EXPR:
+ case VIEW_CONVERT_EXPR:
{
tree op = TREE_OPERAND (t, 0);
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 EXPR_PACK_EXPANSION:
- dump_expr (PACK_EXPANSION_PATTERN (t), flags);
- pp_cxx_identifier (cxx_pp, "...");
+ case ARGUMENT_PACK_SELECT:
+ dump_template_argument (ARGUMENT_PACK_SELECT_FROM_PACK (t), flags);
break;
case RECORD_TYPE:
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:
- pp_cxx_typeid_expression (cxx_pp, t);
+ 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.
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;
}
/* 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;
}