Ping for this; was there any changes that you wanted me to make here?
On Sat, Feb 08, 2025 at 11:32:28PM +1100, Nathaniel Shead wrote: > On Fri, Feb 07, 2025 at 11:11:21AM -0500, Jason Merrill wrote: > > On 2/7/25 9:28 AM, Nathaniel Shead wrote: > > > On Fri, Feb 07, 2025 at 08:14:23AM -0500, Jason Merrill wrote: > > > > On 1/31/25 8:46 AM, Nathaniel Shead wrote: > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? > > > > > > > > > > Happy to remove the custom inform for lambdas, but I felt that the > > > > > original message (which suggests that defining it within a class > > > > > should > > > > > make it OK) was unhelpful here. > > > > > > > > > > Similarly the 'is_exposure_of_member_type' function is not necessary > > > > > to > > > > > fix the bug, and is just for slightly nicer diagnostics. > > > > > > > > > > -- >8 -- > > > > > > > > > > Previously, 'is_tu_local_entity' wouldn't detect the exposure of the > > > > > (in > > > > > practice) TU-local lambda in the following example, unless > > > > > instantiated: > > > > > > > > > > struct S { > > > > > template <typename> > > > > > static inline decltype([]{}) x = {}; > > > > > }; > > > > > > > > > > This is for two reasons. Firstly, when traversing the TYPE_FIELDS of > > > > > S > > > > > we only see the TEMPLATE_DECL, and never end up building a dependency > > > > > on > > > > > its DECL_TEMPLATE_RESULT (due to not being instantiated). This patch > > > > > fixes this by stripping any templates before checking for unnamed > > > > > types. > > > > > > > > > > The second reason is that we currently assume all class-scope entities > > > > > are not TU-local. Despite this being unambiguous in the standard, > > > > > this > > > > > is not actually true in our implementation just yet, due to issues > > > > > with > > > > > mangling lambdas in some circumstances. Allowing these lambdas to be > > > > > exported can cause issues in importers with apparently conflicting > > > > > declarations, so this patch treats them as TU-local as well. > > > > > > > > > > After these changes, we now get double diagnostics from the two ways > > > > > that we can see the above lambda being exposed, via 'S' (through > > > > > TYPE_FIELDS) or via 'S::x'. To workaround this we hide diagnostics > > > > > from > > > > > the first case, so we only get errors from 'S::x' which will be closer > > > > > to the point the offending lambda is declared. > > > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > > > * module.cc (trees_out::type_node): Adjust assertion. > > > > > (depset::hash::is_tu_local_entity): Handle unnamed template > > > > > types, treat lambdas specially. > > > > > (is_exposure_of_member_type): New function. > > > > > (depset::hash::add_dependency): Use it. > > > > > (depset::hash::finalize_dependencies): Likewise. > > > > > > > > > > gcc/testsuite/ChangeLog: > > > > > > > > > > * g++.dg/modules/internal-10.C: New test. > > > > > > > > > > Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> > > > > > --- > > > > > gcc/cp/module.cc | 67 > > > > > ++++++++++++++++++---- > > > > > gcc/testsuite/g++.dg/modules/internal-10.C | 25 ++++++++ > > > > > 2 files changed, 81 insertions(+), 11 deletions(-) > > > > > create mode 100644 gcc/testsuite/g++.dg/modules/internal-10.C > > > > > > > > > > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc > > > > > index c89834c1abd..59b7270f4a5 100644 > > > > > --- a/gcc/cp/module.cc > > > > > +++ b/gcc/cp/module.cc > > > > > @@ -9261,7 +9261,9 @@ trees_out::type_node (tree type) > > > > > /* We'll have either visited this type or have newly discovered > > > > > that it's TU-local; either way we won't need to visit it > > > > > again. */ > > > > > - gcc_checking_assert (TREE_VISITED (type) || has_tu_local_dep > > > > > (name)); > > > > > + gcc_checking_assert (TREE_VISITED (type) > > > > > + || has_tu_local_dep (TYPE_NAME (type)) > > > > > + || has_tu_local_dep (TYPE_TI_TEMPLATE > > > > > (type))); > > > > > > > > Why doesn't the template having a TU-local dep imply that the TYPE_NAME > > > > does? > > > > > > I may not have written this the most clearly; the type doesn't > > > necessarily even have a template, but if it's not visited and its > > > TYPE_NAME hasn't had a TU-local dep made then we must instead have seen > > > a TYPE_TI_TEMPLATE that does have a TU-local dep. > > > > My question is why has_tu_local_dep (name) can be false while > > has_tu_local_dep (tmpl) is true. > > In this case it's an early exit thing; when walking the TYPE_NAME, we > find that it's a TEMPLATE_DECL_RESULT in 'trees_out::decl_node', and > walk the TI_TEMPLATE of that decl there. > > When walking this TEMPLATE_DECL we end up calling 'add_dependency' on > it, which creates the depset and adds it to the worklist. This doesn't > add the TYPE_DECL in this pass (we don't walk the TEMPLATE_DECL dep > we've just made yet, we're still walking whatever decl we were > processing when we saw this type), so when we come back to this checking > assertion we haven't made a dep for the TYPE_NAME yet. > > > I notice that find_tu_local_decl doesn't walk into TYPE_TI_TEMPLATE. > > So my thinking had been that 'find_tu_local_decl' doesn't need to handle > this case, because it's only ran when '!is_initial_scan', so all > dependencies that we could possibly have seen will have been created by > now. > > But because 'decl_value' early exits when we see a TU-local dep, we > never end up building the TYPE_NAME depset at all, which would indeed > cause 'find_tu_local_decl' to break. I haven't been able to make a > testcase for this however, as to actually reach this point we would have > needed to do the above walk in the body of a function template and find > just the TU-local DECL_TEMPLATE_RESULT in a type node, without walking > into any other TU-local decl as a byproduct. I'm not sure this is > possible, as use of decltype would require naming another TU-local decl. > > If we're sure that this case can never come up in practice, we could > maybe add a checking assert to 'find_tu_local_decl' that if we found a > decl and it didn't have a TU-local dep, it also didn't have a template > info that had a TU-local dep. > > Or the safe way to handle this possibility is to remove the early exit > from 'decl_value', and just do the extra walking of the value that we'll > throw away later anyway. Or a slightly less expensive alternative would > be to, if we have a TEMPLATE_DECL, also build the depset for the > DECL_TEMPLATE_RESULT before bailing. > > Nathaniel