On Wed, 1 May 2024, Jason Merrill wrote:

> On 5/1/24 08:54, Patrick Palka wrote:
> > On Thu, 2 May 2024, Nathaniel Shead wrote:
> > 
> > > On Wed, May 01, 2024 at 10:11:20AM -0400, Patrick Palka wrote:
> > > > On Wed, 1 May 2024, 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.
> > > > 
> > > > LGTM.  Another approach is to instantiate all so-far deferred
> > > > instantiations and vtables once we reach the start of the module
> > > > purview, but your approach is much cleaner.
> > > > 
> > > > Note that deferred instantiation can induce more deferred instantiation,
> > > > but your approach will do the right thing here (module_kind will be
> > > > inherited from the point of instantiation).
> > > > 
> > > > What if an instantiation is needed from both the GMF and the module
> > > > purview?  Then IIUC it'll be instantiated as if from the GMF, which
> > > > seems right to me.
> > > > 
> > > 
> > > Hm..., so I believe it'll be marked according to whichever instantiates
> > > it "first", so if e.g. deferred from GMF and then instantiated
> > > non-deferred from purview it'll be marked purview (and the deferred
> > > instantiation will be skipped as it's already instantiated).  This could
> > > mean it gets unnecessarily emitted if it only got instantiated because
> > > it got used in e.g. a non-inline function body, I suppose; but that's
> > > true in general actually, at the moment.
> > 
> > FWIW I think the most relevant situation where we need to instantiate
> > immediately and can't defer until EOF is during constexpr evaluation of
> > a variable initializer.  (We also immediately instantiate variable
> > template specializations, and function template specializations with
> > deduced return type, but in these cases we'd always instantiate from the
> > first use, i.e. from the GMF in this scenario.)
> > 
> > So I guess a testcase for this situation could be something like:
> > 
> >      module;
> >      template<class T> constexpr int f(T t) { return t; }
> >      template int f(int);
> > 
> >      export module foo;
> >      constexpr int w = f(0);
> >      // f<int> ideally shouldn't be emitted in the CMI?
> 
> Does the explicit instantiation change that at all?  Either way it seams like
> f and f<int> aren't decl-reachable from w if we determine that after constant
> evaluation.

Currently due to the bug in question we handle this as if the explicit
instantiation was performed from the module purview:

  module;
  template<class T> constexpr int f(T t) { return t; }

  export module foo;
  template int f(int);
  constexpr int w = f(0);

I think we do want to emit f<int> in that case?

Reply via email to