c++: Track declarations imported from partitions [PR99377]
commit77c0b5b23f91404004a9bf710981f6d615b63f57
authorNathaniel Shead <nathanieloshead@gmail.com>
Thu, 4 Apr 2024 12:16:08 +0000 (4 23:16 +1100)
committerNathaniel Shead <nathanieloshead@gmail.com>
Wed, 10 Apr 2024 00:40:36 +0000 (10 10:40 +1000)
treefeb98b1a6f2a2dc9d22f2834da3e7c43dbbcef91
parent0753ae158af42ca5f20567381805b27283c92b53
c++: Track declarations imported from partitions [PR99377]

The testcase in comment 15 of the linked PR is caused because the
following assumption in depset::hash::make_dependency doesn't hold:

  if (DECL_LANG_SPECIFIC (not_tmpl)
      && DECL_MODULE_IMPORT_P (not_tmpl))
    {
      /* Store the module number and index in cluster/section,
         so we don't have to look them up again.  */
      unsigned index = import_entity_index (decl);
      module_state *from = import_entity_module (index);
      /* Remap will be zero for imports from partitions, which
         we want to treat as-if declared in this TU.  */
      if (from->remap)
        {
          dep->cluster = index - from->entity_lwm;
          dep->section = from->remap;
          dep->set_flag_bit<DB_IMPORTED_BIT> ();
        }
    }

This is because at least for template specialisations, we first see the
declaration in the header unit imported from the partition, and then the
instantiation provided by the partition itself.  This means that the
'import_entity_index' lookup doesn't report that the specialisation was
declared in the partition and thus should be considered as-if it was
part of the TU, and get emitted into the CMI.

We always need to emit definitions from module partitions into the
primary module interface's CMI, as unlike with other kinds of transitive
imports the built CMIs for module partitions are not visible to
importers.

To fix this, this patch allows, as a special case for installing an
entity from a partition, to overwrite the entity_map entry with the
(later) index into the partition so that this assumption holds again.

We only do this for the first time we override with a partition, so that
entities are at least still reported as originating from the first
imported partition that declares them (rather than the last); existing
tests check for this and this seems to be a friendlier approach to go
for, albeit slightly more expensive.

PR c++/99377

gcc/cp/ChangeLog:

* module.cc (trees_in::install_entity): Overwrite entity map
index if installing from a partition.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr99377-3_a.H: New test.
* g++.dg/modules/pr99377-3_b.C: New test.
* g++.dg/modules/pr99377-3_c.C: New test.
* g++.dg/modules/pr99377-3_d.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
gcc/cp/module.cc
gcc/testsuite/g++.dg/modules/pr99377-3_a.H [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99377-3_b.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99377-3_c.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99377-3_d.C [new file with mode: 0644]