Skip to content

Conversation

@ecatmur
Copy link
Owner

@ecatmur ecatmur commented Jul 17, 2022

Per http://wiki.dwarfstd.org/index.php?title=C%2B%2B0x:_Variadic_templates DW_TAG_GNU_formal_parameter_pack should have a DW_AT_name:

17$: DW_TAG_formal_parameter_pack
DW_AT_name("args")
18$: DW_TAG_formal_parameter
! no DW_AT_name attribute
DW_AT_type(reference to 13$)
(...)

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70536

Send command:

git send-email -1 --to gcc-patches@gcc.gnu.org --subject-prefix "PATCH v3"

@mistarro
Copy link

mistarro commented Jan 9, 2023

Hi, what is the status of this change? I have a lot of variadic templated code to debug and it seems this is part of the solution... Is there anything I could help with?

@ecatmur
Copy link
Owner Author

ecatmur commented Jan 10, 2023

I submitted it upstream: https://gcc.gnu.org/pipermail/gcc-patches/2022-March/591678.html

Unfortunately I don't have the email to ping. I'll try submitting again.

@ecatmur
Copy link
Owner Author

ecatmur commented Jan 10, 2023

Resent: https://gcc.gnu.org/pipermail/gcc-patches/2023-January/609659.html
If you want, you could join the ML and ping it occasionally: https://gcc.gnu.org/mailman/listinfo/gcc-patches

@mistarro
Copy link

mistarro commented Jan 11, 2023

Thanks for the quick reply. I'm wondering also about gdb part as per your answer in https://stackoverflow.com/questions/36407941/inspect-template-parameter-pack-in-gdb (and your patch attached to https://sourceware.org/bugzilla/show_bug.cgi?id=17272). Do you have github fork for that as well? I guess this is a bit harder to update as there are some changes to gdb code. I tried myself to "blindly" merge but it didn't work (g++ compiled with the patch emitted names properly but of course it needs proper handling on gdb side): gdb worked but the symbols were not visible so I guess I could have made something wrong.

I work on heavily templated C++20 based library and support for variadic templates would greatly improve debugging experience. For now I use workaround to step into std::forward part which is repeated when preparing arguments but this still involves guessing the order.

@ecatmur
Copy link
Owner Author

ecatmur commented Jan 14, 2023

Do you have github fork for that as well? I guess this is a bit harder to update as there are some changes to gdb code. I tried myself to "blindly" merge but it didn't work (g++ compiled with the patch emitted names properly but of course it needs proper handling on gdb side): gdb worked but the symbols were not visible so I guess I could have made something wrong.

Yes, see ecatmur/binutils-gdb#1. It took a little perseverance to get the patch through the various changes that have been made, but it should work now.

ecatmur added a commit to ecatmur/binutils-gdb that referenced this pull request Feb 4, 2023
…meter_pack

This patch adds support for DW_TAG_GNU_formal_parameter_pack and
DW_TAG_GNU_template_parameter_pack, added to DWARF in March 2009 for
C++11 variadic templates[1].

They are not currently emitted thanks to a typo[2] but the fix is
trivial[3] and has been repeatedly submitted[4] to gcc; I'm not sure
what else I can do to get it accepted; regardless, anyone building their
own compiler can still make use of this.

This implementation synthesizes type and parameter names as T#n, p#n
e.g. Args#1, args#1. This is a pretty simple approach but it seems to
work OK and is compatible with the old style type and parameter names
emitted by old versions of gcc and when it's writing stabs+ format,
meaning that any debugger scripts will continue to work.

1. http://wiki.dwarfstd.org/index.php?title=C%2B%2B0x:_Variadic_templates
2. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70536
3. ecatmur/gcc#5
4. https://gcc.gnu.org/pipermail/gcc-patches/2023-January/609659.html
PR. https://sourceware.org/bugzilla/show_bug.cgi?id=17272
ecatmur added a commit to ecatmur/binutils-gdb that referenced this pull request Feb 4, 2023
This patch adds support for DW_TAG_GNU_formal_parameter_pack and
DW_TAG_GNU_template_parameter_pack, added to DWARF in March 2009 for
C++11 variadic templates[1].

They are not currently emitted thanks to a typo[2] but the fix is
trivial[3] and has been repeatedly submitted[4] to gcc; I'm not sure
what else I can do to get it accepted; regardless, anyone building their
own compiler can still make use of this.

This implementation synthesizes type and parameter names as T#n, p#n
e.g. Args#1, args#1. This is a pretty simple approach but it seems to
work OK and is compatible with the old style type and parameter names
emitted by old versions of gcc and when it's writing stabs+ format,
meaning that any debugger scripts will continue to work.

1. http://wiki.dwarfstd.org/index.php?title=C%2B%2B0x:_Variadic_templates
2. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70536
3. ecatmur/gcc#5
4. https://gcc.gnu.org/pipermail/gcc-patches/2023-January/609659.html
PR. https://sourceware.org/bugzilla/show_bug.cgi?id=17272
ecatmur added a commit to ecatmur/binutils-gdb that referenced this pull request Feb 4, 2023
This patch adds support for DW_TAG_GNU_formal_parameter_pack and
DW_TAG_GNU_template_parameter_pack, added to DWARF in March 2009 for
C++11 variadic templates[1].

They are not currently emitted thanks to a typo[2] but the fix is
trivial[3] and has been repeatedly submitted[4] to gcc; I'm not sure
what else I can do to get it accepted; regardless, anyone building their
own compiler can still make use of this.

This implementation synthesizes type and parameter names as T#n, p#n
e.g. Args#1, args#1. This is a pretty simple approach but it seems to
work OK and is compatible with the old style type and parameter names
emitted by old versions of gcc and when it's writing stabs+ format,
meaning that any debugger scripts will continue to work.

