On 11/8/21 11:40, Matthias Kretz wrote:
On Tuesday, 17 August 2021 20:31:54 CET Jason Merrill wrote:
2. Given a DECL_TI_ARGS tree, can I query whether an argument was deduced
or explicitly specified? I'm asking because I still consider diagnostics
of function templates unfortunate. `template <class T> void f()` is fine,
as is `void f(T) [with T = float]`, but `void f() [with T = float]` could
be better. I.e. if the template parameter appears somewhere in the
function parameter list, dump_template_parms would only produce noise.
If, however, the template parameter was given explicitly, it would be
nice if it could show up accordingly in diagnostics.

NON_DEFAULT_TEMPLATE_ARGS_COUNT has that information, though there are
some issues with it.  Attached is my WIP from May to improve it
somewhat, if that's interesting.

It is interesting. I used your patch to come up with the attached. Patch. I
must say, I didn't try to read through all the cp/pt.c code to understand all
of what you did there (which is why my ChangeLog entry says "Jason?"), but it
works for me (and all of `make check`).

Anyway, I'd like to propose the following before finishing my diagnose_as
patch. I believe it's useful to fix this part first. The diagnostic/default-
template-args-[12].C tests show a lot of examples of the intent of this patch.
And the remaining changes to the testsuite show how it changes diagnostic
output.

---------------------- 8< --------------------

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.

Signed-off-by: Matthias Kretz <m.kr...@gsi.de>

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.
         * g++.dg/diagnostic/default-template-args-2.C: New.
         * 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:

         * cp-tree.h (GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT): Return
         absolute value of stored constant.
         (EXPLICIT_TEMPLATE_ARGS_P): New.
         (SET_EXPLICIT_TEMPLATE_ARGS_P): New.
         (TFF_AS_PRIMARY): New constant.
         * error.c (get_non_default_template_args_count): Avoid
         GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT if
         NON_DEFAULT_TEMPLATE_ARGS_COUNT is a NULL_TREE. 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.
         (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.
         (dump_function_name): Add and document conditions for calling
         dump_template_parms.
         (dump_template_parms): Print only non-default template
         parameters.
         * pt.c (determine_specialization): Jason?

Also copy the inner TREE_VECs.

         (template_parms_level_to_args): Jason?

Always count non-default args.  Also, I think

-  if (CHECKING_P)
-    SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
+  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, nondefault);

should have been

if (CHECKING_P || nondefault != TREE_VEC_LENGTH (a))
  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, nondefault);

         (copy_template_args): Jason?

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): Jason?

Count non-default args sooner.

         (get_partial_spec_bindings): Jason?

Set non-default args count.

         (tsubst_template_args): Determine number of defaulted arguments
         from new argument vector, if possible.
---
  gcc/cp/cp-tree.h                              | 18 +++-
  gcc/cp/error.c                                | 83 ++++++++++++++-----
  gcc/cp/pt.c                                   | 58 +++++++++----
  .../g++.dg/debug/dwarf2/template-params-12n.C |  2 +-
  .../diagnostic/default-template-args-1.C      | 73 ++++++++++++++++
  .../diagnostic/default-template-args-2.C      | 37 +++++++++
  .../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 +-
  13 files changed, 242 insertions(+), 55 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


+  /* Pretty print only template instantiations. Don't pretty print explicit
+     specializations like 'template <> void fun<int> (int)'.  */

This seems like a significant change of behavior unrelated to printing default template arguments. What's the rationale for handling specializations differently from instantiations?

I also don't understand the purpose of TFF_AS_PRIMARY.

+/* Print function template parameters if:
+   1. t is template, and
+   2. flags did not request "show only template-name", and
+   3. t is a specialization of a template (Why is this needed? This was present
+      since 1999 via !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION: "Don't crash 
if
+      given a friend pseudo-instantiation". The DECL_USE_TEMPLATE should likely
+      inform the PRIMARY parameter of dump_template_parms.), and

Good question. It seems that the existing !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION has mostly been excluding the most general template; removing that line changes things like

int bar(T) [with T = int]

to

int bar<T>(T) [with T = int]

+   4. either
+      - flags requests to show no function arguments, in which case deduced
+        types could be hidden, or
+      - at least one function template argument was given explicitly, or
+      - we're printing a DWARF name,

...but perhaps this can replace the above. Though, why do we want different behavior here when printing a DWARF name?

+   5. either
+      - t is a member friend template of a template class (see DECL_TI_TEMPLATE
+        documentation), or
+ -

Missing the last item.  :)

+ */

*/ doesn't get its own line.

   if (DECL_TEMPLATE_INFO (t)
       && !(flags & TFF_TEMPLATE_NAME)
-      && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t)
+      && DECL_USE_TEMPLATE (t)
+      && ((flags & TFF_NO_FUNCTION_ARGUMENTS)
+           || (DECL_TI_ARGS (t)
+                 && EXPLICIT_TEMPLATE_ARGS_P (INNERMOST_TEMPLATE_ARGS
+                                                (DECL_TI_ARGS (t))))
+           || (pp->flags & pp_c_flag_gnu_v3) != 0)
       && (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);
+    dump_template_parms (pp, DECL_TEMPLATE_INFO (t), false, flags);


Jason

Reply via email to