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. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
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
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:
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 (tmplate)
/* Else fall through. */
case FIELD_DECL:
case PARM_DECL:
- case ALIAS_DECL:
dump_simple_decl (t, TREE_TYPE (t), flags);
break;
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;
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);
}
}
}
+/* 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));
+ 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);
+
+ return BV_FN (fun);
+}
+
/* Print out an expression E under control of FLAGS. */
static void
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:
+ pp_constant (cxx_pp, t);
break;
case THROW_EXPR:
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_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;
}
}
}
- 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);
}
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. */
TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
loc = TINST_LOCATION (t);
}
- 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;
}
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);
-}
-
-void
-cp_warning_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,
- location_of (here), DK_WARNING);
- 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_pedwarn_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), pedantic_error_kind());
+ 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);
}