On Fri, 21 Feb 2025, Nathaniel Shead wrote: > After seeing PR c++/118964 I'm coming back around to this [1] patch > series, since it appears that this can cause errors on otherwise valid > code by instantiations coming into module purview that reference > TU-local entities. > > [1]: https://gcc.gnu.org/pipermail/gcc-patches/2024-May/650324.html > > We'd previously discussed that the best way to solve this in general > would be to perform all deferred instantiations at the end of the GMF to > ensure that they would not leak into the module purview. I still > tentatively agree that this would be the "nicer" way to go (though I've > since come across https://eel.is/c++draft/temp.point#7 and wonder if > this may not be strictly conforming according to the current wording?). > > I've not yet managed to implement this however, and even if I had, at > this stage it would definitely not be appropriate for GCC15; would the > approach described below be appropriate for GCC15 as a stop-gap to > reduce these issues?
+1 > > Another approach would be to maybe lower the error to a permerror, so > that users that 'know better' could compile such modules anyway (at risk > of various link errors and ODR issues), though I would also need to > adjust the streaming logic to handle this better. Thoughts? > > Nathaniel > > On Wed, May 01, 2024 at 08:00:22PM +1000, Nathaniel Shead wrote: > > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? > > > > -- >8 -- > > > > When calling instantiate_pending_templates at end of parsing, any new > > functions that are instantiated from this point have their module > > purview set based on the current value of module_kind. > > > > This is unideal, however, as the modules code will then treat these > > instantiations as reachable and cause large swathes of the GMF to be > > emitted into the module CMI, despite no code in the actual module > > purview referencing it. > > > > This patch fixes this by also remembering the value of module_kind when > > the instantiation was deferred, and restoring it when doing this > > deferred instantiation. That way newly instantiated declarations > > appropriately get a DECL_MODULE_PURVIEW_P appropriate for where the > > instantiation was required, meaning that GMF entities won't be counted > > as reachable unless referenced by an actually reachable entity. > > > > Note that purviewness and attachment etc. is generally only determined > > by the base template: this is purely for determining whether a > > specialisation was declared in the module purview and hence whether it > > should be streamed out. See the comment on 'set_instantiating_module'. > > > > PR c++/114630 > > PR c++/114795 > > > > gcc/cp/ChangeLog: > > > > * cp-tree.h (struct tinst_level): Add field for tracking > > module_kind. > > * pt.cc (push_tinst_level_loc): Cache module_kind in new_level. > > (reopen_tinst_level): Restore module_kind from level. > > (instantiate_pending_templates): Save and restore module_kind so > > it isn't affected by reopen_tinst_level. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/modules/gmf-3.C: New test. > > > > Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> > > --- > > gcc/cp/cp-tree.h | 3 +++ > > gcc/cp/pt.cc | 4 ++++ > > gcc/testsuite/g++.dg/modules/gmf-3.C | 13 +++++++++++++ > > 3 files changed, 20 insertions(+) > > create mode 100644 gcc/testsuite/g++.dg/modules/gmf-3.C > > > > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > > index 1938ada0268..0e619120ccc 100644 > > --- a/gcc/cp/cp-tree.h > > +++ b/gcc/cp/cp-tree.h > > @@ -6626,6 +6626,9 @@ struct GTY((chain_next ("%h.next"))) tinst_level { > > /* The location where the template is instantiated. */ > > location_t locus; > > > > + /* The module kind where the template is instantiated. */ > > + unsigned module_kind; > > + > > /* errorcount + sorrycount when we pushed this level. */ > > unsigned short errors; > > > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > > index 1c3eef60c06..401aa92bc3e 100644 > > --- a/gcc/cp/pt.cc > > +++ b/gcc/cp/pt.cc > > @@ -11277,6 +11277,7 @@ push_tinst_level_loc (tree tldcl, tree targs, > > location_t loc) > > new_level->tldcl = tldcl; > > new_level->targs = targs; > > new_level->locus = loc; > > + new_level->module_kind = module_kind; > > new_level->errors = errorcount + sorrycount; > > new_level->next = NULL; > > new_level->refcount = 0; > > @@ -11345,6 +11346,7 @@ reopen_tinst_level (struct tinst_level *level) > > for (t = level; t; t = t->next) > > ++tinst_depth; > > > > + module_kind = level->module_kind; > > set_refcount_ptr (current_tinst_level, level); > > pop_tinst_level (); > > if (current_tinst_level) > > @@ -27442,6 +27444,7 @@ instantiate_pending_templates (int retries) > > { > > int reconsider; > > location_t saved_loc = input_location; > > + unsigned saved_module_kind = module_kind; > > > > /* Instantiating templates may trigger vtable generation. This in turn > > may require further template instantiations. We place a limit here > > @@ -27532,6 +27535,7 @@ instantiate_pending_templates (int retries) > > while (reconsider); > > > > input_location = saved_loc; > > + module_kind = saved_module_kind; > > } > > > > /* Substitute ARGVEC into T, which is a list of initializers for > > diff --git a/gcc/testsuite/g++.dg/modules/gmf-3.C > > b/gcc/testsuite/g++.dg/modules/gmf-3.C > > new file mode 100644 > > index 00000000000..e52ae904ea9 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/modules/gmf-3.C > > @@ -0,0 +1,13 @@ > > +// PR c++/114630 > > +// { dg-additional-options "-fmodules-ts -Wno-global-module > > -fdump-lang-module" } > > +// { dg-module-cmi M } > > + > > +module; > > +template <typename> struct allocator { > > + allocator() {} > > +}; > > +template class allocator<wchar_t>; > > +export module M; > > + > > +// The whole GMF should be discarded here > > +// { dg-final { scan-lang-dump "Wrote 0 clusters" module } } > > -- > > 2.43.2 > > > >