On 8/6/24 2:35 AM, Nathaniel Shead wrote:
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
Another potential approach would be to go searching for this unexported
type and load it, either with a new LOOK_want::ANY_REACHABLE flag or by
expanding on the lookup_imported_temploid_friend hack. I'm still not
exactly sure how name lookup for template friends is supposed to behave
though, specifically in terms of when and where they should conflict
with other entities with the same name.
CWG2588 tried to clarify this in https://eel.is/c++draft/basic#link-4.8
-- if there's a matching reachable declaration, the friend refers to it
even if it isn't visible to name lookup.
It seems like an oversight that the new second bullet refers
specifically to functions, it seems natural for it to apply to classes
as well.
So, they correspond but do not conflict because they declare the same
entity.
The relevant paragraphs seem to be https://eel.is/c++draft/temp.friend#2
and/or https://eel.is/c++draft/dcl.meaning.general#2.2.2, in addition to
the usual rules in [basic.link] and [basic.scope.scope], but how these
all are supposed to interact isn't super clear to me right now.
Additionally I wonder if maybe the better approach long-term would be to
focus on getting textual redefinitions working first, and then reuse
whatever logic we build for that to handle template friends rather than
relying on finding these hidden 'mergeable' slots first.
I have a WIP patch to allow textual redefinitions by teaching
duplicate_decls that it's OK to redefine an imported GM entity, so
check_module_override works.
My current plan is to then just token-skip the bodies. This won't
diagnose ODR problems, but our module merging doesn't do that
consistently either.
@@ -11800,6 +11800,15 @@ tsubst_friend_class (tree friend_tmpl, tree args)
input_location = saved_input_location;
}
}
+ else if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (friend_tmpl))
+ <= TMPL_ARGS_DEPTH (args))
This condition seems impossible normally; it's only satisfied in this
testcase because friend_tmpl doesn't actually represent the friend
declaration, it's already the named class template. So the substitution
in the next else fails because it was done already.
If this condition is true, we could set tmpl = friend_tmpl earlier, and
skip doing name lookup at all.
It's interesting that the previous if does the same depth comparison,
and that dates back to 2002; I wonder why it was needed then?
Jason