diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 2896efdd7f2..17dce107491 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -2890,10 +2890,11 @@ get_mapped_args (tree map) tree level = make_tree_vec (list.length ()); for (unsigned j = 0; j < list.length(); ++j) TREE_VEC_ELT (level, j) = list[j]; + /* None of the args at any level are defaulted. */ + SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (level, list.length()); SET_TMPL_ARGS_LEVEL (args, i + 1, level); list.release (); } - SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args, 0); return args; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1ee2c57e83c..97d5efec2e1 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3689,25 +3689,29 @@ struct GTY(()) lang_decl { ((struct tree_template_info*)TEMPLATE_INFO_CHECK (NODE))->args #define TI_PENDING_TEMPLATE_FLAG(NODE) \ TREE_LANG_FLAG_1 (TEMPLATE_INFO_CHECK (NODE)) -/* For a given TREE_VEC containing a template argument list, - this property contains the number of arguments that are not - defaulted. */ +/* For a given TREE_VEC containing a template argument list (but not multiple + levels of arguments), this property contains the number of arguments that are + not defaulted and optionally the number of explicitly specified template + arguments. It is either a INT_CST denoting the number of non-default + arguments, or a TREE_LIST with TREE_PURPOSE denoting the number of explicitly + given template arguments of a function template, and TREE_VALUE denoting the + number of non-default arguments. */ #define NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) \ TREE_CHAIN (TREE_VEC_CHECK (NODE)) /* Below are the setter and getter of the NON_DEFAULT_TEMPLATE_ARGS_COUNT property. */ #define SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE, INT_VALUE) \ - NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) = build_int_cst (NULL_TREE, INT_VALUE) -#if CHECKING_P -#define GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) \ - int_cst_value (NON_DEFAULT_TEMPLATE_ARGS_COUNT (NODE)) -#else + set_non_default_template_args_count (TREE_VEC_CHECK (NODE), INT_VALUE) + #define GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) \ - NON_DEFAULT_TEMPLATE_ARGS_COUNT (NODE) \ - ? int_cst_value (NON_DEFAULT_TEMPLATE_ARGS_COUNT (NODE)) \ - : TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS (NODE)) -#endif + get_non_default_template_args_count (TREE_VEC_CHECK (NODE)) + +#define EXPLICIT_TEMPLATE_ARGS_P(NODE) \ + (get_explicit_template_args_count (TREE_VEC_CHECK (NODE)) > 0) + +#define SET_EXPLICIT_TEMPLATE_ARGS_COUNT(NODE, INT_VALUE) \ + set_explicit_template_args_count (TREE_VEC_CHECK (NODE), INT_VALUE) /* The list of access checks that were deferred during parsing which need to be performed at template instantiation time. @@ -5949,7 +5953,8 @@ enum auto_deduction_context identical to their defaults. TFF_NO_TEMPLATE_BINDINGS: do not print information about the template arguments for a function template specialization. - TFF_POINTER: we are printing a pointer type. */ + TFF_POINTER: we are printing a pointer type. + TFF_AS_PRIMARY: show the template like a primary template. */ #define TFF_PLAIN_IDENTIFIER (0) #define TFF_SCOPE (1) @@ -5967,6 +5972,7 @@ enum auto_deduction_context #define TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS (1 << 12) #define TFF_NO_TEMPLATE_BINDINGS (1 << 13) #define TFF_POINTER (1 << 14) +#define TFF_AS_PRIMARY (1 << 15) /* These constants can be used as bit flags to control strip_typedefs. @@ -7171,6 +7177,10 @@ extern void pop_access_scope (tree); extern bool check_template_shadow (tree); extern bool check_auto_in_tmpl_args (tree, tree); extern tree get_innermost_template_args (tree, int); +extern void set_non_default_template_args_count (tree args, int count); +extern int get_non_default_template_args_count (tree args); +extern void set_explicit_template_args_count (tree args, int count); +extern bool get_explicit_template_args_count (tree args); extern void maybe_begin_member_template_processing (tree); extern void maybe_end_member_template_processing (void); extern tree finish_member_template_decl (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 56f80775ca0..24d6ee51db7 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9968,6 +9968,10 @@ grokfndecl (tree ctype, /* A friend declaration of the form friend void f<>(). Record the information in the TEMPLATE_ID_EXPR. */ SET_DECL_IMPLICIT_INSTANTIATION (decl); + /* Set the template args as explicitly specified - they were certainly + not deduced from function arguments. */ + if (args) + SET_EXPLICIT_TEMPLATE_ARGS_COUNT (args, NUM_TMPL_ARGS (args)); gcc_assert (identifier_p (fns) || OVL_P (fns)); DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 98c1f0e4bdf..5b5e67e6963 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -86,11 +86,11 @@ static void dump_exception_spec (cxx_pretty_printer *, tree, int); static void dump_template_argument (cxx_pretty_printer *, tree, int); static void dump_template_argument_list (cxx_pretty_printer *, tree, int); static void dump_template_parameter (cxx_pretty_printer *, tree, int); -static void dump_template_bindings (cxx_pretty_printer *, tree, tree, - vec *); +static void dump_template_bindings (cxx_pretty_printer *, tree, tree, tree, + vec *, int); static void dump_scope (cxx_pretty_printer *, tree, int); static void dump_template_parms (cxx_pretty_printer *, tree, int, int); -static int get_non_default_template_args_count (tree, int); +static int args_or_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 *); @@ -272,24 +272,23 @@ dump_template_argument (cxx_pretty_printer *pp, tree arg, int flags) } } -/* Count the number of template arguments ARGS whose value does not - match the (optional) default template parameter in PARAMS */ +/* Returns GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (ARGS) unless FLAGS requests the + full count of template args. */ static int -get_non_default_template_args_count (tree args, int flags) +args_or_non_default_template_args_count (tree args, int flags) { - int n = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS (args)); + gcc_assert (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)); 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; + (flags & TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS) != 0) + return NUM_TMPL_ARGS (args); - return GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (INNERMOST_TEMPLATE_ARGS (args)); + return GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args); } /* Dump a template-argument-list ARGS (always a TREE_VEC) under control @@ -298,7 +297,7 @@ get_non_default_template_args_count (tree args, int flags) static void dump_template_argument_list (cxx_pretty_printer *pp, tree args, int flags) { - int n = get_non_default_template_args_count (args, flags); + int n = args_or_non_default_template_args_count (args, flags); int need_comma = 0; int i; @@ -369,7 +368,7 @@ dump_template_parameter (cxx_pretty_printer *pp, tree parm, int flags) static void dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, - vec *typenames) + tree used_parms, vec *typenames, int flags) { /* Print "[with" and ']', conditional on whether anything is printed at all. This is tied to whether a semicolon is needed to separate multiple template @@ -414,23 +413,47 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, /* Don't crash if we had an invalid argument list. */ if (TMPL_ARGS_DEPTH (args) >= lvl) lvl_args = TMPL_ARGS_LEVEL (args, lvl); + const int len = TREE_VEC_LENGTH (p); + const int non_default_len + = lvl_args ? args_or_non_default_template_args_count (lvl_args, flags) + : len; - for (i = 0; i < TREE_VEC_LENGTH (p); ++i) + for (i = 0; i < len; ++i, ++arg_idx) { + const tree parm_i = TREE_VEC_ELT (p, i); + gcc_assert (TREE_CODE (parm_i) == TREE_LIST); + const tree parm_val = TREE_VALUE (parm_i); + const tree parm_type = TREE_CODE (parm_val) == TYPE_DECL + || TREE_CODE (parm_val) == TEMPLATE_DECL + ? TREE_TYPE (parm_val) + : TREE_CODE (parm_val) == PARM_DECL + ? DECL_ARG_TYPE (parm_val) + : NULL_TREE; + + /* If the template parameter is defaulted and does not appear in + used_parms (function arguments, return type, or exception + specifier), skip the parameter. */ + if (i >= non_default_len) + { + tree it; + for (it = used_parms; it && TREE_VALUE (it) != parm_type; + it = TREE_CHAIN (it)) + ; + if (!it) + continue; + } + tree arg = NULL_TREE; /* Don't crash if we had an invalid argument list. */ if (lvl_args && NUM_TMPL_ARGS (lvl_args) > arg_idx) arg = TREE_VEC_ELT (lvl_args, arg_idx); - tree parm_i = TREE_VEC_ELT (p, i); /* If the template argument repeats the template parameter (T = T), skip the parameter.*/ if (arg && TREE_CODE (arg) == TEMPLATE_TYPE_PARM - && TREE_CODE (parm_i) == TREE_LIST - && TREE_CODE (TREE_VALUE (parm_i)) == TYPE_DECL - && TREE_CODE (TREE_TYPE (TREE_VALUE (parm_i))) - == TEMPLATE_TYPE_PARM + && TREE_CODE (parm_val) == TYPE_DECL + && TREE_CODE (TREE_TYPE (parm_val)) == TEMPLATE_TYPE_PARM && DECL_NAME (TREE_VALUE (parm_i)) == DECL_NAME (TREE_CHAIN (arg))) continue; @@ -450,8 +473,6 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, } else pp_string (pp, M_("")); - - ++arg_idx; } parms = TREE_CHAIN (parms); @@ -1634,8 +1655,30 @@ dump_substitution (cxx_pretty_printer *pp, if (template_parms != NULL_TREE && template_args != NULL_TREE && !(flags & TFF_NO_TEMPLATE_BINDINGS)) { - vec *typenames = t ? find_typenames (t) : NULL; - dump_template_bindings (pp, template_parms, template_args, typenames); + vec *typenames = nullptr; + tree used_parms = NULL_TREE; + if (t) + { + typenames = find_typenames (t); + const tree fn = TREE_TYPE (DECL_TEMPLATE_RESULT (t)); + if (TREE_CODE (fn) == METHOD_TYPE) + { + /* For methods, we have to skip walking TYPE_METHOD_BASETYPE and + the hidden "self" function parameter. Otherwise, we'll discover + all template parameters of class templates in the function's + context. */ + used_parms = find_template_parameters (TREE_TYPE (fn), + template_parms); + for (tree arg = TREE_CHAIN (TYPE_ARG_TYPES (fn)); arg; + arg = TREE_CHAIN (arg)) + used_parms = chainon (used_parms, find_template_parameters + (arg, template_parms)); + } + else + used_parms = find_template_parameters (fn, template_parms); + } + dump_template_bindings (pp, template_parms, template_args, used_parms, + typenames, flags); } } @@ -1689,8 +1732,15 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) constexpr_p = (DECL_DECLARED_CONSTEXPR_P (t) && !decl_implicit_constexpr_p (t)); - /* Pretty print template instantiations only. */ - if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t) + /* Keep t before the following branch makes t point to a more general + template. Without the specialized template, the information about defaulted + template arguments is lost. */ + tree specialized_t = t; + int specialized_flags = 0; + + /* Pretty print only template instantiations. Don't pretty print explicit + specializations like 'template <> void fun (int)'. */ + if (DECL_TEMPLATE_INSTANTIATION (t) && DECL_TEMPLATE_INFO (t) && !(flags & TFF_NO_TEMPLATE_BINDINGS) && flag_pretty_templates) { @@ -1702,6 +1752,9 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) { template_parms = DECL_TEMPLATE_PARMS (tmpl); t = tmpl; + /* The "[with ...]" clause is printed, thus dump functions printing + SPECIALIZED_T need to add TFF_AS_PRIMARY to their flags. */ + specialized_flags = TFF_AS_PRIMARY; } } @@ -1711,8 +1764,8 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) fntype = TREE_TYPE (t); parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t); - if (DECL_CLASS_SCOPE_P (t)) - cname = DECL_CONTEXT (t); + if (DECL_CLASS_SCOPE_P (specialized_t)) + cname = DECL_CONTEXT (specialized_t); /* This is for partially instantiated template methods. */ else if (TREE_CODE (fntype) == METHOD_TYPE) cname = TREE_TYPE (TREE_VALUE (parmtypes)); @@ -1750,13 +1803,14 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) /* Nothing. */; else if (cname) { - dump_type (pp, cname, flags); + dump_type (pp, cname, flags | specialized_flags); pp_cxx_colon_colon (pp); } else dump_scope (pp, CP_DECL_CONTEXT (t), flags); - dump_function_name (pp, t, dump_function_name_flags); + dump_function_name (pp, specialized_t, + dump_function_name_flags | specialized_flags); if (!(flags & TFF_NO_FUNCTION_ARGUMENTS)) { @@ -1803,26 +1857,6 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) pp_character (pp, ']'); } } - else if (template_args) - { - bool need_comma = false; - int i; - pp_cxx_begin_template_argument_list (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 (pp); - if (ARGUMENT_PACK_P (arg)) - pp_cxx_left_brace (pp); - dump_template_argument (pp, arg, TFF_PLAIN_IDENTIFIER); - if (ARGUMENT_PACK_P (arg)) - pp_cxx_right_brace (pp); - need_comma = true; - } - pp_cxx_end_template_argument_list (pp); - } } /* Print a parameter list. If this is for a member function, the @@ -1969,13 +2003,35 @@ dump_function_name (cxx_pretty_printer *pp, tree t, int flags) dump_module_suffix (pp, t); +/* Print function template parameters if: + 1. t is template, and + 2. the caller didn't request to only print the template-name, and + 3. t actually has template parameters that are not indirect parameters from + enclosing scopes, i.e. either + - t is a friend template specialization + (eg. template struct X { friend void foo(int); }; since + PRIMARY_TEMPLATE_P requires a TEMPLATE_DECL, this case must be checked + before PRIMARY_TEMPLATE_P is safe to call), or + - t is a primary template (own template header), + and + 4. either + - flags requests to show no function arguments, in which case deduced + types could be hidden and thus need to be printed, or + - at least one function template argument was given explicitly and the + diagnostics output should reflect the code as it was written, + + Whether t is a specialization of a template informs the PRIMARY parameter of + dump_template_parms. + */ if (DECL_TEMPLATE_INFO (t) && !(flags & TFF_TEMPLATE_NAME) - && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t) && (TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL - || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t)))) - dump_template_parms (pp, DECL_TEMPLATE_INFO (t), !DECL_USE_TEMPLATE (t), - flags); + || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t))) + && ((flags & TFF_NO_FUNCTION_ARGUMENTS) + || (DECL_TI_ARGS (t) + && EXPLICIT_TEMPLATE_ARGS_P (INNERMOST_TEMPLATE_ARGS + (DECL_TI_ARGS (t)))))) + dump_template_parms (pp, DECL_TEMPLATE_INFO (t), !DECL_USE_TEMPLATE (t), flags); } /* Dump the template parameters from the template info INFO under control of @@ -1990,6 +2046,8 @@ dump_template_parms (cxx_pretty_printer *pp, tree info, { tree args = info ? TI_ARGS (info) : NULL_TREE; + if (flags & TFF_AS_PRIMARY) + primary = true; if (primary && flags & TFF_TEMPLATE_NAME) return; flags &= ~(TFF_CLASS_KEY_OR_ENUM | TFF_TEMPLATE_NAME); @@ -1999,10 +2057,11 @@ dump_template_parms (cxx_pretty_printer *pp, tree info, to crash producing error messages. */ if (args && !primary) { - int len, ix; - len = get_non_default_template_args_count (args, flags); + int ix; args = INNERMOST_TEMPLATE_ARGS (args); + int len = args_or_non_default_template_args_count (args, flags); + gcc_assert (len <= NUM_TMPL_ARGS (args)); for (ix = 0; ix != len; ix++) { tree arg = TREE_VEC_ELT (args, ix); @@ -2027,25 +2086,35 @@ dump_template_parms (cxx_pretty_printer *pp, tree info, tree parms = DECL_TEMPLATE_PARMS (tpl); int len, ix; - parms = TREE_CODE (parms) == TREE_LIST ? TREE_VALUE (parms) : NULL_TREE; - len = parms ? TREE_VEC_LENGTH (parms) : 0; - - for (ix = 0; ix != len; ix++) + if (TREE_CODE (parms) == TREE_LIST) { - tree parm; + parms = INNERMOST_TEMPLATE_PARMS (parms); + if (args) + { + len = args_or_non_default_template_args_count + (INNERMOST_TEMPLATE_ARGS (args), flags); + gcc_assert (len <= TREE_VEC_LENGTH (parms)); + } + else + len = TREE_VEC_LENGTH (parms); - if (TREE_VEC_ELT (parms, ix) == error_mark_node) - { - pp_string (pp, M_("