static void dump_parameters (tree, int);
static void dump_exception_spec (tree, int);
static void dump_template_argument (tree, int);
-static void dump_template_argument_list (tree, tree, int);
+static void dump_template_argument_list (tree, int);
static void dump_template_parameter (tree, int);
static void dump_template_bindings (tree, tree, VEC(tree,gc) *);
static void dump_scope (tree, int);
static void dump_template_parms (tree, int, int);
-
-static int count_non_default_template_args (tree, tree);
-
+static int get_non_default_template_args_count (tree, int);
static const char *function_category (tree);
static void maybe_print_instantiation_context (diagnostic_context *);
static void print_instantiation_full_context (diagnostic_context *);
dump_template_argument (tree arg, int flags)
{
if (ARGUMENT_PACK_P (arg))
- dump_template_argument_list (ARGUMENT_PACK_ARGS (arg), NULL_TREE, flags);
+ 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
match the (optional) default template parameter in PARAMS */
static int
-count_non_default_template_args (tree args, tree params)
+get_non_default_template_args_count (tree args, int flags)
{
- tree inner_args = INNERMOST_TEMPLATE_ARGS (args);
- int n = TREE_VEC_LENGTH (inner_args);
- int last;
+ int n = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS (args));
- if (params == NULL_TREE || !flag_pretty_templates)
+ if (/* We use this flag when generating debug information. We don't
+ want to expand templates at this point, for this may generate
+ new decls, which gets decl counts out of sync, which may in
+ turn cause codegen differences between compilations with and
+ without -g. */
+ (flags & TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS) != 0
+ || !flag_pretty_templates)
return n;
- for (last = n - 1; last >= 0; --last)
- {
- tree param = TREE_VEC_ELT (params, last);
- tree def = TREE_PURPOSE (param);
-
- if (!def)
- break;
- if (uses_template_parms (def))
- {
- ++processing_template_decl;
- def = tsubst_copy_and_build (def, args, tf_none, NULL_TREE, false, true);
- --processing_template_decl;
- }
- if (!cp_tree_equal (TREE_VEC_ELT (inner_args, last), def))
- break;
- }
-
- return last + 1;
+ return GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (INNERMOST_TEMPLATE_ARGS (args));
}
/* Dump a template-argument-list ARGS (always a TREE_VEC) under control
of FLAGS. */
static void
-dump_template_argument_list (tree args, tree parms, int flags)
+dump_template_argument_list (tree args, int flags)
{
- int n = count_non_default_template_args (args, parms);
+ int n = get_non_default_template_args_count (args, flags);
int need_comma = 0;
int i;
pp_equal (cxx_pp);
pp_cxx_whitespace (cxx_pp);
if (arg)
- dump_template_argument (arg, TFF_PLAIN_IDENTIFIER);
+ {
+ 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);
+ }
else
pp_string (cxx_pp, M_("<missing>"));
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_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, NULL_TREE, flags);
+ dump_template_argument_list (args, flags);
pp_cxx_end_template_argument_list (cxx_pp);
}
break;
break;
case UNBOUND_CLASS_TEMPLATE:
- dump_type (TYPE_CONTEXT (t), flags);
- pp_cxx_colon_colon (cxx_pp);
+ if (! (flags & TFF_UNQUALIFIED_NAME))
+ {
+ dump_type (TYPE_CONTEXT (t), flags);
+ pp_cxx_colon_colon (cxx_pp);
+ }
pp_cxx_ws_string (cxx_pp, "template");
dump_type (DECL_NAME (TYPE_NAME (t)), flags);
break;
{
typdef = !DECL_ARTIFICIAL (name);
- if (typdef
- && ((flags & TFF_CHASE_TYPEDEF)
- || (!flag_pretty_templates && DECL_LANG_SPECIFIC (name)
- && DECL_TEMPLATE_INFO (name))))
+ if ((typdef
+ && ((flags & TFF_CHASE_TYPEDEF)
+ || (!flag_pretty_templates && DECL_LANG_SPECIFIC (name)
+ && DECL_TEMPLATE_INFO (name))))
+ || DECL_SELF_REFERENCE_P (name))
{
t = TYPE_MAIN_VARIANT (t);
name = TYPE_NAME (t);
else
pp_printf (pp_base (cxx_pp), M_("<anonymous %s>"), variety);
}
+ else if (LAMBDANAME_P (name))
+ {
+ /* A lambda's "type" is essentially its signature. */
+ pp_string (cxx_pp, M_("<lambda"));
+ if (lambda_function (t))
+ dump_parameters (FUNCTION_FIRST_USER_PARMTYPE (lambda_function (t)),
+ flags);
+ pp_character(cxx_pp, '>');
+ }
else
pp_cxx_tree_identifier (cxx_pp, name);
if (tmplate)
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 TYPE_DECL:
case TREE_VEC:
case UNION_TYPE:
- case UNKNOWN_TYPE:
+ case LANG_TYPE:
case VOID_TYPE:
case TYPENAME_TYPE:
case COMPLEX_TYPE:
dump_type (TREE_TYPE (t), flags);
break;
}
- if (flags & TFF_DECL_SPECIFIERS)
+ if ((flags & TFF_DECL_SPECIFIERS)
+ && !DECL_SELF_REFERENCE_P (t))
pp_cxx_ws_string (cxx_pp, "typedef");
dump_simple_decl (t, DECL_ORIGINAL_TYPE (t)
? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t),
break;
case SCOPE_REF:
- pp_expression (cxx_pp, t);
+ dump_type (TREE_OPERAND (t, 0), flags);
+ pp_string (cxx_pp, "::");
+ dump_decl (TREE_OPERAND (t, 1), flags|TFF_UNQUALIFIED_NAME);
break;
case ARRAY_REF:
dump_decl (name, flags);
pp_cxx_begin_template_argument_list (cxx_pp);
if (TREE_OPERAND (t, 1))
- dump_template_argument_list (TREE_OPERAND (t, 1), NULL_TREE, flags);
+ dump_template_argument_list (TREE_OPERAND (t, 1), flags);
pp_cxx_end_template_argument_list (cxx_pp);
}
break;
}
/* find_typenames looks through the type of the function template T
- and returns a VEC containing any typedefs or TYPENAME_TYPEs it finds. */
+ and returns a VEC containing any typedefs, decltypes or TYPENAME_TYPEs
+ it finds. */
struct find_typenames_t
{
if (TYPE_P (*tp) && is_typedef_decl (TYPE_NAME (*tp)))
/* Add the type of the typedef without any additional cv-quals. */
mv = TREE_TYPE (TYPE_NAME (*tp));
- else if (TREE_CODE (*tp) == TYPENAME_TYPE)
+ else if (TREE_CODE (*tp) == TYPENAME_TYPE
+ || TREE_CODE (*tp) == DECLTYPE_TYPE)
/* Add the typename without any cv-qualifiers. */
mv = TYPE_MAIN_VARIANT (*tp);
tree exceptions;
VEC(tree,gc) *typenames = NULL;
+ if (LAMBDA_FUNCTION_P (t))
+ {
+ /* A lambda's signature is essentially its "type", so defer. */
+ gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
+ dump_type (DECL_CONTEXT (t), flags);
+ return;
+ }
+
flags &= ~TFF_UNQUALIFIED_NAME;
if (TREE_CODE (t) == TEMPLATE_DECL)
t = DECL_TEMPLATE_RESULT (t);
/* Don't let the user see __comp_ctor et al. */
if (DECL_CONSTRUCTOR_P (t)
|| DECL_DESTRUCTOR_P (t))
- name = constructor_name (DECL_CONTEXT (t));
+ {
+ if (LAMBDA_TYPE_P (DECL_CONTEXT (t)))
+ name = get_identifier ("<lambda>");
+ else
+ name = constructor_name (DECL_CONTEXT (t));
+ }
if (DECL_DESTRUCTOR_P (t))
{
if (args && !primary)
{
int len, ix;
- /* We don't know the parms for a friend template specialization. */
- tree params = (TREE_CODE (TI_TEMPLATE (info)) == TEMPLATE_DECL
- ? DECL_INNERMOST_TEMPLATE_PARMS (TI_TEMPLATE (info))
- : NULL_TREE);
-
- len = count_non_default_template_args (args, params);
+ len = get_non_default_template_args_count (args, flags);
args = INNERMOST_TEMPLATE_ARGS (args);
for (ix = 0; ix != len; ix++)
break;
case SCOPE_REF:
+ dump_decl (t, flags);
+ break;
+
case EXPR_PACK_EXPANSION:
case TYPEID_EXPR:
case MEMBER_REF:
reinit_cxx_pp ();
pp_translate_identifiers (cxx_pp) = translate;
- if (v == 1 && DECL_CLASS_SCOPE_P (decl))
+ if (v == 1
+ && (DECL_CLASS_SCOPE_P (decl)
+ || (DECL_NAMESPACE_SCOPE_P (decl)
+ && CP_DECL_CONTEXT (decl) != global_namespace)))
{
dump_type (CP_DECL_CONTEXT (decl), TFF_PLAIN_IDENTIFIER);
pp_cxx_colon_colon (cxx_pp);
return _("In constructor %qs");
else if (DECL_DESTRUCTOR_P (fn))
return _("In destructor %qs");
+ else if (LAMBDA_FUNCTION_P (fn))
+ return _("In lambda function");
else
return _("In member function %qs");
}
print_instantiation_partial_context (context, p, location);
}
-/* Same as above but less verbose. */
+/* Helper function of print_instantiation_partial_context() that
+ prints a single line of instantiation context. */
+
static void
-print_instantiation_partial_context (diagnostic_context *context,
- struct tinst_level *t, location_t loc)
+print_instantiation_partial_context_line (diagnostic_context *context,
+ const struct tinst_level *t,
+ location_t loc, bool recursive_p)
{
expanded_location xloc;
- const char *str;
- for (; ; t = t->next)
+ xloc = expand_location (loc);
+
+ if (t != NULL)
{
- xloc = expand_location (loc);
- if (t == NULL)
- break;
+ const char *str;
str = decl_as_string_translate (t->decl,
- TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE);
+ TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE);
if (flag_show_column)
pp_verbatim (context->printer,
- _("%s:%d:%d: instantiated from %qs\n"),
+ recursive_p
+ ? _("%s:%d:%d: recursively instantiated from %qs\n")
+ : _("%s:%d:%d: instantiated from %qs\n"),
xloc.file, xloc.line, xloc.column, str);
else
pp_verbatim (context->printer,
- _("%s:%d: instantiated from %qs\n"),
+ recursive_p
+ ? _("%s:%d: recursively instantiated from %qs\n")
+ : _("%s:%d: recursively instantiated from %qs\n"),
xloc.file, xloc.line, str);
- loc = t->locus;
}
- if (flag_show_column)
- pp_verbatim (context->printer, _("%s:%d:%d: instantiated from here"),
- xloc.file, xloc.line, xloc.column);
else
- pp_verbatim (context->printer, _("%s:%d: instantiated from here"),
- xloc.file, xloc.line);
+ {
+ 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);
+ }
+}
+
+/* Same as print_instantiation_full_context but less verbose. */
+
+static void
+print_instantiation_partial_context (diagnostic_context *context,
+ struct tinst_level *t0, location_t loc)
+{
+ struct tinst_level *t;
+ int n_total = 0;
+ int n;
+ location_t prev_loc = loc;
+
+ for (t = t0; t != NULL; t = t->next)
+ if (prev_loc != t->locus)
+ {
+ prev_loc = t->locus;
+ n_total++;
+ }
+
+ t = t0;
+
+ if (n_total >= 12)
+ {
+ int skip = n_total - 10;
+ for (n = 0; n < 5; n++)
+ {
+ gcc_assert (t != NULL);
+ if (loc != t->locus)
+ print_instantiation_partial_context_line (context, t, loc,
+ /*recursive_p=*/false);
+ loc = t->locus;
+ t = t->next;
+ }
+ if (t != NULL && skip > 1)
+ {
+ expanded_location xloc;
+ xloc = expand_location (loc);
+ if (flag_show_column)
+ pp_verbatim (context->printer,
+ _("%s:%d:%d: [ skipping %d instantiation contexts ]\n"),
+ xloc.file, xloc.line, xloc.column, skip);
+ else
+ pp_verbatim (context->printer,
+ _("%s:%d: [ skipping %d instantiation contexts ]\n"),
+ xloc.file, xloc.line, skip);
+
+ do {
+ loc = t->locus;
+ t = t->next;
+ } while (t != NULL && --skip > 0);
+ }
+ }
+
+ while (t != NULL)
+ {
+ while (t->next != NULL && t->locus == t->next->locus)
+ {
+ loc = t->locus;
+ t = t->next;
+ }
+ print_instantiation_partial_context_line (context, t, loc,
+ t->locus == loc);
+ loc = t->locus;
+ t = t->next;
+ }
+ print_instantiation_partial_context_line (context, NULL, loc,
+ /*recursive_p=*/false);
pp_base_newline (context->printer);
}
\f
/* Warn about the use of C++0x features when appropriate. */
void
-maybe_warn_cpp0x (const char* str)
+maybe_warn_cpp0x (cpp0x_warn_str str)
{
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 (input_location, 0, "%s only available with -std=c++0x or -std=gnu++0x", str);
+ switch (str)
+ {
+ case CPP0X_INITIALIZER_LISTS:
+ pedwarn (input_location, 0,
+ "extended initializer lists "
+ "only available with -std=c++0x or -std=gnu++0x");
+ break;
+ case CPP0X_EXPLICIT_CONVERSION:
+ pedwarn (input_location, 0,
+ "explicit conversion operators "
+ "only available with -std=c++0x or -std=gnu++0x");
+ break;
+ case CPP0X_VARIADIC_TEMPLATES:
+ pedwarn (input_location, 0,
+ "variadic templates "
+ "only available with -std=c++0x or -std=gnu++0x");
+ break;
+ case CPP0X_LAMBDA_EXPR:
+ pedwarn (input_location, 0,
+ "lambda expressions "
+ "only available with -std=c++0x or -std=gnu++0x");
+ break;
+ case CPP0X_AUTO:
+ pedwarn (input_location, 0,
+ "C++0x auto only available with -std=c++0x or -std=gnu++0x");
+ break;
+ case CPP0X_SCOPED_ENUMS:
+ pedwarn (input_location, 0,
+ "scoped enums only available with -std=c++0x or -std=gnu++0x");
+ break;
+ case CPP0X_DEFAULTED_DELETED:
+ pedwarn (input_location, 0,
+ "defaulted and deleted functions "
+ "only available with -std=c++0x or -std=gnu++0x");
+ break;
+ default:
+ gcc_unreachable();
+ }
}
/* Warn about the use of variadic templates when appropriate. */
void
maybe_warn_variadic_templates (void)
{
- maybe_warn_cpp0x ("variadic templates");
+ maybe_warn_cpp0x (CPP0X_VARIADIC_TEMPLATES);
}