Re: [PATCH] dwarf2out: Emit DWARF 6 DW_AT_language_{name,version}

Mark Wielaard <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gdb.devel
Message-ID <[email protected]>
Hi Jakub,

On Tue, 2025-01-07 at 20:22 +0100, Jakub Jelinek wrote:
> DWARF has voted in yesterday https://dwarfstd.org/issues/241209.1.html ,
> which is basically just a guarantee that the DWARF 6 draft
> DW_AT_language_{name,version} attribute codes and content of
> https://dwarfstd.org/languages-v6.html can be used as an extension
> in DWARF 5 and won't be changed.
> 
> So, this patch is an alternative to the
> https://gcc.gnu.org/pipermail/gcc-patches/2024-November/669671.html
> patch, which had the major problem that it required changing all the
> DWARF consumers to be able to debug C17 or later or C++17 or later
> sources.

Note that most consumers (binutils, gdb, systemtap, valgrind, elfutils)
have already been updated to use the new DW_LANG constants. We can
easily backport that to the last stable releases before gcc 15 is
released.

> This patch uses still DWARF 5 DW_LANG_C11 or DW_LANG_C_plus_plus_14,
> the latest code in DWARF 5 proper, so all DWARF 5 capable consumers
> should be able to deal with that, but additionally emits the
> DWARF 6 attributes so that newer DWARF consumers can see it isn't
> just C++14 but say C++23 or C11 but C23.  Consumers which don't know
> those DWARF 6 attributes would just ignore them.  This is like any other
> -gno-strict-dwarf extension, except that normally we emit say DWARF 5
> codes where possible only after DWARF 5 is released, while in this case
> there is a guarantee it can be used before DWARF 6 is released.

Code looks ok to me, it is only for C and C++, would be nice to at
least get it for Fortran and Ada too.

> --- gcc/dwarf2out.cc.jj	2025-01-02 11:23:35.541251268 +0100
> +++ gcc/dwarf2out.cc	2025-01-07 10:09:16.866866563 +0100
> @@ -8755,6 +8755,14 @@ break_out_comdat_types (dw_die_ref die)
>          unit = new_die (DW_TAG_type_unit, NULL, NULL);
>          add_AT_unsigned (unit, DW_AT_language,
>                           get_AT_unsigned (comp_unit_die (), DW_AT_language));
> +	if (unsigned lname = get_AT_unsigned (comp_unit_die (),
> +					      DW_AT_language_name))
> +	  {
> +	    add_AT_unsigned (unit, DW_AT_language_name, lname);
> +	    add_AT_unsigned (unit, DW_AT_language_version,
> +			     get_AT_unsigned (comp_unit_die (),
> +					      DW_AT_language_version));
> +	  }

This relies on language_name and language_version always being set
together. Which is the case in the code at this time. Should we assert
that?

> @@ -25376,11 +25388,28 @@ gen_compile_unit_die (const char *filena
>  	    language = DW_LANG_C99;
>  
>  	  if (dwarf_version >= 5 /* || !dwarf_strict */)
> -	    if (strcmp (language_string, "GNU C11") == 0
> -		|| strcmp (language_string, "GNU C17") == 0
> -		|| strcmp (language_string, "GNU C23") == 0
> -		|| strcmp (language_string, "GNU C2Y") == 0)
> -	      language = DW_LANG_C11;
> +	    {
> +	      if (strcmp (language_string, "GNU C11") == 0)
> +		language = DW_LANG_C11;
> +	      else if (strcmp (language_string, "GNU C17") == 0)
> +		{
> +		  language = DW_LANG_C11;
> +		  lname = DW_LNAME_C;
> +		  lversion = 201710;
> +		}
> +	      else if (strcmp (language_string, "GNU C23") == 0)
> +		{
> +		  language = DW_LANG_C11;
> +		  lname = DW_LNAME_C;
> +		  lversion = 202311;
> +		}
> +	      else if (strcmp (language_string, "GNU C2Y") == 0)
> +		{
> +		  language = DW_LANG_C11;
> +		  lname = DW_LNAME_C;
> +		  lversion = 202500;
> +		}
> +	    }

The use of language_string (lang_hooks.name) is a little clumsy, but
already part of the current code. In the future it would be nice to
have separate language and version hooks for this.

Personally I would just go with the new DW_LANG_C17/C23 language code,
they will be supported by consumers when gcc 15 is released.

The 00 for the month in C2Y is clever. Does that match the
__STDC_VERSION__ defined?

> @@ -25392,12 +25421,30 @@ gen_compile_unit_die (const char *filena
>  	    language = DW_LANG_C_plus_plus_11;
>  	  else if (strcmp (language_string, "GNU C++14") == 0)
>  	    language = DW_LANG_C_plus_plus_14;
> -	  else if (strcmp (language_string, "GNU C++17") == 0
> -		   || strcmp (language_string, "GNU C++20") == 0
> -		   || strcmp (language_string, "GNU C++23") == 0
> -		   || strcmp (language_string, "GNU C++26") == 0)
> -	    /* For now.  */
> -	    language = DW_LANG_C_plus_plus_14;
> +	  else if (strcmp (language_string, "GNU C++17") == 0)
> +	    {
> +	      language = DW_LANG_C_plus_plus_14;
> +	      lname = DW_LNAME_C_plus_plus;
> +	      lversion = 201703;
> +	    }
> +	  else if (strcmp (language_string, "GNU C++20") == 0)
> +	    {
> +	      language = DW_LANG_C_plus_plus_14;
> +	      lname = DW_LNAME_C_plus_plus;
> +	      lversion = 202002;
> +	    }
> +	  else if (strcmp (language_string, "GNU C++23") == 0)
> +	    {
> +	      language = DW_LANG_C_plus_plus_14;
> +	      lname = DW_LNAME_C_plus_plus;
> +	      lversion = 202302;
> +	    }
> +	  else if (strcmp (language_string, "GNU C++26") == 0)
> +	    {
> +	      language = DW_LANG_C_plus_plus_14;
> +	      lname = DW_LNAME_C_plus_plus;
> +	      lversion = 202400;
> +	    }

Why 202400 and not 202600?

Cheers,

Mark
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.