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?