Re: [PATCH v4 5/8] Remove C++ special case from process_imported_unit_die

Tom de Vries
2026-02-24T09:19:30Z

On 2/24/26 2:16 AM, Tom Tromey wrote:
> process_imported_unit_die has a special case for C++, added as a
> performance improvement.
>
> While I somewhat agree with the general idea of this snippet --
> importing a compilation unit seems like a strange thing to do, given
> that partial units exist -- I think there are two issues with it.

Hi Tom,

this is the type of debuginfo generated by gcc for lto.

To briefly reiterate:
- at an early stage of compilation, type info is generated for each
compilation unit, resulting in a CU with only types, so no addresses.
- then lto optimization happens, resulting in one blob of code per
optimization unit (an lto partition), and debug info is generated for
that blob (a CU with name "<artifical>").
- the artificial CU imports the CUs in the partition.

Importing a CU feels strange to me, but the DWARF standard (quoting v4)
seems to allow it:
...
3.1.2 Imported Unit Entries
The place where a normal or partial unit is imported is represented by a
debugging information entry with the tag DW_TAG_imported_unit.

An imported unit entry contains a DW_AT_import attribute whose value is
a reference to the normal or partial compilation unit whose declarations
logically belong at the place of the imported unit entry.

An imported unit entry does not necessarily correspond to any entity or
construct in the source program. It is merely “glue” used to relate a
partial unit, or a compilation unit used as a partial unit, to a place
in some other compilation unit.
...

> First, it is specific to C++. I don't see any real reason that this
> should be the case.

I implemented the optimization for cases where I could prove it was safe.

For C++, we have a global namespace so importing the types from a CU
once or twice into the global namespace should have the same effect.

For C, each CU has it's own namespace, so each import is significant.

The DWARF standard refers to this difference here:
...
C Example
The C++ example in this Section might appear to be equally valid as a C
example. However, it is prudent to include a DW_TAG_imported_unit in the
primary unit (see Figure 84) with an DW_AT_import attribute that refers
to the proper unit in the section group.
The C rules for consistency of global (file scope) symbols across
compilations are less strict than for C++; inclusion of the import unit
attribute assures that the declarations of the proper section group are
considered before declarations from other compilations.
...

It could be that with the current implementation, this difference is no
longer relevant, I'm not sure.

> Second, it does not have a corresponding bit of code in the indexer.
> This means that the cooked index's view of the DWARF differs from the
> full reader's view here. This causes regressions in this series,
> because the indexer assumes that reading a CU will cause all the
> imported CUs to be read as a side effect -- but that does not happen
> here.
>
> I think fixing this in the indexer is not trivial. The reason for
> this is that the indexer works in parallel, and once a reader has
> acquired the "scan" bit for a CU, it is obligated to read it.
> However, in this case this would require making a new cooked indexer.
>

I see.

> Instead, because (1) this is weird and rare DWARF anyway, and (2) this
> is just a performance optimization, I propose removing this.

I agree removing it is the right thing to do.

I also feels weird to me, though the DWARF standard explicitly allows it.

But from the perspective of a linux distro using gcc and lto for package
compilation, it's the opposite of rare.

Anyway, I've filed a PR to reimplement this in some form or another (
https://sourceware.org/bugzilla/show_bug.cgi?id=33922 ).

Thanks,
- Tom

> ---
> gdb/dwarf2/read.c | 9 ---------
> 1 file changed, 9 deletions(-)
>
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index 5917e697aad..e48745d7969 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -4890,15 +4890,6 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
> dwarf2_per_cu *per_cu
> = dwarf2_find_containing_unit ({ &section, sect_off }, per_objfile);
>
> - /* We're importing a C++ compilation unit with tag DW_TAG_compile_unit
> - into another compilation unit, at root level. Regard this as a hint,
> - and ignore it. This is a best effort, it only works if unit_type and
> - lang are already set. */
> - if (die->parent && die->parent->parent == NULL
> - && per_cu->unit_type (false) == DW_UT_compile
> - && per_cu->lang (false) == language_cplus)
> - return;
> -
> /* If necessary, add it to the queue and load its DIEs. */
> if (maybe_queue_comp_unit (cu, per_cu, per_objfile))
> load_full_comp_unit (per_cu, per_objfile, false, cu->lang ());
>