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

Reply via email to