diff options
author | Matthias Kretz <kretz@kde.org> | 2021-05-27 17:25:37 +0200 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2021-05-27 17:00:38 -0400 |
commit | c33ec196aa713c62d73907dc8f9e57d7ab2e4e4b (patch) | |
tree | 375bd623fffa857993da6ea84d2af838d029c2d8 /gcc | |
parent | 27e906d5bb2e46e59fe4aa137317f3c8d49ecb44 (diff) | |
download | gcc-c33ec196aa713c62d73907dc8f9e57d7ab2e4e4b.zip gcc-c33ec196aa713c62d73907dc8f9e57d7ab2e4e4b.tar.gz gcc-c33ec196aa713c62d73907dc8f9e57d7ab2e4e4b.tar.bz2 |
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/error.c | 63 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/diagnostic/pr100716-1.C | 54 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/diagnostic/pr100716.C | 54 |
3 files changed, 156 insertions, 15 deletions
diff --git a/gcc/cp/error.c b/gcc/cp/error.c index ae78b10..4a89b34 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<tree, va_gc> *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_("<missing>")); ++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<tree, va_gc> *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 0000000..93490da --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/pr100716-1.C @@ -0,0 +1,54 @@ +// { dg-options "-fno-pretty-templates" } + +template<typename T> + struct A + { + template<typename U> + void f() {} // { dg-line Af } + + template<typename U> + void g(U) {} // { dg-line Ag } + }; + +template<typename T> + struct B + { + template<typename U> + void f(U) {} // { dg-line Bf } + + template<typename U> + void g(U, T) {} // { dg-line Bg } + }; + +struct C +{ + template<typename U> + void f(U) {} // { dg-line Cf } + + template<typename U> + void g() {} // { dg-line Cg } +}; + +int main() +{ + A<int>().f(0); // { dg-error "no matching function for call to 'A<int>::f\\(int\\)'" } + // { dg-message "candidate: 'template<class U> void A<int>::f\\(\\)'" "" { target *-*-* } Af } + + A<int>().g(); // { dg-error "no matching function for call to 'A<int>::g\\(\\)'" } + // { dg-message "candidate: 'template<class U> void A<int>::g\\(U\\)'" "" { target *-*-* } Ag } + + B<int>().f(); // { dg-error "no matching function for call to 'B<int>::f\\(\\)'" } + // { dg-message "candidate: 'template<class U> void B<int>::f\\(U\\)'" "" { target *-*-* } Bf } + + B<int>().g(); // { dg-error "no matching function for call to 'B<int>::g\\(\\)'" } + // { dg-message "candidate: 'template<class U> void B<int>::g\\(U, int\\)'" "" { target *-*-* } Bg } + + B<float>().g(0); // { dg-error "no matching function for call to 'B<float>::g\\(int\\)'" } + // { dg-message "candidate: 'template<class U> void B<float>::g\\(U, float\\)'" "" { target *-*-* } Bg } + + C().f(); // { dg-error "no matching function for call to 'C::f\\(\\)'" } + // { dg-message "candidate: 'template<class U> void C::f\\(U\\)'" "" { target *-*-* } Cf } + + C().g(0); // { dg-error "no matching function for call to 'C::g\\(int\\)'" } + // { dg-message "candidate: 'template<class U> 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 0000000..4a1f0a4 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/pr100716.C @@ -0,0 +1,54 @@ +// { dg-options "-fpretty-templates" } + +template<typename T> + struct A + { + template<typename U> + void f() {} // { dg-line Af } + + template<typename U> + void g(U) {} // { dg-line Ag } + }; + +template<typename T> + struct B + { + template<typename U> + void f(U) {} // { dg-line Bf } + + template<typename U> + void g(U, T) {} // { dg-line Bg } + }; + +struct C +{ + template<typename U> + void f(U) {} // { dg-line Cf } + + template<typename U> + void g() {} // { dg-line Cg } +}; + +int main() +{ + A<int>().f(0); // { dg-error "no matching function for call to 'A<int>::f\\(int\\)'" } + // { dg-message "candidate: 'template<class U> void A<T>::f\\(\\) \\\[with T = int\\\]'" "" { target *-*-* } Af } + + A<int>().g(); // { dg-error "no matching function for call to 'A<int>::g\\(\\)'" } + // { dg-message "candidate: 'template<class U> void A<T>::g\\(U\\) \\\[with T = int\\\]'" "" { target *-*-* } Ag } + + B<int>().f(); // { dg-error "no matching function for call to 'B<int>::f\\(\\)'" } + // { dg-message "candidate: 'template<class U> void B<T>::f\\(U\\) \\\[with T = int\\\]'" "" { target *-*-* } Bf } + + B<int>().g(); // { dg-error "no matching function for call to 'B<int>::g\\(\\)'" } + // { dg-message "candidate: 'template<class U> void B<T>::g\\(U, T\\) \\\[with T = int\\\]'" "" { target *-*-* } Bg } + + B<float>().g(0); // { dg-error "no matching function for call to 'B<float>::g\\(int\\)'" } + // { dg-message "candidate: 'template<class U> void B<T>::g\\(U, T\\) \\\[with T = float\\\]'" "" { target *-*-* } Bg } + + C().f(); // { dg-error "no matching function for call to 'C::f\\(\\)'" } + // { dg-message "candidate: 'template<class U> void C::f\\(U\\)'" "" { target *-*-* } Cf } + + C().g(0); // { dg-error "no matching function for call to 'C::g\\(int\\)'" } + // { dg-message "candidate: 'template<class U> void C::g\\(\\)'" "" { target *-*-* } Cg } +} |