From: Matthias Kretz Date: Thu, 27 May 2021 15:25:37 +0000 (+0200) Subject: c++: Output less irrelevant info for function template decl [PR100716] X-Git-Tag: basepoints/gcc-13~7213 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c33ec196aa713c62d73907dc8f9e57d7ab2e4e4b;p=thirdparty%2Fgcc.git c++: Output less irrelevant info for function template decl [PR100716] Ensure dump_template_decl for function templates never prints template parameters after the function name (it did with -fno-pretty-templates) and skip output of irrelevant & confusing "[with T = T]" in dump_substitution. gcc/cp/ChangeLog: PR c++/100716 * error.c (dump_template_bindings): Include code to print "[with" and ']', conditional on whether anything is printed at all. This is tied to whether a semicolon is needed to separate multiple template parameters. If the template argument repeats the template parameter (T = T), then skip the parameter. (dump_substitution): Moved code to print "[with" and ']' to dump_template_bindings. (dump_function_decl): Partial revert of PR50828, which masked TFF_TEMPLATE_NAME for all of dump_function_decl. Now TFF_TEMPLATE_NAME is masked for the scope of the function and only carries through to dump_function_name. (dump_function_name): Avoid calling dump_template_parms if TFF_TEMPLATE_NAME is set. gcc/testsuite/ChangeLog: PR c++/100716 * g++.dg/diagnostic/pr100716.C: New test. * g++.dg/diagnostic/pr100716-1.C: Same test with -fno-pretty-templates. --- diff --git a/gcc/cp/error.c b/gcc/cp/error.c index ae78b10c7b2e..4a89b3488291 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -371,7 +371,35 @@ static void dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, vec *typenames) { - bool need_semicolon = false; + /* Print "[with" and ']', conditional on whether anything is printed at all. + This is tied to whether a semicolon is needed to separate multiple template + parameters. */ + struct prepost_semicolon + { + cxx_pretty_printer *pp; + bool need_semicolon; + + void operator() () + { + if (need_semicolon) + pp_separate_with_semicolon (pp); + else + { + pp_cxx_whitespace (pp); + pp_cxx_left_bracket (pp); + pp->translate_string ("with"); + pp_cxx_whitespace (pp); + need_semicolon = true; + } + } + + ~prepost_semicolon () + { + if (need_semicolon) + pp_cxx_right_bracket (pp); + } + } semicolon_or_introducer = {pp, false}; + int i; tree t; @@ -395,10 +423,20 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, if (lvl_args && NUM_TMPL_ARGS (lvl_args) > arg_idx) arg = TREE_VEC_ELT (lvl_args, arg_idx); - if (need_semicolon) - pp_separate_with_semicolon (pp); - dump_template_parameter (pp, TREE_VEC_ELT (p, i), - TFF_PLAIN_IDENTIFIER); + 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 + && DECL_NAME (TREE_VALUE (parm_i)) + == DECL_NAME (TREE_CHAIN (arg))) + continue; + + semicolon_or_introducer (); + dump_template_parameter (pp, parm_i, TFF_PLAIN_IDENTIFIER); pp_cxx_whitespace (pp); pp_equal (pp); pp_cxx_whitespace (pp); @@ -414,7 +452,6 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, pp_string (pp, M_("")); ++arg_idx; - need_semicolon = true; } parms = TREE_CHAIN (parms); @@ -436,8 +473,7 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, FOR_EACH_VEC_SAFE_ELT (typenames, i, t) { - if (need_semicolon) - pp_separate_with_semicolon (pp); + semicolon_or_introducer (); dump_type (pp, t, TFF_PLAIN_IDENTIFIER); pp_cxx_whitespace (pp); pp_equal (pp); @@ -1599,12 +1635,7 @@ dump_substitution (cxx_pretty_printer *pp, && !(flags & TFF_NO_TEMPLATE_BINDINGS)) { vec *typenames = t ? find_typenames (t) : NULL; - pp_cxx_whitespace (pp); - pp_cxx_left_bracket (pp); - pp->translate_string ("with"); - pp_cxx_whitespace (pp); dump_template_bindings (pp, template_parms, template_args, typenames); - pp_cxx_right_bracket (pp); } } @@ -1645,7 +1676,8 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) bool constexpr_p; tree ret = NULL_TREE; - flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME); + int dump_function_name_flags = flags & ~TFF_UNQUALIFIED_NAME; + flags = dump_function_name_flags & ~TFF_TEMPLATE_NAME; if (TREE_CODE (t) == TEMPLATE_DECL) t = DECL_TEMPLATE_RESULT (t); @@ -1723,7 +1755,7 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) else dump_scope (pp, CP_DECL_CONTEXT (t), flags); - dump_function_name (pp, t, flags); + dump_function_name (pp, t, dump_function_name_flags); if (!(flags & TFF_NO_FUNCTION_ARGUMENTS)) { @@ -1937,6 +1969,7 @@ dump_function_name (cxx_pretty_printer *pp, tree t, int flags) dump_module_suffix (pp, t); 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)))) diff --git a/gcc/testsuite/g++.dg/diagnostic/pr100716-1.C b/gcc/testsuite/g++.dg/diagnostic/pr100716-1.C new file mode 100644 index 000000000000..93490da6a83a --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/pr100716-1.C @@ -0,0 +1,54 @@ +// { dg-options "-fno-pretty-templates" } + +template + struct A + { + template + void f() {} // { dg-line Af } + + template + void g(U) {} // { dg-line Ag } + }; + +template + struct B + { + template + void f(U) {} // { dg-line Bf } + + template + void g(U, T) {} // { dg-line Bg } + }; + +struct C +{ + template + void f(U) {} // { dg-line Cf } + + template + void g() {} // { dg-line Cg } +}; + +int main() +{ + A().f(0); // { dg-error "no matching function for call to 'A::f\\(int\\)'" } + // { dg-message "candidate: 'template void A::f\\(\\)'" "" { target *-*-* } Af } + + A().g(); // { dg-error "no matching function for call to 'A::g\\(\\)'" } + // { dg-message "candidate: 'template void A::g\\(U\\)'" "" { target *-*-* } Ag } + + B().f(); // { dg-error "no matching function for call to 'B::f\\(\\)'" } + // { dg-message "candidate: 'template void B::f\\(U\\)'" "" { target *-*-* } Bf } + + B().g(); // { dg-error "no matching function for call to 'B::g\\(\\)'" } + // { dg-message "candidate: 'template void B::g\\(U, int\\)'" "" { target *-*-* } Bg } + + B().g(0); // { dg-error "no matching function for call to 'B::g\\(int\\)'" } + // { dg-message "candidate: 'template void B::g\\(U, float\\)'" "" { target *-*-* } Bg } + + C().f(); // { dg-error "no matching function for call to 'C::f\\(\\)'" } + // { dg-message "candidate: 'template void C::f\\(U\\)'" "" { target *-*-* } Cf } + + C().g(0); // { dg-error "no matching function for call to 'C::g\\(int\\)'" } + // { dg-message "candidate: 'template void C::g\\(\\)'" "" { target *-*-* } Cg } +} diff --git a/gcc/testsuite/g++.dg/diagnostic/pr100716.C b/gcc/testsuite/g++.dg/diagnostic/pr100716.C new file mode 100644 index 000000000000..4a1f0a4e10a3 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/pr100716.C @@ -0,0 +1,54 @@ +// { dg-options "-fpretty-templates" } + +template + struct A + { + template + void f() {} // { dg-line Af } + + template + void g(U) {} // { dg-line Ag } + }; + +template + struct B + { + template + void f(U) {} // { dg-line Bf } + + template + void g(U, T) {} // { dg-line Bg } + }; + +struct C +{ + template + void f(U) {} // { dg-line Cf } + + template + void g() {} // { dg-line Cg } +}; + +int main() +{ + A().f(0); // { dg-error "no matching function for call to 'A::f\\(int\\)'" } + // { dg-message "candidate: 'template void A::f\\(\\) \\\[with T = int\\\]'" "" { target *-*-* } Af } + + A().g(); // { dg-error "no matching function for call to 'A::g\\(\\)'" } + // { dg-message "candidate: 'template void A::g\\(U\\) \\\[with T = int\\\]'" "" { target *-*-* } Ag } + + B().f(); // { dg-error "no matching function for call to 'B::f\\(\\)'" } + // { dg-message "candidate: 'template void B::f\\(U\\) \\\[with T = int\\\]'" "" { target *-*-* } Bf } + + B().g(); // { dg-error "no matching function for call to 'B::g\\(\\)'" } + // { dg-message "candidate: 'template void B::g\\(U, T\\) \\\[with T = int\\\]'" "" { target *-*-* } Bg } + + B().g(0); // { dg-error "no matching function for call to 'B::g\\(int\\)'" } + // { dg-message "candidate: 'template void B::g\\(U, T\\) \\\[with T = float\\\]'" "" { target *-*-* } Bg } + + C().f(); // { dg-error "no matching function for call to 'C::f\\(\\)'" } + // { dg-message "candidate: 'template void C::f\\(U\\)'" "" { target *-*-* } Cf } + + C().g(0); // { dg-error "no matching function for call to 'C::g\\(int\\)'" } + // { dg-message "candidate: 'template void C::g\\(\\)'" "" { target *-*-* } Cg } +}