1. http://wiki.dwarfstd.org/index.php?title=C%2B%2B0x:_Variadic_templates
2. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70536
3. ecatmur/gcc#5
4. https://gcc.gnu.org/pipermail/gcc-patches/2023-January/609659.html
PR. https://sourceware.org/bugzilla/show_bug.cgi?id=17272
Per http://wiki.dwarfstd.org/index.php?title=C%2B%2B0x:_Variadic_templates DW_TAG_GNU_formal_parameter_pack should have a DW_AT_name:

17$:      DW_TAG_formal_parameter_pack
              DW_AT_name("args")
18$:          DW_TAG_formal_parameter
                  ! no DW_AT_name attribute
                  DW_AT_type(reference to 13$)
(...)

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70536
@ecatmur
Copy link
Owner Author

ecatmur commented Feb 4, 2023

Resubmitted: https://gcc.gnu.org/pipermail/gcc-patches/2023-February/611366.html
Hopefully this time I'll remember to save the email for pinging.

ecatmur pushed a commit that referenced this pull request May 17, 2023
I noticed that for member class templates of a class template we were
unnecessarily substituting both the template and its type.  Avoiding that
duplication speeds compilation of this silly testcase from ~12s to ~9s on my
laptop.  It's unlikely to make a difference on any real code, but the
simplification is also nice.

We still need to clear CLASSTYPE_USE_TEMPLATE on the partial instantiation
of the template class, but it makes more sense to do that in
tsubst_template_decl anyway.

  #define NC(X)					\
    template <class U> struct X##1;		\
    template <class U> struct X##2;		\
    template <class U> struct X##3;		\
    template <class U> struct X##4;		\
    template <class U> struct X##5;		\
    template <class U> struct X##6;
  #define NC2(X) NC(X##a) NC(X##b) NC(X##c) NC(X##d) NC(X##e) NC(X##f)
  #define NC3(X) NC2(X##A) NC2(X##B) NC2(X##C) NC2(X##D) NC2(X##E)
  template <int I> struct A
  {
    NC3(am)
  };
  template <class...Ts> void sink(Ts...);
  template <int...Is> void g()
  {
    sink(A<Is>()...);
  }
  template <int I> void f()
  {
    g<__integer_pack(I)...>();
  }
  int main()
  {
    f<1000>();
  }

gcc/cp/ChangeLog:

	* pt.cc (instantiate_class_template): Skip the RECORD_TYPE
	of a class template.
	(tsubst_template_decl): Clear CLASSTYPE_USE_TEMPLATE.
@mistarro
Copy link

mistarro commented Jun 24, 2024

I've investigated the issue a bit deeper recently as I discovered that the following code snippet is partially supported by the official GCC release (tested on 14.1 only):

template <typename ... Us>
struct A {
  static int f(Us ... us) {
    return 0; // breakpoint
  }
};

template <typename ... Ts>
int g(Ts ... ts) {
  return A<Ts ...>::f(ts ...);
}

int main() {
  return g(1, 2.5);
}

with (unpatched) GDB stacktrace for the breakpoint at line 4:

#0  A<int, double>::f (us#0=1, us#1=2.5) at vt.cpp:4
#1  0x0000555555555171 in g<int, double> () at vt.cpp:10
#2  0x0000555555555147 in main () at vt.cpp:14

It seems that the issue with variadic parameters is only for function templates (f is not one). After examining gimple output, it's clear that the names for parameters are already there, they are just not exported in respective DIEs:

main ()
{
  int D.2099;

  D.2099 = g<int, double> (1, 2.5e+0);
  return D.2099;
  D.2099 = 0;
  return D.2099;
}


g<int, double> (int ts#0, double ts#1)
{
  int D.2102;

  D.2102 = A<int, double>::f (ts#0, ts#1);
  return D.2102;
}


A<int, double>::f (int us#0, double us#1)
{
  int D.2104;

  D.2104 = 0;
  return D.2104;
}

It's tempting to just change false to true just below your change (to emit names) but the problem is that GDB does not support it (DW_TAG_formal_parameter DIEs should appear directly under the respective DW_TAG_subprogram DIE).
So instead, I modified while (generic_decl_parm || parm) loop at gcc/dwarf2out.cc:24103 to just export all the DW_TAG_formal_parameter DIEs and separately all the DW_TAG_GNU_formal_parameter_pack DIEs (separate loop) without exporting formal parameters again:

      // emit all formal parameter packs
      while (generic_decl_parm)
	{
	  if (lang_hooks.function_parameter_pack_p (generic_decl_parm))
	    gen_formal_parameter_pack_die (generic_decl_parm, NULL, subr_die,
					   NULL);
	  generic_decl_parm = DECL_CHAIN (generic_decl_parm);
	}

      // emit all formal parameters
      while (parm)
	{
	  dw_die_ref parm_die = gen_decl_die (parm, NULL, NULL, subr_die);

	  if (early_dwarf
	      && parm == DECL_ARGUMENTS (decl)
	      && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
	      && parm_die
	      && (dwarf_version >= 3 || !dwarf_strict))
	    add_AT_die_ref (subr_die, DW_AT_object_pointer, parm_die);

	  parm = DECL_CHAIN (parm);
	}

This seems to work as expected (also with mixed normal + variadic parameters) with official GDB.

@mistarro
Copy link

mistarro commented Jun 24, 2024

BTW, VSCode and Eclipse have a problem debugging when symbols contain # character (most probably they don't quote symbol strings) so I also changed # to $ when generating parameter names in function make_ith_pack_parameter_name in file gcc/cp/pt.cc (line 3599 for release 14.1.0). Do you think this change would break anything? The $ sign is allowed in symbols as opposed to #.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants