From patchwork Fri Nov 26 15:24:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Matthias Kretz X-Patchwork-Id: 48196 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D8D683857828 for ; Fri, 26 Nov 2021 15:25:11 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from lxmtout2.gsi.de (lxmtout2.gsi.de [140.181.3.112]) by sourceware.org (Postfix) with ESMTPS id B03CA3857C60 for ; Fri, 26 Nov 2021 15:24:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B03CA3857C60 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gsi.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gsi.de Received: from localhost (localhost [127.0.0.1]) by lxmtout2.gsi.de (Postfix) with ESMTP id C21EB202AD67; Fri, 26 Nov 2021 16:24:45 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at lxmtout2.gsi.de Received: from lxmtout2.gsi.de ([127.0.0.1]) by localhost (lxmtout2.gsi.de [127.0.0.1]) (amavisd-new, port 10024) with LMTP id FQePSzJeZUAF; Fri, 26 Nov 2021 16:24:45 +0100 (CET) Received: from srvex3.campus.gsi.de (unknown [10.10.4.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) by lxmtout2.gsi.de (Postfix) with ESMTPS id A1D33202AD65; Fri, 26 Nov 2021 16:24:45 +0100 (CET) Received: from excalibur.localnet (140.181.3.12) by srvex3.campus.gsi.de (10.10.4.16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2375.17; Fri, 26 Nov 2021 16:24:45 +0100 From: Matthias Kretz To: , Subject: [PATCH 1/2] c++: Print function template parms when relevant Date: Fri, 26 Nov 2021 16:24:44 +0100 Message-ID: <2802202.e9J7NaK4W3@excalibur> Organization: GSI Helmholtzzentrum =?utf-8?q?f=C3=BCr?= Schwerionenforschung In-Reply-To: <1800263.tdWV9SEqCh@excalibur> References: <1800263.tdWV9SEqCh@excalibur> MIME-Version: 1.0 X-Originating-IP: [140.181.3.12] X-ClientProxiedBy: SRVEX2.campus.gsi.de (10.10.4.15) To srvex3.campus.gsi.de (10.10.4.16) X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, BODY_8BITS, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H2, SPF_PASS, TXREP, T_SPF_HELO_PERMERROR autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" The choice when to print a function template parameter was still suboptimal. That's because sometimes the function template parameter list only adds noise, while in other situations the lack of a function template parameter list makes diagnostic messages hard to understand. The general idea of this change is to print template parms wherever they would appear in the source code as well. Thus, the diagnostics code needs to know whether any template parameter was given explicitly. DWARF names of functions use dump_function_name to produce a name without function arguments (function arguments are printed from dump_function_decl). However, FLAGS should still state the intent of printing a name without function arguments (TFF_NO_FUNCTION_ARGUMENTS so that dump_function_name can decide correctly whether to call dump_template_parms. Based on an initial patch from Jason Merrill . Signed-off-by: Matthias Kretz gcc/testsuite/ChangeLog: * g++.dg/debug/dwarf2/template-params-12n.C: Optionally, allow DW_AT_default_value. * g++.dg/diagnostic/default-template-args-1.C: New test. * g++.dg/diagnostic/default-template-args-2.C: New test. * g++.dg/diagnostic/default-template-args-3.C: New test. * g++.dg/diagnostic/default-template-args-4.C: New test. * g++.dg/diagnostic/default-template-args-5.C: New test. * g++.dg/diagnostic/param-type-mismatch-2.C: Expect template parms in diagnostic. * g++.dg/ext/pretty1.C: Expect function template specialization to not pretty-print template parms. * g++.old-deja/g++.ext/pretty3.C: Ditto. * g++.old-deja/g++.pt/memtemp77.C: Ditto. * g++.dg/goacc/template.C: Expect function template parms for explicit arguments. * g++.dg/gomp/declare-variant-7.C: Expect no function template parms for deduced arguments. * g++.dg/template/error40.C: Expect only non-default template arguments in diagnostic. gcc/cp/ChangeLog: * constraint.cc (get_mapped_args): Remove incorrect non-default args count on multi-level template args; instead set the non-default args count on each inner TREE_VEC. * cp-tree.h: Rewrite NON_DEFAULT_TEMPLATE_ARGS_COUNT implementation to store the number explicitly specified arguments in a TREE_LIST. (EXPLICIT_TEMPLATE_ARGS_P): New. (SET_EXPLICIT_TEMPLATE_ARGS_P): New. (set_non_default_template_args_count): New declaration. (get_non_default_template_args_count): New declaration. (set_explicit_template_args_count): New declaration. (get_explicit_template_args_count): New declaration. (TFF_AS_PRIMARY): New constant. * decl.c (grokfndecl): Mark all template arguments in a friend declaration as explicitly specified. * error.c (args_or_non_default_template_args_count): Renamed from get_non_default_template_args_count (name-clash). Make independent of flag_pretty_templates. (dump_template_bindings): Add flags parameter to be passed to get_non_default_template_args_count. Print only non-default template arguments. Add used_parms parameter: print defaulted template bindings if the parameter name is part of used_parms. (dump_substitution): Walk the function_decl to find all used template parameters. (dump_function_decl): Call dump_function_name and dump_type of the DECL_CONTEXT with specialized template and set TFF_AS_PRIMARY for their flags. Don't print template arguments. dump_function_name already does so. (dump_function_name): Add and document conditions for calling dump_template_parms. Move DECL_USE_TEMPLATE to PRIMARY parameter of dump_template_parms. (dump_template_parms): Print only non-default template parameters. (lang_decl_name): Add TFF_NO_FUNCTION_ARGUMENTS to dump_function_name flags. * pt.c (set_non_default_template_args_count): New function. (get_non_default_template_args_count): New function. (set_explicit_template_args_count): New function. (get_explicit_template_args_count): New function. (expand_template_argument_pack): Always adjust and set the adjusted non-default args count. (template_parm_to_arg): SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT independent of CHECKING_P. (coerce_template_parameter_pack): Ditto. (coerce_template_parms): Ditto. (fn_type_unification): Ditto. (type_unification_real): Ditto. (get_partial_spec_bindings): Ditto. (determine_specialization): Also copy the inner TREE_VECs. (template_parms_level_to_args): Always count non-default args. (copy_template_args): Only copy the non-default template args count on TREE_VECs that should have it. (fn_type_unification): Set EXPLICIT_TEMPLATE_ARGS_P on the template arguments tree if any template parameter was explicitly given. (type_unification_real): Count non-default args sooner. (get_partial_spec_bindings): Set non-default args count. (tsubst_template_args): Take a shortcut for multi-level args to avoid a lot of unnecessary checks and simplify non-default args counting. Fix the count of non-default template arguments. gcc/cp/constraint.cc | 3 +- gcc/cp/cp-tree.h | 36 ++- gcc/cp/decl.c | 4 + gcc/cp/error.c | 200 +++++++++------ gcc/cp/pt.c | 232 ++++++++++++++---- .../g++.dg/debug/dwarf2/template-params-12n.C | 2 +- .../diagnostic/default-template-args-1.C | 61 +++++ .../diagnostic/default-template-args-2.C | 37 +++ .../diagnostic/default-template-args-3.C | 29 +++ .../diagnostic/default-template-args-4.C | 19 ++ .../diagnostic/default-template-args-5.C | 12 + .../g++.dg/diagnostic/param-type-mismatch-2.C | 2 +- gcc/testsuite/g++.dg/ext/pretty1.C | 2 +- gcc/testsuite/g++.dg/goacc/template.C | 8 +- gcc/testsuite/g++.dg/gomp/declare-variant-7.C | 4 +- gcc/testsuite/g++.dg/template/error40.C | 6 +- gcc/testsuite/g++.old-deja/g++.ext/pretty3.C | 2 +- gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C | 2 +- 18 files changed, 508 insertions(+), 153 deletions(-) create mode 100644 gcc/testsuite/g++.dg/diagnostic/default-template-args-1.C create mode 100644 gcc/testsuite/g++.dg/diagnostic/default-template-args-2.C create mode 100644 gcc/testsuite/g++.dg/diagnostic/default-template-args-3.C create mode 100644 gcc/testsuite/g++.dg/diagnostic/default-template-args-4.C create mode 100644 gcc/testsuite/g++.dg/diagnostic/default-template-args-5.C Dr. Matthias Kretz https://mattkretz.github.io GSI Helmholtz Centre for Heavy Ion Research https://gsi.de stdₓ::simd ────────────────────────────────────────────────────────────────────────── Signed-off-by: Matthias Kretz 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 f387b5036d2..b5350bb8409 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3684,25 +3684,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. @@ -5938,7 +5942,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) @@ -5956,6 +5961,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. @@ -7153,6 +7159,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 7c2a134e406..74b0cac0f2f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9985,6 +9985,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 012a4ecddf4..fb62adbeb0b 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,16 @@ 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)); + used_parms = find_template_parameters (fn, template_parms); + } + dump_template_bindings (pp, template_parms, template_args, used_parms, + typenames, flags); } } @@ -1688,8 +1717,15 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) /* Likewise for the constexpr specifier, in case t is a specialization. */ constexpr_p = DECL_DECLARED_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) { @@ -1701,6 +1737,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; } } @@ -1710,8 +1749,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)); @@ -1749,13 +1788,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)) { @@ -1802,26 +1842,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 @@ -1968,13 +1988,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 @@ -1989,6 +2031,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); @@ -1998,10 +2042,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); @@ -2026,25 +2071,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_("