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