On 12/05/2026 23:04, Jason Merrill wrote:
On 4/29/26 10:09 AM, feedable wrote:

On 29/04/2026 05:27, Jason Merrill wrote:
On 4/28/26 4:17 PM, feedable wrote:

On 28/04/2026 22:10, Jason Merrill wrote:
On 4/27/26 7:14 PM, feedable wrote:

On 28/04/2026 01:03, Jason Merrill wrote:
On 4/27/26 2:14 PM, feedable wrote:
+          else if (BASELINK_P (expr))
+        expr  = build_baselink (access_path, BASELINK_BINFO (expr),

Extra space before =.  Also I guess BASELINK_ACCESS_BINFO instead of
BASELINK_BINFO?

We want to use access_path (relative to the actual object_type) in place of BASELINK_ACCESS_BINFO, but indeed the access path should be the second argument rather than the first in both this call and the existing one.

If I understand correctly, access_path is the endpoint of the search, so it should go into BASELINK_BINFO, and it's the object type that should go into BASELINK_ACCESS_BINFO (in both cases, actually), since it's the
place where we started the search.

Ah, true.

Apparently, the start would actually correspond to the time when we got the reflection in the first place (as we are essentially performing x.C::m, but with C::m being spliced); so obtaining the access binfo from the
reflection here is correct.

I think you were right before; the reflection of a member does not include any information about how it was produced, whether from ^^ directly or otherwise. And normally BASELINK_ACCESS_BINFO needs to represent either the object type or a base thereof.
I believe that information is set in https://forge.sourceware.org/ gcc/ gcc-TEST/src/commit/c607c686100689e3e68487cd8097c2fbd3904168/ gcc/cp/ parser.cc#L10181, at least for the ^^ case.
So using TYPE_BINFO (object_type) as in v3 makes sense.  Of course we're suppressing access checking anyway so it doesn't much matter, but better to be correct if it isn't a burden.
Consider this case:
```
struct X {};
struct Y { template<class T> T f(T); };
auto _ = X{}.[:^^Y::f:]<int>(1);
```

Here, in v3 we build a BASELINK with the start point at X, even though X has nothing to do with Y::f, we couldn't've possibly found Y::F through X.

Hmm, in that case lookup_base should fail so we don't build a BASELINK at all.

The call to lookup_base probably should fail, yes. That said, we still do build the BASELINK even if the result is NULL. We want that because code later really really wants that BASELINK even if it has no BINFO, to perform access checks on.

Ah, yes, I was forgetting null return for "not a base".  But I would think we want to error immediately in that case and set expr = error_mark_node rather than build a BASELINK.

finish_class_member_access_expr does that for us already if we just leave the BINFO as NULL in such cases.

Only accidentally; better to give an error here as well rather than build a broken BASELINK that's likely to cause crashes if something looks at it closely.

We still can't emit error_mark_node here, since we wouldn't be able to parse `(` in `obj.[:memfn:]<args>()` otherwise, since we won't know that it's a function.

We can emit the function without the baselink, however, but that also changes the error in finish_class_member_access_expr to "is not a base of" one, which is worse than the "is not a member of" that was issued there previously. I guess that error is directed at the case of `b.A::x` where it would say "A is not a base of B", but for `obj.[:member:]` it makes much less sense.

I also don't really want to change that since that was being built even before the patch, and it seems to work just fine.

Incidentally, the above case doesn't seem to be represented in the tests.

It is basically from member13.С, that's how I caught that as an error in the first place.


Jason

Reply via email to