On Wednesday, 17 November 2021 07:09:18 CET Jason Merrill wrote: > > - 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);
TBH, I don't understand the purpose of CHECKING_P here, or rather it makes me nervous because AFAIU I'm only testing with CHECKING_P enabled. Why make behavior dependent on CHECKING_P? I expected CHECKING_P to basically only add more assertions. > > (copy_template_args): Jason? > > Only copy the non-default template args count on TREE_VECs that should > have it. Why not simply set the count on all args? Is it a performance concern? The INTEGER_CST the TREE_CHAIN has to point to exists anyway, so it's not wasting any memory, right? > > > + /* 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? Right, this is about "The general idea of this change is to print template parms wherever they would appear in the source code as well". Initially, the change to print function template arguments/parameters only if the args were explicitly specified lead to printing 'void fun (T) [with T = ...]' or 'template <> void fun (int)'. Both are not telling the full story, even if the former is how the function would be called. But if the reader should quickly recognize what code is getting called, it is helpful to see right away that a function template specialization is called. (It might also reveal an implementation detail of a library, so it's not 100% obvious how to choose here.) Also, saying 'T = int' is kind of wrong. Yes, 'int' was deduced. But there's no T in fun<int>: template <class T> void fun (T); template <> void fun<int> (int); __FUNCTION__ was 'fun<int>' all the time, but __PRETTY_FUNCTION__ was 'void fun(T) [with T = int]'. It's more consistent that __PRETTY_FUNCTION__ contains __FUNCTION__, IMHO, so it would have to be at least 'void fun<int>(T) [with T = int]'. But that's strange: How it uses T and int for the same type. So I settled on 'void fun<int>(int)'. > I also don't understand the purpose of TFF_AS_PRIMARY. dump_function_decl generalizes the TEMPLATE_DECL (if flag_pretty_templates is true) and, before this change, passes the generalized TEMPLATE_DECL to dump_type (... DECL_CONTEXT (t) ...) and dump_function_name (... t ...). That's why the whole template is printed as primary template (i.e. with template parms instead of template args, as is needed for flag_pretty_templates). But this drops the count of non-default template args. To retain the count, dump_type and dump_function_name need to be called with the original TEMPLATE_DECL. But if I do this, pretty-templates is broken. 'template <class T> struct A { template <class U> void f(T, U); };' would print as 'A<int>::f<float>(T, U) [with U = float, T = int]'. To get back to 'A<T>::f<U>(T, U) [with U = float, T = int]' I needed to tell dump_template_parms that even though the template args are there, it should print only the template parms. The most obvious way to do that was to carry it through via flags. Note that this creates another problem. Given template <class T0, class T1 = int> struct Outer { template <class T, class U> struct A; template <class X> struct A<X, int> { void f(); }; }; we want to print e.g. 'void Outer<T0>::A<X, int>::f() [with X = int, T0 = int]', but certainly not 'void Outer<T0>::A<T, U>::f() [with X = int, T0 = int]'. However, specialized_t holds A<int, int> which is printed as A<T, U> with TFF_AS_PRIMARY. Only most_general_template of the function's TEMPLATE_DECL can give us A<X, int> as DECL_CONTEXT. I have a solution in the diagnose_as patch, where I had to solve a similar problem because for the diagnose_as attribute (dump_template_scope). > > +/* 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. I'll rerun the tests with DECL_USE_TEMPLATE moved to the PRIMARY parameter of dump_template_parms. > Though, why do we want > different behavior here when printing a DWARF name? Sorry, I should have asked ... I also added the same issue as an open question on the diagnose_as patch. When I ran the whole testsuite I had failures in the DWARF tests. This change resolved them. I don't know enough about how those strings are used and whether they may change between GCC versions. Anyway, the DWARF strings in that test had only the function name and template argument list (i.e. no function arguments). If the template argument list was removed (as was the case without the condition here), the DWARF strings lost important information, giving several different functions the same name. That seemed like a regression. So either the DWARF strings need to include the function arguments, or we need this condition to keep showing the template arguments independent of whether they were explicitly given or not. > > + 5. either > > + - t is a member friend template of a template class (see > > DECL_TI_TEMPLATE + documentation), or > > + - > > Missing the last item. :) Oh, I got distracted while trying to figure this out. :) I'll try to understand why PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t)) is needed and document it. -- ────────────────────────────────────────────────────────────────────────── Dr. Matthias Kretz https://mattkretz.github.io GSI Helmholtz Centre for Heavy Ion Research https://gsi.de stdₓ::simd ──────────────────────────────────────────────────────────────────────────