[Bug c++/102609] [C++23] P0847R7 - Deducing this

2024-01-11 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102609

--- Comment #27 from Gašper Ažman  ---
I think there is an example in the standard that distinguishes those two as
far as overload resolution is concerned.

On Thu, Jan 11, 2024, 21:08 waffl3x at protonmail dot com <
gcc-bugzi...@gcc.gnu.org> wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102609
>
> --- Comment #26 from waffl3x  ---
> (In reply to corentinjabot from comment #25)
> > Hey folks.
> > Congrats on landing support for deducing this in GCC.
>
> Thanks!
>
> > While there is no spec for it, after discussion here,
> > https://github.com/itanium-cxx-abi/cxx-abi/issues/148 explicit objects
> > parameters are mangled with `H`
> > This is the form that has been adopted for Clang.
> >
> > The reason we need mangling is because WG21 made the following
> well-formed
> > (and that was reaffirmed. In fact, some complexity was added by P2797)
> >
> >
> >struct S {
> >  static void f(S);
> >  void f(this S);
> >};
> >
> > And we need a way to distinguish both functions
> > I wasn't sure you were aware of this; I hope that form of mangling will
> work
> > for you.
> >
> >
> > Thanks
>
> I don't have the experience to comment but my gut says this is a weird
> outcome. Oh well! I think I know how to implement this so I'll give it
> a go at some point today. If I have any trouble I'll leave it for
> someone else.
>
> Thanks for informing us.
>
> --
> You are receiving this mail because:
> You are on the CC list for the bug.

[Bug c++/102609] [C++23] P0847R7 - Deducing this

2023-09-02 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102609

--- Comment #19 from Gašper Ažman  ---
Correct, the use of the capture is the source of the error, not the
instantiation with an unrelated type.

On Sat, Sep 2, 2023, 09:54 waffl3x at protonmail dot com <
gcc-bugzi...@gcc.gnu.org> wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102609
>
> --- Comment #18 from waffl3x  ---
> (In reply to Gašper Ažman from comment #17)
> > Read through the patch quickly, want to suggest a few tests.
> >
> > When a lambda has captures, the explicit object parameter is used to get
> at
> > them *silently*, if they are related, otherwise the program is
> ill-formed:
> >
> > int x = 42;
> > auto f1 = [x](this auto&&) {
> >return x;
> > };
> > auto f2 = [](this auto&&) { return 42; }
> >
> > static_cast(decltype(f1)::operator()); // OK
> > static_cast(decltype(f1)::operator()); // ERROR
> > static_cast(decltype(f2)::operator()); // OK
>
> Ah I see, thanks for the input. I was actually wondering about that,
> especially
> if you were expected to use the explicit object parameter to access
> captures.
> Is my understanding correct that the second case would not be an error if
> captures were not used in the body of the lambda? Based on your wording I
> would
> believe that is the case, so implementing this behavior would not be as
> simple
> as just disallowing unrelated deduced types when there are captures.
>
> Unfortunately, I will not have access to my computer for a while more, I
> plan
> on setting up an environment at another computer and fixing the formatting
> errors that were noted, but I will wait until I have access to my computer
> before I work on it more seriously I think.
>
> Thanks a lot for looking at the patch though, I really appreciate the time
> you've taken.
>
> --
> You are receiving this mail because:
> You are on the CC list for the bug.

[Bug c++/102609] [C++23] P0847R7 - Deducing this

2023-08-31 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102609

--- Comment #17 from Gašper Ažman  ---
Read through the patch quickly, want to suggest a few tests.

When a lambda has captures, the explicit object parameter is used to get at
them *silently*, if they are related, otherwise the program is ill-formed:

int x = 42;
auto f1 = [x](this auto&&) {
   return x;
};
auto f2 = [](this auto&&) { return 42; }

static_cast(decltype(f1)::operator()); // OK
static_cast(decltype(f1)::operator()); // ERROR
static_cast(decltype(f2)::operator()); // OK

[Bug c++/102609] [C++23] P0847R7 - Deducing this

2023-08-20 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102609

--- Comment #12 from Gašper Ažman  ---
Replies to relevant snippets inline.

That was quite a write-up!


> The only compelling case I can think of for such a thing would be passing a
> pointer type that isn't related by inheritance anyway. That is to say, I'm not
> disagreeing with you, I just stopped to think about it and came up with this,
> consider the following example.
>
> struct my_function {
> using func_ptr = void(*)(int);
> func_ptr _f;
>
> void operator()(this func_ptr f, int a) {
> return f(a);
> }
>
> operator func_ptr() const {
> return _f;
> }
> };


This case is already covered by surrogate functions:

struct S {
using fptr = int(*)(int);
operator fptr() const {
return +[](int){return 42;};
}
};

int main() {
S x;
x(3); // OK, returns 42
}


https://godbolt.org/z/48Efzdr1q

The conversion operator is a better match in this case, so the
operator() which requires an implicit conversion is not the one
called.

>
> I'm mostly just excited to share what I finally thought of as a good example
> for an explicit object parameter that is not of a deduced or base type, but
> it's never the less a pointer type.

Converting to a pointer-type is not weird; it's converting to pointer
to your own type that is. Any proxy object with a conversion operator
to its underlying will have that if the underlying happens to be a
pointer type. Such a proxy object might well forward methods directly
to the underlying object via a conversion instead of stamping out a
body for each cv-ref qualifier.

> Granted, I think this type of use should also have some sort of warning
> available as it is still weird.

I disagree; conversion to your own type I think is a reasonable
warning (unless you have a conversion operator in the same class)
because it can come with a fixit hint (replace with reference to S
instead). All other types are legit.

> I think a warning for declaring an explicit object parameter as a pointer to
> base, derived, or deduced type should be in, since a reference is probably the
> best choice in that case.

I definitely agree that this warning is reasonable.

> Perhaps deduced type shouldn't be included in that
> warning, as there are cases that are kind of compelling for having that, one
> could trap implicit conversions to any pointer type that way on derived
> classes.

Yeah, deduced is legit, no warning for that one unless we discover
active pathologies.

> To elaborate on what I said above, I still think a warning when using a type
> that is not related to the class should be provided.

Strong disagree, that'll break a lot of code I actually intend to
write. Not stamping out additional template instantiations /  better
ABI by having implicit conversions will, I expect, be quite the common
implementation trick (for instance, any member algorithm on a vector
that doesn't change size can be called on an equivalent span instead
and therefore be passed in registers). This can be an implementation
detail of vector, so that vector and array can share template
instantiations, for instance.

> Even given that my example
> above presents a legitimate pattern, I think it's use is infrequent enough to
> provide an optional warning for this. I question if there's any value in
> suppressing the warning when there are legitimate conversions present, as it
> would no longer inform the user that they might have done something by 
> mistake.

I think my ruminations above give a good example of why such false
positives should definitely be expected in well-behaved code.

> Essentially, since it's not possible to warn that there are no viable
> conversions without false positives occurring, I think the warning should be
> present simply because you are doing something weird, not because you are
> declaring a function that won't be selected by overload resolution.

Yes, but you can get a pointer to it and call it directly. Might be a
useful way to pass overload sets.

> Just to reiterate, I fully agree that both warnings should be behind a flag. I
> think I would propose that the first (warning for pointer to base, derived, or
> deduced type in an explicit object parameter) should be turned on by default,
> while the second should be turned off by default.

I'm not sure the second one should even exist, as it's bound to be
even more annoying than -Wshadow.

>
> struct S : B {
> int f0(this B*) {} // warning 1, on by default
> int f1(this S*) {} // warning 1, on by default
> int f2(this auto*) {} // warning 1, on by default?, separate warning?
>
> int f3(this int) {} // warning 2, off by default(?)
> };

I say no warning on f2. S could be a CRTP-sans-CRTP mixin that expect
that conversion to exist.

>
> On the other hand, warning 2 could be split into 2 warnings, where one would
> warn for a "weird" explicit object parameter, while the other would warn for
> uncallable functions due 

[Bug c++/102609] [C++23] P0847R7 - Deducing this

2023-08-19 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102609

--- Comment #10 from Gašper Ažman  ---
Yes, the explicit object parameter always receives the cv-l/r qualified
reference to the object of the call. Implicit conversions are then of
course allowed, same as any other parameter. S* is not that useful as a
type of an explicit object parameter, implicit conversions to pointer to
yourself are probably about as weird as overloading operator&().

Also, don't forget explicit object function bodies and their type behave a
lot more like static functions than member functions.

On Sat, Aug 19, 2023, 10:43 redi at gcc dot gnu.org <
gcc-bugzi...@gcc.gnu.org> wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102609
>
> --- Comment #9 from Jonathan Wakely  ---
> If we're right about that, then I agree that a warning would be useful for
> classes that have no such implicit conversion from S to S*.
>
> I think the warning would give a false positive in the case below, so a
> way to
> disable it locally would be needed (e.g. via a diagnostic pragma).
>
> struct S {
>   int f(this S*); // warning: explicit object parameter of pointer type can
> only match if an implicit conversion to S* exists
> };
>
> struct T : S {
>   operator T*();
> };
>
> T t;
> int i = t.f(); // derived class has the required conversion
>
> --
> You are receiving this mail because:
> You are on the CC list for the bug.

[Bug c++/102609] [C++23] P0847R7 - Deducing this

2023-08-16 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102609

--- Comment #5 from Gašper Ažman  ---
And of course by "this" I meant support for a default argument on the explicit
object parameter.

We might add it back in the future if we find a usecase.

[Bug c++/102609] [C++23] P0847R7 - Deducing this

2023-08-16 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102609

--- Comment #4 from Gašper Ažman  ---
As one of the authors, I can assure you you never need to implement this for
c++23.

[Bug c++/110441] c++17: temporary causes static member function call to confuse required copy elision

2023-06-28 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110441

--- Comment #2 from Gašper Ažman  ---
Some more color from twitter, courtesy of @matthewecross:

Interestingly both "return S::f();" and "auto s = S(); return s.f();" both
pass.  It's only when you create a temporary instance of S in the return
statement that it fails.

[Bug c++/110441] c++17: temporary causes static member function call to confuse required copy elision

2023-06-28 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110441

Gašper Ažman  changed:

   What|Removed |Added

 CC||gasper.azman at gmail dot com

--- Comment #1 from Gašper Ažman  ---
I hit this in gcc 10 as well when implementing sender/receiver. Was not able to
reduce it this nicely, so I didn't report. Nice work, Eric.

[Bug c++/110380] [feature request] "-pg-constexpr=coverage-output" emit coverage metrics for constexpr code evaluated at compile time

2023-06-26 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110380

--- Comment #4 from Gašper Ažman  ---
John McFarlane noted that pre-initializing coverage datastructures with the
results of the constexpr-evaluated traces would also be a possible direction.
It does mean the linker needs to then correctly merge those, otherwise you lose
constexpr coverage at link time.

[Bug c++/110380] [feature request] "-pg-constexpr=coverage-output" emit coverage metrics for constexpr code evaluated at compile time

2023-06-24 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110380

--- Comment #2 from Gašper Ažman  ---
-fprofile-constexpr is perfectly fine :), as long as it gets a filename
argument for the output; build automation will be thankful.

[Bug c++/110380] New: [feature request] "-pg-constexpr=coverage-output" emit coverage metrics for constexpr code evaluated at compile time

2023-06-23 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110380

Bug ID: 110380
   Summary: [feature request] "-pg-constexpr=coverage-output" emit
coverage metrics for constexpr code evaluated at
compile time
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gasper.azman at gmail dot com
  Target Milestone: ---

We've been converting so much code to constexpr that entire test suites are now
evaluated at compile time. This is a problem because traditional coverage
metrics have become useless, but compile time evaluation is desirable due to
deep-UB checking.

It would be nice if gcc could emit coverage metrics for code that it executed
at compile time during the build, so that prof could combine it with the rest
of the test coverage.

Probably not a high priority, but a nice-to-have at some point.

[Bug c++/98660] -Wold-style-cast should not warn on casts that look like (decltype(x))(x)

2021-01-16 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98660

--- Comment #5 from Gašper Ažman  ---
s/endif/pragma GCC diagnostic pop

[Bug c++/98660] -Wold-style-cast should not warn on casts that look like (decltype(x))(x)

2021-01-16 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98660

--- Comment #4 from Gašper Ažman  ---
@Eric Gallager: yes, the #pragma solution is what I currently use. It is
entirely unsatisfactory, for the reasons described in my original request.

The long-term usefulness of warnings is directly proportional to the number of
false positives they generate. If I wanted to enforce the warning in most of
the code, and only disable it where appropriate, this is what that looks like,
on a non-terrible example (borrowed from libunifex):

  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignore "-Wold-style-cast"
  template 
  constexpr auto operator()(CPO cpo, Args&&... args) const
  noexcept(noexcept(tag_invoke((CPO &&) cpo, (Args &&) args...)))
  -> decltype(tag_invoke((CPO &&) cpo, (Args &&) args...)) {
return tag_invoke((CPO &&) cpo, (Args &&) args...);
  }
  #endif

Now please, kindly tell me how I can know I didn't screw up a C-style cast in
that mess? It turns out that in the example above, ALL the casts mean
std::forward, but imagine it was a function where only some of the arguments
are forwarded, and a co-worker mistakenly puts in a c-style cast that doesn't
just change the value-category.

I'm asking for this warning to get more useful by still diagnosing c-style
casts that change more than the value category, and not diagnosing c-style
casts that are the "safest" kind - value category only, since that's what the
idiom seems to be.

[Bug c++/98660] -Wold-style-cast should not warn on casts that look like (decltype(x))(x)

2021-01-14 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98660

--- Comment #2 from Gašper Ažman  ---
Ivan: indeed, you could use a static cast, or a macro - you're literally just
changing the value category of the expression to its original one. The cast is
safe.

The reason Niebler and friends (including me) are using the c-style cast is
purely because it's short, concise, unambiguous, and fast to compile.
`static_cast(x)` is a lot longer than `(T&&)x`. When you have 6 or
10 of these expressions (often with `...`s) in a function declaration (please
see the `tag_invoke` definition linked), the noise starts to matter.

[Bug c++/98660] New: -Wold-style-cast should not warn on casts that look like (decltype(x))(x)

2021-01-13 Thread gasper.azman at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98660

Bug ID: 98660
   Summary: -Wold-style-cast should not warn on casts that look
like (decltype(x))(x)
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gasper.azman at gmail dot com
  Target Milestone: ---

Dear GCC wizards,

Recently, the use of std::forward has been idiomatically replaced by the
following:

```
template 
void george(T&& x) {
   john((T&&)x); // means std::forward(x)
}
```

Casting an `x` to `decltype(x)` is far shorter and faster to compile (which
matters since it's done in unevaluated contexts A LOT). For an example, observe
the usage in libunifex, the in-progress research implementation of the
executors proposal:

https://github.com/facebookexperimental/libunifex/blob/master/include/unifex/tag_invoke.hpp

Unfortunately, the only real way to combine this fairly important exception to
the general rules of "no c-style casts" is to disable -Wold-style-cast.

It would be a great benefit if I could leave that warning enabled, and sleep
soundly in the knowledge I didn't mistype the forwarding expression if gcc
checked for me that the type I'm casting to is, in fact, `decltype(x)`, and
complain otherwise.

Please consider this refinement for a future release of GCC.

Thank you.