/* 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, 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003,
+ 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
-#include "real.h"
-#include "toplev.h"
#include "flags.h"
#include "diagnostic.h"
+#include "tree-diagnostic.h"
#include "langhooks-def.h"
#include "intl.h"
#include "cxx-pretty-print.h"
+#include "tree-pretty-print.h"
#include "pointer-set.h"
+#include "c-family/c-objc.h"
#define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
+#define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';')
/* The global buffer where we dump everything. It is there only for
transitional purpose. It is expected, in the near future, to be
static const char *parm_to_string (int);
static const char *type_to_string (tree, int);
+static void dump_alias_template_specialization (tree, int);
static void dump_type (tree, int);
static void dump_typename (tree, int);
static void dump_simple_decl (tree, tree, int);
static void dump_template_parms (tree, int, int);
static int get_non_default_template_args_count (tree, int);
static const char *function_category (tree);
+static void maybe_print_constexpr_context (diagnostic_context *);
static void maybe_print_instantiation_context (diagnostic_context *);
static void print_instantiation_full_context (diagnostic_context *);
static void print_instantiation_partial_context (diagnostic_context *,
static bool cp_printer (pretty_printer *, text_info *, const char *,
int, bool, bool, bool);
-static location_t location_of (tree);
void
init_error (void)
static void
dump_scope (tree scope, int flags)
{
- int f = ~TFF_RETURN_TYPE & (flags & (TFF_SCOPE | TFF_CHASE_TYPEDEF));
+ int f = flags & (TFF_SCOPE | TFF_CHASE_TYPEDEF);
if (scope == NULL_TREE)
return;
dump_template_argument (tree arg, int flags)
{
if (ARGUMENT_PACK_P (arg))
- dump_template_argument_list (ARGUMENT_PACK_ARGS (arg), flags);
+ dump_template_argument_list (ARGUMENT_PACK_ARGS (arg),
+ /* No default args in argument packs. */
+ flags|TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS);
else if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL)
dump_type (arg, flags & ~TFF_CLASS_KEY_OR_ENUM);
else
static void
dump_template_bindings (tree parms, tree args, VEC(tree,gc)* typenames)
{
- int need_comma = 0;
+ bool need_semicolon = false;
int i;
tree t;
if (lvl_args && NUM_TMPL_ARGS (lvl_args) > arg_idx)
arg = TREE_VEC_ELT (lvl_args, arg_idx);
- if (need_comma)
- pp_separate_with_comma (cxx_pp);
+ if (need_semicolon)
+ pp_separate_with_semicolon (cxx_pp);
dump_template_parameter (TREE_VEC_ELT (p, i), TFF_PLAIN_IDENTIFIER);
pp_cxx_whitespace (cxx_pp);
pp_equal (cxx_pp);
pp_string (cxx_pp, M_("<missing>"));
++arg_idx;
- need_comma = 1;
+ need_semicolon = true;
}
parms = TREE_CHAIN (parms);
}
- for (i = 0; VEC_iterate (tree, typenames, i, t); ++i)
+ /* Don't bother with typenames for a partial instantiation. */
+ if (VEC_empty (tree, typenames) || uses_template_parms (args))
+ return;
+
+ FOR_EACH_VEC_ELT (tree, typenames, i, t)
{
- if (need_comma)
- pp_separate_with_comma (cxx_pp);
+ if (need_semicolon)
+ pp_separate_with_semicolon (cxx_pp);
dump_type (t, TFF_PLAIN_IDENTIFIER);
pp_cxx_whitespace (cxx_pp);
pp_equal (cxx_pp);
pp_cxx_whitespace (cxx_pp);
+ push_deferring_access_checks (dk_no_check);
t = tsubst (t, args, tf_none, NULL_TREE);
+ pop_deferring_access_checks ();
/* Strip typedefs. We can't just use TFF_CHASE_TYPEDEF because
pp_simple_type_specifier doesn't know about it. */
t = strip_typedefs (t);
}
}
+/* Dump a human-readable equivalent of the alias template
+ specialization of T. */
+
+static void
+dump_alias_template_specialization (tree t, int flags)
+{
+ tree name;
+
+ gcc_assert (alias_template_specialization_p (t));
+
+ if (!(flags & TFF_UNQUALIFIED_NAME))
+ dump_scope (CP_DECL_CONTEXT (TYPE_NAME (t)), flags);
+ name = TYPE_IDENTIFIER (t);
+ pp_cxx_tree_identifier (cxx_pp, name);
+ dump_template_parms (TYPE_TEMPLATE_INFO (t),
+ /*primary=*/false,
+ flags & ~TFF_TEMPLATE_HEADER);
+}
+
/* Dump a human-readable equivalent of TYPE. FLAGS controls the
format. */
if (t == NULL_TREE)
return;
+ /* Don't print e.g. "struct mytypedef". */
+ if (TYPE_P (t) && typedef_variant_p (t))
+ {
+ tree decl = TYPE_NAME (t);
+ if ((flags & TFF_CHASE_TYPEDEF)
+ || DECL_SELF_REFERENCE_P (decl)
+ || (!flag_pretty_templates
+ && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)))
+ t = strip_typedefs (t);
+ else if (alias_template_specialization_p (t))
+ {
+ dump_alias_template_specialization (t, flags);
+ return;
+ }
+ else if (same_type_p (t, TREE_TYPE (decl)))
+ t = decl;
+ else
+ {
+ pp_cxx_cv_qualifier_seq (cxx_pp, t);
+ pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t));
+ return;
+ }
+ }
+
if (TYPE_PTRMEMFUNC_P (t))
goto offset_type;
switch (TREE_CODE (t))
{
- case UNKNOWN_TYPE:
+ case LANG_TYPE:
if (t == init_list_type_node)
pp_string (cxx_pp, M_("<brace-enclosed initializer list>"));
- else
+ else if (t == unknown_type_node)
pp_string (cxx_pp, M_("<unresolved overloaded function type>"));
+ else
+ {
+ pp_cxx_cv_qualifier_seq (cxx_pp, t);
+ pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t));
+ }
break;
case TREE_LIST:
pp_cxx_right_paren (cxx_pp);
break;
+ case UNDERLYING_TYPE:
+ pp_cxx_ws_string (cxx_pp, "__underlying_type");
+ pp_cxx_whitespace (cxx_pp);
+ pp_cxx_left_paren (cxx_pp);
+ dump_expr (UNDERLYING_TYPE_TYPE (t), flags & ~TFF_EXPR_IN_PARENS);
+ pp_cxx_right_paren (cxx_pp);
+ break;
+
case TYPE_PACK_EXPANSION:
dump_type (PACK_EXPANSION_PATTERN (t), flags);
pp_cxx_ws_string (cxx_pp, "...");
pp_cxx_right_paren (cxx_pp);
break;
+ case NULLPTR_TYPE:
+ pp_string (cxx_pp, "std::nullptr_t");
+ break;
+
default:
pp_unsupported_tree (cxx_pp, t);
/* Fall through to error. */
if (name)
{
- typdef = !DECL_ARTIFICIAL (name);
+ typdef = (!DECL_ARTIFICIAL (name)
+ /* An alias specialization is not considered to be a
+ typedef. */
+ && !alias_template_specialization_p (t));
if ((typdef
&& ((flags & TFF_CHASE_TYPEDEF)
{
/* Because the template names are mangled, we have to locate
the most general template, and use that name. */
- tree tpl = CLASSTYPE_TI_TEMPLATE (t);
+ tree tpl = TYPE_TI_TEMPLATE (t);
while (DECL_TEMPLATE_INFO (tpl))
tpl = DECL_TI_TEMPLATE (tpl);
{
pp_cxx_whitespace (cxx_pp);
pp_cxx_left_paren (cxx_pp);
+ pp_c_attributes_display (pp_c_base (cxx_pp),
+ TYPE_ATTRIBUTES (sub));
}
if (TREE_CODE (t) == POINTER_TYPE)
pp_character(cxx_pp, '*');
case TYPE_DECL:
case TREE_VEC:
case UNION_TYPE:
- case UNKNOWN_TYPE:
+ case LANG_TYPE:
case VOID_TYPE:
case TYPENAME_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
case TYPEOF_TYPE:
+ case UNDERLYING_TYPE:
case DECLTYPE_TYPE:
case TYPE_PACK_EXPANSION:
case FIXED_POINT_TYPE:
+ case NULLPTR_TYPE:
dump_type (t, flags);
pp_base (cxx_pp)->padding = pp_before;
break;
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, class_of_this_parm (t));
else
pp_cxx_cv_qualifier_seq (cxx_pp, t);
dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags);
case TYPE_DECL:
case TREE_VEC:
case UNION_TYPE:
- case UNKNOWN_TYPE:
+ case LANG_TYPE:
case VOID_TYPE:
case TYPENAME_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
case TYPEOF_TYPE:
+ case UNDERLYING_TYPE:
case DECLTYPE_TYPE:
case TYPE_PACK_EXPANSION:
case FIXED_POINT_TYPE:
+ case NULLPTR_TYPE:
break;
default:
{
if (flags & TFF_DECL_SPECIFIERS)
{
+ if (TREE_CODE (t) == VAR_DECL
+ && DECL_DECLARED_CONSTEXPR_P (t))
+ pp_cxx_ws_string (cxx_pp, "constexpr");
dump_type_prefix (type, flags & ~TFF_UNQUALIFIED_NAME);
pp_maybe_space (cxx_pp);
}
if (! (flags & TFF_UNQUALIFIED_NAME)
+ && TREE_CODE (t) != PARM_DECL
&& (!DECL_INITIAL (t)
|| TREE_CODE (DECL_INITIAL (t)) != TEMPLATE_PARM_INDEX))
dump_scope (CP_DECL_CONTEXT (t), flags);
if (t == NULL_TREE)
return;
+ /* If doing Objective-C++, give Objective-C a chance to demangle
+ Objective-C method names. */
+ if (c_dialect_objc ())
+ {
+ const char *demangled = objc_maybe_printable_name (t, flags);
+ if (demangled)
+ {
+ pp_string (cxx_pp, demangled);
+ return;
+ }
+ }
+
switch (TREE_CODE (t))
{
case TYPE_DECL:
dump_type (TREE_TYPE (t), flags);
break;
}
+ if (TYPE_DECL_ALIAS_P (t)
+ && (flags & TFF_DECL_SPECIFIERS
+ || flags & TFF_CLASS_KEY_OR_ENUM))
+ {
+ pp_cxx_ws_string (cxx_pp, "using");
+ dump_decl (DECL_NAME (t), flags);
+ pp_cxx_whitespace (cxx_pp);
+ pp_cxx_ws_string (cxx_pp, "=");
+ pp_cxx_whitespace (cxx_pp);
+ dump_type (DECL_ORIGINAL_TYPE (t), flags);
+ break;
+ }
if ((flags & TFF_DECL_SPECIFIERS)
&& !DECL_SELF_REFERENCE_P (t))
pp_cxx_ws_string (cxx_pp, "typedef");
dump_scope (CP_DECL_CONTEXT (t), flags);
flags &= ~TFF_UNQUALIFIED_NAME;
if (DECL_NAME (t) == NULL_TREE)
- pp_string (cxx_pp, M_("<unnamed>"));
+ pp_cxx_ws_string (cxx_pp, M_("{anonymous}"));
else
pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t));
}
dump_type (DECL_CONTEXT (t), flags);
pp_cxx_colon_colon (cxx_pp);
}
- else if (DECL_CONTEXT (t))
+ else if (!DECL_FILE_SCOPE_P (t))
{
dump_decl (DECL_CONTEXT (t), flags);
pp_cxx_colon_colon (cxx_pp);
}
}
- if (DECL_TEMPLATE_RESULT (t)
- && TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
+ if (DECL_CLASS_TEMPLATE_P (t))
dump_type (TREE_TYPE (t),
((flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
| (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0)));
else if (DECL_TEMPLATE_RESULT (t)
- && TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL)
+ && (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL
+ /* Alias template. */
+ || DECL_TYPE_TEMPLATE_P (t)))
dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME);
else
{
tree exceptions;
VEC(tree,gc) *typenames = NULL;
- if (LAMBDA_FUNCTION_P (t))
+ if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
{
/* A lambda's signature is essentially its "type", so defer. */
gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
else if (TREE_CODE (fntype) == METHOD_TYPE)
cname = TREE_TYPE (TREE_VALUE (parmtypes));
- if (!(flags & TFF_DECL_SPECIFIERS))
- /* OK */;
- else if (DECL_STATIC_FUNCTION_P (t))
- pp_cxx_ws_string (cxx_pp, "static");
- else if (DECL_VIRTUAL_P (t))
- pp_cxx_ws_string (cxx_pp, "virtual");
+ if (flags & TFF_DECL_SPECIFIERS)
+ {
+ if (DECL_STATIC_FUNCTION_P (t))
+ pp_cxx_ws_string (cxx_pp, "static");
+ else if (DECL_VIRTUAL_P (t))
+ pp_cxx_ws_string (cxx_pp, "virtual");
+
+ if (DECL_DECLARED_CONSTEXPR_P (STRIP_TEMPLATE (t)))
+ pp_cxx_ws_string (cxx_pp, "constexpr");
+ }
/* Print the return type? */
if (show_return)
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_cxx_cv_qualifier_seq (cxx_pp, class_of_this_parm (fntype));
}
if (flags & TFF_EXCEPTION_SPECIFICATION)
if (show_return)
dump_type_suffix (TREE_TYPE (fntype), flags);
- }
- /* If T is a template instantiation, dump the parameter binding. */
- if (template_parms != NULL_TREE && template_args != NULL_TREE)
+ /* If T is a template instantiation, dump the parameter binding. */
+ if (template_parms != NULL_TREE && template_args != NULL_TREE)
+ {
+ pp_cxx_whitespace (cxx_pp);
+ pp_cxx_left_bracket (cxx_pp);
+ pp_cxx_ws_string (cxx_pp, M_("with"));
+ pp_cxx_whitespace (cxx_pp);
+ dump_template_bindings (template_parms, template_args, typenames);
+ pp_cxx_right_bracket (cxx_pp);
+ }
+ }
+ else if (template_args)
{
- pp_cxx_whitespace (cxx_pp);
- pp_cxx_left_bracket (cxx_pp);
- pp_cxx_ws_string (cxx_pp, M_("with"));
- pp_cxx_whitespace (cxx_pp);
- dump_template_bindings (template_parms, template_args, typenames);
- pp_cxx_right_bracket (cxx_pp);
+ bool need_comma = false;
+ int i;
+ pp_cxx_begin_template_argument_list (cxx_pp);
+ template_args = INNERMOST_TEMPLATE_ARGS (template_args);
+ for (i = 0; i < TREE_VEC_LENGTH (template_args); ++i)
+ {
+ tree arg = TREE_VEC_ELT (template_args, i);
+ if (need_comma)
+ pp_separate_with_comma (cxx_pp);
+ if (ARGUMENT_PACK_P (arg))
+ pp_cxx_left_brace (cxx_pp);
+ dump_template_argument (arg, TFF_PLAIN_IDENTIFIER);
+ if (ARGUMENT_PACK_P (arg))
+ pp_cxx_right_brace (cxx_pp);
+ need_comma = true;
+ }
+ pp_cxx_end_template_argument_list (cxx_pp);
}
}
dump_parameters (tree parmtypes, int flags)
{
int first = 1;
+ flags &= ~TFF_SCOPE;
pp_cxx_left_paren (cxx_pp);
for (first = 1; parmtypes != void_list_node;
static void
dump_exception_spec (tree t, int flags)
{
- if (t)
+ if (t && TREE_PURPOSE (t))
+ {
+ pp_cxx_ws_string (cxx_pp, "noexcept");
+ pp_cxx_whitespace (cxx_pp);
+ pp_cxx_left_paren (cxx_pp);
+ if (DEFERRED_NOEXCEPT_SPEC_P (t))
+ pp_cxx_ws_string (cxx_pp, "<uninstantiated>");
+ else
+ dump_expr (TREE_PURPOSE (t), flags);
+ pp_cxx_right_paren (cxx_pp);
+ }
+ else if (t)
{
pp_cxx_ws_string (cxx_pp, "throw");
pp_cxx_whitespace (cxx_pp);
}
else if (name && IDENTIFIER_OPNAME_P (name))
pp_cxx_tree_identifier (cxx_pp, name);
+ else if (name && UDLIT_OPER_P (name))
+ pp_cxx_tree_identifier (cxx_pp, name);
else
dump_decl (name, flags);
case NAMESPACE_DECL:
case LABEL_DECL:
case OVERLOAD:
+ case TYPE_DECL:
case IDENTIFIER_NODE:
- dump_decl (t, (flags & ~TFF_DECL_SPECIFIERS) | TFF_NO_FUNCTION_ARGUMENTS);
+ dump_decl (t, ((flags & ~(TFF_DECL_SPECIFIERS|TFF_RETURN_TYPE
+ |TFF_TEMPLATE_HEADER))
+ | TFF_NO_FUNCTION_ARGUMENTS));
break;
case INTEGER_CST:
pp_constant (cxx_pp, t);
break;
+ case USERDEF_LITERAL:
+ pp_cxx_userdef_literal (cxx_pp, t);
+ break;
+
case THROW_EXPR:
/* While waiting for caret diagnostics, avoid printing
__cxa_allocate_exception, __cxa_throw, and the like. */
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)
+ if (TREE_TYPE (fn) != NULL_TREE
+ && NEXT_CODE (fn) == METHOD_TYPE
+ && call_expr_nargs (t))
{
tree ob = CALL_EXPR_ARG (t, 0);
if (TREE_CODE (ob) == ADDR_EXPR)
case INIT_EXPR:
case MODIFY_EXPR:
+ dump_binary_op (assignment_operator_name_info[(int)NOP_EXPR].name,
+ t, flags);
+ break;
+
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this")))
{
dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
- pp_cxx_arrow (cxx_pp);
+ if (TREE_CODE (TREE_TYPE (ob)) == REFERENCE_TYPE)
+ pp_cxx_dot (cxx_pp);
+ else
+ pp_cxx_arrow (cxx_pp);
}
}
else
}
break;
+ case MEM_REF:
+ if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
+ && integer_zerop (TREE_OPERAND (t, 1)))
+ dump_expr (TREE_OPERAND (TREE_OPERAND (t, 0), 0), flags);
+ else
+ {
+ pp_cxx_star (cxx_pp);
+ if (!integer_zerop (TREE_OPERAND (t, 1)))
+ {
+ pp_cxx_left_paren (cxx_pp);
+ if (!integer_onep (TYPE_SIZE_UNIT
+ (TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0))))))
+ {
+ pp_cxx_left_paren (cxx_pp);
+ dump_type (ptr_type_node, flags);
+ pp_cxx_right_paren (cxx_pp);
+ }
+ }
+ dump_expr (TREE_OPERAND (t, 0), flags);
+ if (!integer_zerop (TREE_OPERAND (t, 1)))
+ {
+ pp_cxx_ws_string (cxx_pp, "+");
+ dump_expr (fold_convert (ssizetype, TREE_OPERAND (t, 1)), flags);
+ pp_cxx_right_paren (cxx_pp);
+ }
+ }
+ break;
+
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
break;
CASE_CONVERT:
+ case IMPLICIT_CONV_EXPR:
case VIEW_CONVERT_EXPR:
{
tree op = TREE_OPERAND (t, 0);
-
- if (!same_type_p (TREE_TYPE (op), TREE_TYPE (t)))
+ tree ttype = TREE_TYPE (t);
+ tree optype = TREE_TYPE (op);
+
+ if (TREE_CODE (ttype) != TREE_CODE (optype)
+ && POINTER_TYPE_P (ttype)
+ && POINTER_TYPE_P (optype)
+ && same_type_p (TREE_TYPE (optype),
+ TREE_TYPE (ttype)))
+ {
+ if (TREE_CODE (ttype) == REFERENCE_TYPE)
+ dump_unary_op ("*", t, flags);
+ else
+ dump_unary_op ("&", t, flags);
+ }
+ else if (!same_type_p (TREE_TYPE (op), TREE_TYPE (t)))
{
/* It is a cast, but we cannot tell whether it is a
reinterpret or static cast. Use the C style notation. */
pp_cxx_right_paren (cxx_pp);
break;
+ case AT_ENCODE_EXPR:
+ pp_cxx_ws_string (cxx_pp, "@encode");
+ pp_cxx_whitespace (cxx_pp);
+ pp_cxx_left_paren (cxx_pp);
+ dump_type (TREE_OPERAND (t, 0), flags);
+ pp_cxx_right_paren (cxx_pp);
+ break;
+
+ case NOEXCEPT_EXPR:
+ pp_cxx_ws_string (cxx_pp, "noexcept");
+ pp_cxx_whitespace (cxx_pp);
+ pp_cxx_left_paren (cxx_pp);
+ dump_expr (TREE_OPERAND (t, 0), flags);
+ pp_cxx_right_paren (cxx_pp);
+ break;
+
case REALPART_EXPR:
case IMAGPART_EXPR:
pp_cxx_ws_string (cxx_pp, operator_name_info[TREE_CODE (t)].name);
break;
case BASELINK:
- dump_expr (get_first_fn (t), flags & ~TFF_EXPR_IN_PARENS);
+ dump_expr (BASELINK_FUNCTIONS (t), flags & ~TFF_EXPR_IN_PARENS);
break;
case EMPTY_CLASS_EXPR:
/* Return the location of a tree passed to %+ formats. */
-static location_t
+location_t
location_of (tree t)
{
if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
t = DECL_CONTEXT (t);
else if (TYPE_P (t))
- t = TYPE_MAIN_DECL (t);
+ {
+ t = TYPE_MAIN_DECL (t);
+ if (t == NULL_TREE)
+ return input_location;
+ }
else if (TREE_CODE (t) == OVERLOAD)
t = OVL_FUNCTION (t);
- return DECL_SOURCE_LOCATION (t);
+ if (DECL_P (t))
+ return DECL_SOURCE_LOCATION (t);
+ return EXPR_LOC_OR_HERE (t);
}
/* Now the interfaces from error et al to dump_type et al. Each takes an
reinit_cxx_pp ();
dump_type (typ, flags);
+ /* If we're printing a type that involves typedefs, also print the
+ stripped version. But sometimes the stripped version looks
+ exactly the same, so we don't want it after all. To avoid printing
+ it in that case, we play ugly obstack games. */
+ if (typ && TYPE_P (typ) && typ != TYPE_CANONICAL (typ)
+ && !uses_template_parms (typ))
+ {
+ int aka_start; char *p;
+ struct obstack *ob = pp_base (cxx_pp)->buffer->obstack;
+ /* Remember the end of the initial dump. */
+ int len = obstack_object_size (ob);
+ tree aka = strip_typedefs (typ);
+ pp_string (cxx_pp, " {aka");
+ pp_cxx_whitespace (cxx_pp);
+ /* And remember the start of the aka dump. */
+ aka_start = obstack_object_size (ob);
+ dump_type (aka, flags);
+ pp_character (cxx_pp, '}');
+ p = (char*)obstack_base (ob);
+ /* If they are identical, cut off the aka with a NUL. */
+ if (memcmp (p, p+aka_start, len) == 0)
+ p[len] = '\0';
+ }
return pp_formatted_text (cxx_pp);
}
return pp_formatted_text (cxx_pp);
}
+/* Pretty-print a deduction substitution (from deduction_tsubst_fntype). P
+ is a TREE_LIST with purpose the TEMPLATE_DECL, value the template
+ arguments. */
+
+static const char *
+subst_to_string (tree p)
+{
+ tree decl = TREE_PURPOSE (p);
+ tree targs = TREE_VALUE (p);
+ tree tparms = DECL_TEMPLATE_PARMS (decl);
+ int flags = TFF_DECL_SPECIFIERS|TFF_TEMPLATE_HEADER;
+
+ if (p == NULL_TREE)
+ return "";
+
+ reinit_cxx_pp ();
+ dump_template_decl (TREE_PURPOSE (p), flags);
+ pp_cxx_whitespace (cxx_pp);
+ pp_cxx_left_bracket (cxx_pp);
+ pp_cxx_ws_string (cxx_pp, M_("with"));
+ pp_cxx_whitespace (cxx_pp);
+ dump_template_bindings (tparms, targs, NULL);
+ pp_cxx_right_bracket (cxx_pp);
+ return pp_formatted_text (cxx_pp);
+}
+
static const char *
cv_to_string (tree p, int v)
{
cp_diagnostic_starter (diagnostic_context *context,
diagnostic_info *diagnostic)
{
- diagnostic_report_current_module (context);
+ diagnostic_report_current_module (context, diagnostic->location);
cp_print_error_function (context, diagnostic);
maybe_print_instantiation_context (context);
- pp_base_set_prefix (context->printer, diagnostic_build_prefix (diagnostic));
+ maybe_print_constexpr_context (context);
+ pp_base_set_prefix (context->printer, diagnostic_build_prefix (context,
+ diagnostic));
}
static void
cp_diagnostic_finalizer (diagnostic_context *context,
- diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
+ diagnostic_info *diagnostic)
{
+ virt_loc_aware_diagnostic_finalizer (context, diagnostic);
pp_base_destroy_prefix (context->printer);
}
cp_print_error_function (diagnostic_context *context,
diagnostic_info *diagnostic)
{
+ /* If we are in an instantiation context, current_function_decl is likely
+ to be wrong, so just rely on print_instantiation_full_context. */
+ if (current_instantiation ())
+ return;
if (diagnostic_last_function_changed (context, diagnostic))
{
const char *old_prefix = context->printer->prefix;
const char *file = LOCATION_FILE (diagnostic->location);
- tree abstract_origin = diagnostic->abstract_origin;
+ tree abstract_origin = diagnostic_abstract_origin (diagnostic);
char *new_prefix = (file && abstract_origin == NULL)
? file_name_as_prefix (file) : NULL;
pp_base_newline (context->printer);
if (s.file != NULL)
{
- if (flag_show_column && s.column != 0)
+ if (context->show_column && s.column != 0)
pp_printf (context->printer,
_(" inlined from %qs at %s:%d:%d"),
cxx_printable_name_translate (fndecl, 2),
if (p)
{
- if (current_function_decl != p->decl
- && current_function_decl != NULL_TREE)
- /* We can get here during the processing of some synthesized
- method. Then, P->DECL will be the function that's causing
- the synthesis. */
- ;
- else
- {
- 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_translate (p->decl,
- TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
-
- location = p->locus;
- p = p->next;
- }
+ pp_verbatim (context->printer,
+ TREE_CODE (p->decl) == TREE_LIST
+ ? _("%s: In substitution of %qS:\n")
+ : _("%s: In instantiation of %q#D:\n"),
+ LOCATION_FILE (location),
+ p->decl);
+
+ location = p->locus;
+ p = p->next;
}
print_instantiation_partial_context (context, p, location);
expanded_location xloc;
xloc = expand_location (loc);
- if (t != NULL)
+ if (context->show_column)
+ pp_verbatim (context->printer, _("%s:%d:%d: "),
+ xloc.file, xloc.line, xloc.column);
+ else
+ pp_verbatim (context->printer, _("%s:%d: "),
+ xloc.file, xloc.line);
+
+ if (t != NULL)
{
- const char *str;
- str = decl_as_string_translate (t->decl,
- TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE);
- if (flag_show_column)
+ if (TREE_CODE (t->decl) == TREE_LIST)
pp_verbatim (context->printer,
recursive_p
- ? _("%s:%d:%d: recursively instantiated from %qs\n")
- : _("%s:%d:%d: instantiated from %qs\n"),
- xloc.file, xloc.line, xloc.column, str);
+ ? _("recursively required by substitution of %qS\n")
+ : _("required by substitution of %qS\n"),
+ t->decl);
else
pp_verbatim (context->printer,
recursive_p
- ? _("%s:%d: recursively instantiated from %qs\n")
- : _("%s:%d: recursively instantiated from %qs\n"),
- xloc.file, xloc.line, str);
+ ? _("recursively required from %q#D\n")
+ : _("required from %q#D\n"),
+ t->decl);
}
else
{
- if (flag_show_column)
- pp_verbatim (context->printer,
- recursive_p
- ? _("%s:%d:%d: recursively instantiated from here")
- : _("%s:%d:%d: instantiated from here"),
- xloc.file, xloc.line, xloc.column);
- else
- pp_verbatim (context->printer,
- recursive_p
- ? _("%s:%d: recursively instantiated from here")
- : _("%s:%d: instantiated from here"),
- xloc.file, xloc.line);
+ pp_verbatim (context->printer,
+ recursive_p
+ ? _("recursively required from here")
+ : _("required from here"));
}
}
{
expanded_location xloc;
xloc = expand_location (loc);
- if (flag_show_column)
+ if (context->show_column)
pp_verbatim (context->printer,
_("%s:%d:%d: [ skipping %d instantiation contexts ]\n"),
xloc.file, xloc.line, xloc.column, skip);
diagnostic_flush_buffer (global_dc);
}
\f
+/* Report what constexpr call(s) we're trying to expand, if any. */
+
+void
+maybe_print_constexpr_context (diagnostic_context *context)
+{
+ VEC(tree,heap) *call_stack = cx_error_context ();
+ unsigned ix;
+ tree t;
+
+ FOR_EACH_VEC_ELT (tree, call_stack, ix, t)
+ {
+ expanded_location xloc = expand_location (EXPR_LOCATION (t));
+ const char *s = expr_as_string (t, 0);
+ if (context->show_column)
+ pp_verbatim (context->printer,
+ _("%s:%d:%d: in constexpr expansion of %qs"),
+ xloc.file, xloc.line, xloc.column, s);
+ else
+ pp_verbatim (context->printer,
+ _("%s:%d: in constexpr expansion of %qs"),
+ xloc.file, xloc.line, s);
+ pp_base_newline (context->printer);
+ }
+}
+\f
/* Called from output_format -- during diagnostic message processing --
to handle C++ specific format specifier with the following meanings:
%A function argument-list.
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 'S': result = subst_to_string (next_tree); break;
case 'T': result = type_to_string (next_tree, verbose); break;
case 'V': result = cv_to_string (next_tree, verbose); break;
+ case 'K':
+ percent_K_format (text);
+ return true;
+
default:
return false;
}
case CPP0X_INITIALIZER_LISTS:
pedwarn (input_location, 0,
"extended initializer lists "
- "only available with -std=c++0x or -std=gnu++0x");
+ "only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_EXPLICIT_CONVERSION:
pedwarn (input_location, 0,
"explicit conversion operators "
- "only available with -std=c++0x or -std=gnu++0x");
+ "only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_VARIADIC_TEMPLATES:
pedwarn (input_location, 0,
"variadic templates "
- "only available with -std=c++0x or -std=gnu++0x");
+ "only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_LAMBDA_EXPR:
pedwarn (input_location, 0,
"lambda expressions "
- "only available with -std=c++0x or -std=gnu++0x");
+ "only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_AUTO:
pedwarn (input_location, 0,
- "C++0x auto only available with -std=c++0x or -std=gnu++0x");
+ "C++0x auto only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_SCOPED_ENUMS:
pedwarn (input_location, 0,
- "scoped enums only available with -std=c++0x or -std=gnu++0x");
+ "scoped enums only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_DEFAULTED_DELETED:
pedwarn (input_location, 0,
"defaulted and deleted functions "
- "only available with -std=c++0x or -std=gnu++0x");
- break;
+ "only available with -std=c++11 or -std=gnu++11");
+ break;
+ case CPP0X_INLINE_NAMESPACES:
+ pedwarn (input_location, OPT_pedantic,
+ "inline namespaces "
+ "only available with -std=c++11 or -std=gnu++11");
+ break;
+ case CPP0X_OVERRIDE_CONTROLS:
+ pedwarn (input_location, 0,
+ "override controls (override/final) "
+ "only available with -std=c++11 or -std=gnu++11");
+ break;
+ case CPP0X_NSDMI:
+ pedwarn (input_location, 0,
+ "non-static data member initializers "
+ "only available with -std=c++11 or -std=gnu++11");
+ break;
+ case CPP0X_USER_DEFINED_LITERALS:
+ pedwarn (input_location, 0,
+ "user-defined literals "
+ "only available with -std=c++11 or -std=gnu++11");
+ break;
default:
- gcc_unreachable();
+ gcc_unreachable ();
}
}
va_end (ap);
return report_diagnostic (&diagnostic);
}
+
+/* Issue a diagnostic that NAME cannot be found in SCOPE. DECL is what
+ we found when we tried to do the lookup. LOCATION is the location of
+ the NAME identifier. */
+
+void
+qualified_name_lookup_error (tree scope, tree name,
+ tree decl, location_t location)
+{
+ if (scope == error_mark_node)
+ ; /* We already complained. */
+ else if (TYPE_P (scope))
+ {
+ if (!COMPLETE_TYPE_P (scope))
+ error_at (location, "incomplete type %qT used in nested name specifier",
+ scope);
+ else if (TREE_CODE (decl) == TREE_LIST)
+ {
+ error_at (location, "reference to %<%T::%D%> is ambiguous",
+ scope, name);
+ print_candidates (decl);
+ }
+ else
+ error_at (location, "%qD is not a member of %qT", name, scope);
+ }
+ else if (scope != global_namespace)
+ {
+ error_at (location, "%qD is not a member of %qD", name, scope);
+ suggest_alternatives_for (location, name);
+ }
+ else
+ {
+ error_at (location, "%<::%D%> has not been declared", name);
+ suggest_alternatives_for (location, name);
+ }
+}