On Thu, Sep 4, 2025 at 10:27 AM Jonathan Wakely <jwak...@redhat.com> wrote:
>
> On Thu, 4 Sept 2025 at 08:26, Richard Biener <rguent...@suse.de> wrote:
> >
> > On Wed, 3 Sep 2025, Jakub Jelinek wrote:
> >
> > > On Wed, Sep 03, 2025 at 06:41:08PM +0200, Richard Biener wrote:
> > > > > I'd be worried about C++23 deducing this, but e.g.
> > > > > struct S;
> > > > > extern S t;
> > > > > struct S
> > > > > {
> > > > >  void foo (this S *p, int x);
> > > > >  int s;
> > > > > };
> > > > > void S::foo (this S *p, int x)
> > > > > {
> > > > >  p->s += x;
> > > > >  p = &t;
> > > > >  p->s += x;
> > > > > }
> > > >
> > > > Huh, you can assign to the ‚this‘ parameter?  I’ve read it can be a 
> > > > non-pointer.  But assigning to it makes the non-SSA match broken.  
> > > > What’s the use of such assignment?
> > > > Is p = nullptr valid?  Or delete p;?
> > >
> > > Clearly both g++ and clang++ compile this (but I'm then getting errors
> > > when trying to call it as t.foo (42); or ptr->foo (42)).
> > > Guess normally for deducing this the argument is this S &p instead and
> > > references can't be changed.  But normal this in methods is actually
> > > a pointer and keyword such that one can't change it either.
> > > Or in some tests it is this S and so passed by value.  That then can
> > > be called as t.foo (42).
> >
> > I've skimmed through the paper for the feature and found no wording
> > constraining assignment but also no example doing it ...
> >
> > We also accept
> >
> > struct B {};
> > struct S
> > {
> >   void foo (this B *p, int x);
> >   int s;
> > };
> > extern S t;
> > void S::foo (this B *p, int x)
> > {
> > }
> >
> > though I'm not sure you'd ever be able to call this?
>
> You can if S has an implicit conversion to B*
>
> struct B {};
> struct S
> {
>   void foo (this B *p, int x);
>   int s;
>   operator B*() { return &b; }
>   B b;
> };
> extern S t;
> void S::foo (this B *p, int x)
> {
> }
>
> int main()
> {
>   S s;
>   s.foo(1);
> }
>
>
>
> > int main() { B b; b.foo (1); }
> >
> > is rejected obviously, so is b.S::foo (1).  I think this would
> > warrant a diagnostic at least.  Maybe there's a trick to make
> > name lookup succeed though?
> >
> > That said, the invocation syntax suggests that the 'this' object
> > must be valid, the question is whether it's constrained by the
> > type of the formal argument only or by the class type
> > (TYPE_METHOD_BASETYPE if it were a method).
>
> Yes, it is. You can't call Foo::mem on an object that isn't a Foo or a
> type derived from Foo.
>
> > That said, assigning
> > to the this parameter adds a dataflow problem, easy for the SSA
> > side but impossible to resolve while in GENERIC - this makes
> > it necessary to perform EH pruning during SSA rewrite.
> >
> > That said, it's odd that the proposed "just alternative syntax"
> > produces a non-method type and also allows assigning to 'this'.
>
> It's not 'this' though! It's not a method, it's a static member
> function, so there is no implicit 'this' pointer. The parameter is
> declared  as 'this S' or 'this B' but that's just a token that says
> the function uses the new syntax, it doesn't mean that the parameter
> *is* the 'this' pointer.

Hmm, but the paper explicitly says it's _not_ a static member function
which to me suggests that the 'this' marked parameter must bind to
a valid object (of the declared type then, I guess).  But all these details
seem to be absent from the paper ...

So I hope

struct S
{
  void foo (this S *);
  int i;
};

((S *)0)->foo ();
char c;
((S *)&c)->foo ();

are both invalid, aka invoking UB.

Richard.

>
> > But well, C++ mess, as usual :/
> >
> > Richard.
>

Reply via email to