[Bug c++/114632] ICE with explicit this in lambda

2024-04-15 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114632

waffl3x  changed:

   What|Removed |Added

 CC||waffl3x at protonmail dot com

--- Comment #2 from waffl3x  ---
I have a feeling Bug 112810 is related as providing a return type for
the lambda works around this bug.

struct S {};

auto lambda = [](this auto& self, const int x) -> void {};

int main()
{
void (*func)(S&, int) = lambda;
return 0;
}

https://gcc.godbolt.org/z/WE5qdvYcP

[Bug c++/113388] Calling explicit object member function without object argument inside a function that is not an implicit object member function

2024-01-14 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113388

--- Comment #1 from waffl3x  ---
Yeah, looks like a bug. I won't be able to look at it as I am in the
process of moving but it seems like a similar one to PR113348.

Thanks for the report!

[Bug c++/113348] New: ice when calling xobj member function without an object in an xobj member function

2024-01-12 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113348

Bug ID: 113348
   Summary: ice when calling xobj member function without an
object in an xobj member function
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: waffl3x at protonmail dot com
  Target Milestone: ---

struct S
{
void f(this S& self) {}
void g(this S self) { f(); }
};

void test()
{
S{}.g();
}

Someone on reddit found this one, I forgot to reject this case, and it
turns out it crashes, fun. I've got a fix mostly finished that I will
post tomorrow, just making the bug report as a formality.

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

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

--- Comment #29 from waffl3x  ---
https://cplusplus.github.io/CWG/issues/2789.html
My alteration to CWG2789 came up on reddit and I realized I should
probably post about it here.

Instead of:
"if both are non-static member functions, they have the same types for
their object parameters, and"
We assumed it would be more correct for it to consider corresponding
object parameters:
"if both are non-static member functions, they have corresponding
object parameters, and"

Without this change in wording, the behavior of overload resolution is
different for member function templates with constraints and member
functions that are not templates with constraints. I felt that would be
undesirable so I assumed that the second wording was closer to the
intentions behind CWG2789.

This is the behavior that's currently been implemented, are there any
objections?

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

2024-01-11 Thread waffl3x at protonmail dot com via Gcc-bugs
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.

[Bug c++/113307] fails to diagnose an explicit object parameter to be a function parameter pack

2024-01-10 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113307

--- Comment #1 from waffl3x  ---
I'm on it.

[Bug c++/113308] derived class doesn't currently allow inherited explicit object member function post increment operator

2024-01-10 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113308

--- Comment #3 from waffl3x  ---
I meant to post this link instead of one of the others.
https://godbolt.org/z/oMP8185Yh
I guess I shouldn't be replying to things while still waking up, sorry!

[Bug c++/113308] derived class doesn't currently allow inherited explicit object member function post increment operator

2024-01-10 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113308

--- Comment #2 from waffl3x  ---
(In reply to Nathaniel Shead from comment #1)
> I believe this is correct behaviour: The definition of `operator++` in the
> child class hides the `operator++` declared in the base class. Similarly to
> the following code:
> 
> 
> struct base {
>   void f(int) {}
> };
> struct d1 : base {
>   void f() {}
> };
> struct d2 : base {
>   using base::f;  // explicitly add base::f as an overload
>   void f() {}
> };
> 
> int main() {
>   d1{}.f(10);  // error
>   d2{}.f(10);  // OK
> }

I'm pretty sure Nathaniel is right,
https://godbolt.org/z/d4r3dTsqa
https://godbolt.org/z/sxz1rcGbb
Mind you, clang and msvc's implementations are buggier than mine so I'm
not going to say "doesn't work on theirs so it isn't a bug" but I don't
think this one is a bug.

Thank you for testing my patch though, I do appreciate it.

[Bug c++/113191] [11/12/13/14 Regression] Incorrect overload resolution when base class function introduced with a using declaration is more constrained than a function declared in the derived class

2024-01-02 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113191

--- Comment #2 from waffl3x  ---
> Looking at the above commit, joust already takes care to check
> more_constrained for non-template functions, and only if their function
> parameters match according to cand_parms_match.  But here cand_parms_match
> returns false due to different implicit object parameters:

Okay yeah I definitely misunderstood something in more_specialized_fn,
what it does works but is arguably not the right thing.

> (gdb) frame
> #0  cand_parms_match (c2=0x3402cc0, c1=0x3402d70) at gcc/cp/call.cc:12699
> 12699 if (DECL_FUNCTION_MEMBER_P (fn1)
> (gdb) pct parms1
> 
> struct B *, void
> 
> (gdb) pct parms2
> 
> struct S *, void
> 
> In contrast more_specialized_fn skips over the implicit object parameter
> when comparing two non-static memfns.  Maybe cand_parms_match should follow
> suit?

We COULD do that, but it won't solve the problems with implementing the
xobj/iobj cases. With that said it probably does make more sense to
skip the object parameter when comparing two iobj member functions. Are
there ever any situations where both candidates are viable, but have
different object parameters? I'm pretty sure that will never be the
case, right?

I guess I'll have to open another PR for the xobj/iobj cases because I
think I agree with your evaluation of this.

[Bug c++/113191] New: [10.1/11/12/13/14 Regression] Incorrect overload resolution when base class function introduced with a using declaration is more constrained than a function declared in the deriv

2024-01-01 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113191

Bug ID: 113191
   Summary: [10.1/11/12/13/14 Regression] Incorrect overload
resolution when base class function introduced with a
using declaration is more constrained than a function
declared in the derived class
   Product: gcc
   Version: 10.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: waffl3x at protonmail dot com
  Target Milestone: ---

https://godbolt.org/z/91esEGhj4

template
struct B {
  constexpr int f() requires true { return 5; }
};

template
struct S : B<> {
  using B::f;
  constexpr int f() { return 10; }
};

static_assert(S<>{}.f() == 5);

The bug does not occur in this case:
https://godbolt.org/z/dPM1Gfc1c

We do the right thing in more_specialized_fn (which is why the second
case works fine), but that doesn't apply in this case. Perhaps we
should be lifting that work from more_specialized_fn to joust?

Unfortunately, the changes in more_specialized_fn do not properly
handle the following case.

struct B {
  template
requires true
  int g(T) { return 5; }
};

struct S : B {
  using B::g;
  template
  int g(this S&, T) { return 10; }
};

int main()
{
  S s{};
  s.g(0);
}

This case is ambiguous, I believe the main issue is that
more_specialized_fn does not implement [over.match.funcs.general.4].
This is kind of a separate bug but they are connected, and it's
relevant to how we decide to fix it. I'm mildly of the opinion that we
should be rewriting iobj member functions that are introduced with a
using declaration to have an object parameter matching that of the
class it was introduced into. This might open a can of worms, but it
more closely matches the behavior specified by the standard.

[over.match.funcs.general.4]
For non-conversion functions that are implicit object member
functions nominated by a using-declaration in a derived class, the
function is considered to be a member of the derived class for the purpose
of defining the type of the implicit object parameter.

This wasn't really as relevant before, but it does become relevant now
because of the following case.

https://godbolt.org/z/MjP5nrd8q

template
struct S;

template
struct B {
  constexpr int f(this S<> const&) { return 5; }
  constexpr int g() const { return 5; }
};

template
struct S : B<> {
  using B<>::f;
  using B<>::g;
  constexpr int f() const { return 10; }
  constexpr int g(this S const&) { return 10; }
};

inline constexpr S<> s{};
static_assert(s.f() == 5);
static_assert(s.g() == 5);

I am not 100% sure what the correct behavior here is, but my
interpretation is that the constraints should be taken into account.
Again, this is slightly unrelated to this bug report, but it's more
evidence that we should just overhaul everything with iobj member
functions, and follow the standard to the letter. I think it's going to
be simpler in the long run, trying to hack it in this way or that is
just going to keep introducing problems. With that said, I recognize
theres potential implementation difficulties with doing it this way
too. Ultimately, it's a big decision so I don't mean to declare that we
need to do it this way, I merely intend to present it as food for
thought.

My implementation currently does not do either of these correct at all,
and as you can see in the godbolt link, clang does not exhibit the
behavior I believe to be correct either.

One last note, despite this being a regression, I don't believe that
the previous implementation will be ideal (not that I've found the
divergence yet.) Previous versions had the liberty of making different
assumptions, and as demonstrated in the examples with xobj member
functions, we have some new issues we need to work around here as well.

I've spent the better part of 6 hours investigating this issue and the
issues related to it, trying to figure out how to handle it for my
patch. I have concluded that I'm not going to try to fix this bug for
xobj member functions, and instead going to wait for this bug to be
fixed to try to handle it. So the behavior for xobj member functions
and iobj member functions will both be equally incorrect. Anyway, since
I have spent so much time staring at this I might have made some
mistakes in this report, or it will just be more confusing and
disjointed than I hoped. Hopefully not though!

[Bug c++/113075] New: Inconsistent/wrong diagnostic when incorrectly taking address of single/overloaded

2023-12-18 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113075

Bug ID: 113075
   Summary: Inconsistent/wrong diagnostic when incorrectly taking
address of single/overloaded
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: waffl3x at protonmail dot com
  Target Milestone: ---

I am including all 3 bugs in a single report as they are similar and
located in the same region of code.

```
struct S {
  void f() {}

  void g() {}
  void g(int) {}

  void test() {
void (S::*fp)() = 
void (S::*gp)() = 
  }
};
```

: In member function 'void S::test()':
:29:24: error: ISO C++ forbids taking the address of an unqualified or
parenthesized non-static member function to form a pointer to member function. 
Say '::f' [-fpermissive]
   29 | void (S::*fp)() = 
  |^
:30:24: error: assuming pointer to member 'void S::g()' [-fpermissive]
   30 | void (S::*gp)() = 
  |^
:30:24: note: (a pointer to member can only be formed with '::g')

The error message between the overloaded case and the single case is
largely different. Perhaps there is a reason why it should be different
but this is kind of confusing in my opinion.


```
struct S {
  void f() {}

  void g() {}
  void g(int) {}
};

int main()
{
  S s{};
  void (S::*fp)() = 
  void (S::*gp)() = 
}
```

: In function 'int main()':
:32:24: error: ISO C++ forbids taking the address of a bound member
function to form a pointer to member function.  Say '::f' [-fpermissive]
   32 |   void (S::*fp)() = 
  |  ~~^
:33:24: error: assuming pointer to member 'void S::g()' [-fpermissive]
   33 |   void (S::*gp)() = 
  |^
:33:24: note: (a pointer to member can only be formed with '::g')

The single function case has a slightly different message, while the
overloaded case has an identical message. This appears to be due to a
lack of context in resolve_address_of_overloaded_function where the
errors are emitted in the overloaded case.

```
struct B {
  void f() {}

  void g() {}
  void g(int) {}
};

struct D : B {
  void test() {
void (D::*fp)() = 
void (D::*gp)() = 
  }
};
```

: In member function 'void D::test()':
:10:24: error: ISO C++ forbids taking the address of an unqualified or
parenthesized non-static member function to form a pointer to member function. 
Say '::f' [-fpermissive]
   10 | void (D::*fp)() = 
  |^
:11:24: error: assuming pointer to member 'void B::g()' [-fpermissive]
   11 | void (D::*gp)() = 
  |^
:11:24: note: (a pointer to member can only be formed with '::g')

The single function case properly suggests ::f but the overload case
suggests ::g instead.

All 3 bugs are super mild, and I don't know how feasible they are to
fix, but at the very least it's worth tracking them in my opinion.

[Bug c++/83417] Pointer-to-member template parameter with auto member type dependent container type does not work (C++17)

2023-12-15 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83417

waffl3x  changed:

   What|Removed |Added

 CC||waffl3x at protonmail dot com

--- Comment #5 from waffl3x  ---
https://godbolt.org/z/Kxco7c5Es

Still not working in trunk, was it ever decided on whether or not this
is well-formed?

```
template struct C {};
template 
void zoink(C) { }

struct S { int _m; };

void go() { zoink(C<::_m>{}); }
```
https://godbolt.org/z/ohG9ra5en
This is the workaround I would use, it has better ergonomics anyway. I
believe we should decide on whether this truly is a bug or not and if
not just simply close it.

Credit to Tsche for pointing this case out to me.

[Bug c++/112874] New: low quality diagnostic for overload resolution failure when taking address of overloaded function

2023-12-05 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112874

Bug ID: 112874
   Summary: low quality diagnostic for overload resolution failure
when taking address of overloaded function
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: waffl3x at protonmail dot com
  Target Milestone: ---

template inline constexpr bool not_int_v = !__is_same (T, int);
template concept NotInt = not_int_v;

template struct enable_if {};
template<> struct enable_if { using type = decltype(nullptr); };
template using enable_if_t = typename enable_if::type;

template
void using_concepts(T) {}

template> = nullptr>
void using_enable_if(T) {}

void test()
{
  // bad diagnostics
  void (*fp_concepts)(int) = _concepts;
  void (*fp_enable_if)(int) = _enable_if;

  // good diagnostics
  using_concepts(0);
  using_enable_if(0);
}

In short, the problem is that resolve_address_of_overloaded_function
uses print_candidates instead of the (slightly?) more modern
print_z_candidates. I wont go into too much detail as I'm not super
confident I have it right, but it seems to me that the crux of the
issue is that print_candidates does not call back into
fn_type_unification with the tf_error bit set in complain, while
print_z_candidates does. To be more exact, print_candidates does not
call back into fn_type_unification at all.

In my opinion, print_candidates should be decommissioned and replaced
with print_z_candidates. I don't know what the process of building up a
z_candidate is so I don't know if that is actually practical, but
unifying the interface here would probably be ideal.

[Bug c++/112810] New: bogus ambiguous overload resolution when taking address of static/xobj member function template introduced by using declaration where candidates have a mismatched deduced return

2023-12-01 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112810

Bug ID: 112810
   Summary: bogus ambiguous overload resolution when taking
address of static/xobj member function template
introduced by using declaration where candidates have
a mismatched deduced return type
   Product: gcc
   Version: 4.9.4
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: waffl3x at protonmail dot com
  Target Milestone: ---

struct B {
  static auto f(auto) { return 10; }
  static int g(auto) { return 10; }
};

struct S0 : B {
  using B::f;
  using B::g;
  static auto f(auto) { return 5; }
  static auto g(auto) { return 5; }
};

struct S1 : B {
  using B::f;
  using B::g;
  static int f(auto) { return 5; }
  static int g(auto) { return 5; }
};

void test()
{
  int (*p0)(int) = ::f;
  int (*p1)(int) = ::g;
  int (*p2)(int) = ::f;
  int (*p3)(int) = ::g;
}


https://godbolt.org/z/ebcjshfYd

This does not present in other cases of overload resolution as far as
I've seen. It did not seem to manifest for implicit object member
functions at all.

The godbolt reproducer uses a slightly different test case to test much
older versions of the compiler. I was shocked to find out just how far
back this goes. And I was investigating it to make sure my patch wasn't
causing it!

I can look into fixing it after I finish my patch, if I remember, but
that's why I'm posting this report, just in case I don't remember. :^)

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

2023-09-02 Thread waffl3x at protonmail dot com via Gcc-bugs
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.

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

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

--- Comment #16 from waffl3x  ---
Just gotta note that the patch posted here had an oversight, it never worked as
I hoped. The good news is, I submitted a finalized patch to the patch maillist,
just before I have to leave. Thanks for the help everyone, I will check in but
it will probably be a while before I can work on anything in a dedicated
fashion for a while. I will certainly respond to any chatter on the thread of
my patch if anything comes into question though. I have to go catch a plane
now, thanks again.

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

2023-08-25 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102609

--- Comment #15 from waffl3x  ---
Created attachment 55793
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55793=edit
inital support for P0847 explicit-object-parameter

Alright, I finalized something that I hope is worthy of criticism. I haven't
ran tests on it yet but I think it should be relatively stable. My first time
around I made the mistake of having hard failing TREE_CHECKs in if conditions,
and I'm pretty sure that was causing problems with the tests (I saw a lot of
segfaults), but I'm fairly sure it should be good this time (not that I shared
the first one).

I will probably start tests first thing tomorrow, hopefully I can figure out
how to make it take less than 4-8 hours.

I'm pretty happy with where I put most things, I didn't add anything to the
core tree nodes, I instead used tree_decl_common::decl_flag_3 for PARM_DECL,
but I added a member to lang_decl_base, hopefully this is satisfactory.

As for what I know works right now, the below program outputs 15, 25, 35, 45 as
you would expect. I haven't tried lambda's but I am sure they don't work. I
have not tried anything with inheritance, I wouldn't bet on it working but I
wouldn't bet against it. I have not tried implicit conversions, but I have a
feeling they probably work. I was planning on implementing rejection of
qualifiers on xobj member functions but I forgot, so that will come tomorrow. I
also have to implement errors when trying to declare a xobj parameter in a
function type. I haven't tried taking the address of an xobj member function,
but I have a hunch it will work, they are almost entirely treated as static
member functions at the moment. Speaking of that, the function declaration gets
pretty printed as a static function at the moment too.

So as you can see, there's still lots to do, but it shouldn't be as hard now
that I am more familiar with the code base.

Something I'm not especially happy with is how the error checking is strewn
around. I tried to put it where it is most relevant, but prioritized putting it
where I could get the best diagnostics, but I'm probably missing some things I
could be doing to better group it together. I am also not happy with the
quality of all of the diagnostics, I want to improve on that as I learn the
quirks of the utilities.

Please criticize, I am certain I am still doing some stuff wrong, so I would
appreciate any input so I can correct those mistakes.

Here is the aforementioned program that I know to work on my system. Surely
nothing can go wrong, but who knows.

#include 
struct S {
int _a;
int my_func(this S& s) {
return s._a + 5;
}
int my_func(this S const& s) {
return s._a + 15;
}
int my_func(this S&& s) {
return s._a + 25;
}
int my_func(this S const&& s) {
return s._a + 35;
}
template
int my_func_dispatch(this Self&& self) {
return static_cast(self).my_func();
}
};

int main()
{
S s{10};

printf("%d\n", s.my_func_dispatch());
printf("%d\n", static_cast(s).my_func_dispatch());
printf("%d\n", static_cast(s).my_func_dispatch());
printf("%d\n", static_cast(s).my_func_dispatch());
}

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

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

--- Comment #13 from waffl3x  ---
I am finding myself realizing that implementing this as a member function and
turning off member function bits seems to be more difficult than implementing
it as a static function and implementing member function bits will be.
However, I am uncertain on the differences in what is in scope in static member
functions and implicit object member functions are, and whether explicit object
member functions scope is equal to either of them. Are you required to access
member type aliases through the type of the explicit object parameter? Upon
typing this I'm realizing that cases that deduce the explicit object parameter
would need to access it through the template type, so I guess the answer is
yes?

struct S {
using my_type = int;
void f0(this S, my_type) {}
void g0(this S) {
my_type local;
}
};

struct S {
using my_type = int;
void f1(this S, S::my_type) {}
void g1(this S) {
S::my_type local;
}
};

Of these cases, is f0 or f1 and g0 or g1 correct? I assume the answer is f1 and
g1.
And does the answer change when the type is deduced instead?

struct S {
using my_type = int;
template
void f0(this Self, my_type) {}
template
void g0(this Self) {
my_type local;
}
};

struct S {
using my_type = int;
template
void f0(this Self, Self::my_type) {}
template
void g0(this Self) {
Self::my_type local;
}
};

When deduced, f0 or f1 and g0 or g1? I would definitely think f1 and g1 now.

Really, writing the question out I feel like I know the answer now, but since I
was uncertain in the first place I still better ask, just in case.

(In reply to Gašper Ažman from comment #12)

> 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.
To be clear, when I say a warning should be available, I don't mean to imply
the thing it warns for isn't potentially legitimate. There's quite a few
warnings for legitimate things that you don't want to accidentally do but are
legitimate, or even common. The best example I have is everything under
-Wconversion, I know some people find suppressing it with explicit casts
annoying, but the errors that can come about through accidental conversions are
severe enough to justify using it in my opinion.

I would extend that rationale to not suppressing warnings for S* when a
conversion operator is present. Just because the conversion operator exists
that makes a call to that function (in the absence of any other overloads) well
formed does not mean that one meant to declare the xobj as S*.

> > 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.
Noted, warn for pointer to base or derived, but not to pointer to deduced. Or
at least not behind the same warning flag.

> > 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.
I think you should recognize that these exotic use cases are just that, exotic.
I don't think I should leave warnings that might be useful for the average user
off the table just because you or I would never enable that warning. Writing
this I'm now realizing the case I mentioned earlier that you said is not 

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

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

--- Comment #11 from waffl3x  ---
(In reply to Jonathan Wakely from comment #9)
> 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

I've ran some ideas in my head, no matter what is the decided upon design I
fully agree that all the warnings must be implemented with flags so they can be
suppressed, each independent of the other. I explain the warning I would
propose below, and I will make sure each one is properly documented, especially
since one of them has a clear risk of false positives, as you demonstrated.

(In reply to Gašper Ažman from comment #10)
> 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&().

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;
}
};

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.
Granted, I think this type of use should also have some sort of warning
available as it is still weird.

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. 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.

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. 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.
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.

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.

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(?)
};

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 to a lack of implicit conversions.
warning 2: weird explicit object parameter
warning 3: uncallable function (possibly has false positives)

struct S {
operator int() const {}

int f0(this int) {} // emits warning 2
int f1(this some_type) {} // emits warning 2 or 3
};

I imagine my proposed warnings 2 and 3 should be mutually exclusive, but I'm
not sure which should take precedence.

I suppose I've bikeshedded this a bit but I wanted to get my ideas up here
before I start working on things again today.


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

Yes, that is one of the next thing's on my list to implement. At the moment
they are still member function pointer types.
My current plan is;
1. Pass reference to object when calling explicit object member functions.
2. Convert the function type of explicit object member functions to regular
function types.
3. Make sure calling explicit object member functions as member functions still
works.
4. finally, 

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

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

--- Comment #7 from waffl3x  ---
struct S {
int f(this S*) {
return 5;
}
};

int main()
{
S s{};
return s.f();
}

Here is my current progress, this code works. I have a good feeling that the
rest is going to be easy. Except for deduction maybe, but I have a minor hunch
that it might -just work- without any extra tinkering after everything else has
been implemented.
Also yes, I know that `int f(this S*)` is not a valid declaration, I just
didn't have to change any member function call code for it to work this way so
I made it my first goal to implement it this way.

Actually, I guess it's not explicitly invalid is it? I don't recall seeing it
in the pathological cases section of the paper, indeed, I just checked and
there doesn't seem to be mention of it. I believe it should probably be valid
though, not useful if you ask me. Even less so than the other pathological
cases (which I think might actually prove to be useful in some cases.) However,
regardless of my opinion, following the same direction as the original paper, I
imagine it should be allowed. The class would just need an implicit conversion
to pointer, maybe a warning would be in order though?

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

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

--- Comment #6 from waffl3x  ---
I've noticed the standard does call `this` a specifier, I will perhaps rework
the code to just do parsing in cp_decl_specifier_seq.

(In reply to Gašper Ažman from comment #5)
> 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.

Great, I will just forbid it then, I can't think of a compelling reason to make
it a warning even if it should be benign.

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

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

--- Comment #3 from waffl3x  ---
I have some elements working so far, I opted to implement parsing for `this` in
cp_parser_parameter_declaration instead of in cp_parser_decl_specifier_seq
because I didn't want to add another member to cp_decl_specifier_seq, but I
ended up doing it anyway in the end. The `this` clause isn't a specifier so I
thought including it in the same function for parsing decl-specifier-seq would
be odd, but I ended up needing to put code to skip the first `this` token into
cp_parser_decl_specifier_seq so I don't know if that was the right decision in
the end. Ultimately I would like to refactor attribute parsing into another
function instead of having it be a part of cp_parser_decl_specifier_seq, but
I'm not going to do that while implementing "deducing this."

I'm uncertain of where to put the error checking, right now it is in
grokdeclarator. Setting the "explicit object function flag" is also in
grokdeclarator at the moment as I wanted to avoid adding more parameters to
functions. I'm pretty unhappy with how the code is organized, so if anyone has
any opinions on where certain things should be done, please share them.

Right now, parsing the `this` clause works, and errors are reported when it is
used other than in the first parameter, with an altered diagnostic when it is
used multiple times. There is also a diagnostic when `this` is used in a
function type declaration.

Input would be appreciated, thanks.

(In reply to Marek Polacek from comment #2)
> Related: https://cplusplus.github.io/CWG/issues/2653.html

I don't currently implement this, but I was going to, however I am unsure on
whether it's been merged into the standard, I guess "Status: C++23" means that
it was, yeah?

[Bug c++/109181] requires expression type requirement rejects valid type when it is a nested member template

2023-08-07 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109181

--- Comment #6 from waffl3x  ---
PR 110927 presents a similar use case that originally lead me to this bug, I
also posted the workarounds that I had since discovered there. If anyone coming
across this bug is looking for a solution you can find them there.

[Bug c++/110927] GCC fails to parse dependent type in concept through partial specialization

2023-08-07 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110927

waffl3x  changed:

   What|Removed |Added

 CC||waffl3x at protonmail dot com

--- Comment #2 from waffl3x  ---
(In reply to Andrew Pinski from comment #1)
> Confirmed, I suspect PR 109181 is the same (or rather reduced example).

Yes, I believe the case danakj wrote here is very close to my original use case
when I first submitted the bug. Since I never got around to recreating it and
posting it I'm thankful this report was made, I had mostly forgotten about it.
I found 2 workarounds so I ended up moving on.

I suspect that the bug isn't related to partial specializations given the
reduced case in PR 109181 doesn't have one, however, my original case also
involved partial specializations so perhaps I am wrong.

Here are the workarounds I mentioned just in case they are useful to danakj.

The first workaround is more modern, not resorting to older techniques.
```
template
concept HasTypeMemberTemplate1 = requires{
typename std::type_identity::template type<>>())>;
};
```

The second workaround uses older techniques.
```
template
struct specialization_has_type_member_template
  : std::false_type {};

template
struct specialization_has_type_member_template::template type<>>>
  : std::true_type {};

template
concept HasTypeMemberTemplate2 = has_valid_adapter_specialization::value;
```

You can see both workarounds in action here, hopefully you can get some use out
of them.
https://godbolt.org/z/Po1M4qc5P
I can't take credit for the modern workaround, someone named Raldryniorth in a
small community came up with it when I had the problem months back, so thanks
to him for that.

[Bug c++/110566] [13 Regression] ICE when instantiating function template with template template parameter with 2 or more auto parameters with a dependent member template, ICE in tsubst, at cp/pt.cc:1

2023-07-26 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110566

--- Comment #6 from waffl3x  ---
(In reply to Patrick Palka from comment #5)
> Should be fixed on trunk so far.

Once it shows up on godbolt I will make sure that all the cases that exhibited
the bug are working for me now. I had a bunch of different combinations of
typename and auto and anything with 2 or more autos were breaking.
If I had to guess, I imagine they all should all be working now, but I'll
double check it to make sure.

[Bug c++/110566] New: [13/14 Regression] ICE when instantiating function template with template template parameter with 2 or more auto parameters with a dependent member template, ICE in tsubst, at cp

2023-07-05 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110566

Bug ID: 110566
   Summary: [13/14 Regression] ICE when instantiating function
template with template template parameter with 2 or
more auto parameters with a dependent member template,
ICE in tsubst, at cp/pt.cc:16135
   Product: gcc
   Version: 13.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: waffl3x at protonmail dot com
  Target Milestone: ---

https://godbolt.org/z/6d4ec5va3

template typename> void takes_templ();

template
struct v_v_member_templ_fn {
template
using fn = void;
};

using ice = decltype(takes_templ::template fn>());

This one seems kind of boring to me, only interesting things to note are the
ICE only manifests with 2 or more (I assume) auto template parameters, it works
as expected with only a single auto template parameter.
The version of GCC on my local machine that exhibits this behavior is: 13.1.1
20230429

Not as convoluted as I'm used to, but at least that means it should be easy to
fix! One can hope anyway.

[Bug c++/110006] friend function template with constraint doesn't match existing declaration

2023-06-16 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110006

waffl3x  changed:

   What|Removed |Added

 CC||waffl3x at protonmail dot com

--- Comment #1 from waffl3x  ---
I am pretty certain Bug 110291 is a duplicate of this one

[Bug c++/110291] [11.1 Regression] constraint on friend operator template causes bizarre duplication of RHS template parameter that is passed to the requires expression

2023-06-16 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110291

--- Comment #1 from waffl3x  ---
I opened Bug 110006 and forgot to check before submitting, looking over at it,
I'm pretty sure it's the same bug, and if not, then probably related.
https://godbolt.org/z/7zoWfG4Ws I checked their reproduction and sure enough,
it's also an 11.1 regression just like this one, so it is almost certainly the
same. So this should probably be marked as a duplicate of it? I'm not really
sure what the protocol for that is though so I'll leave it to someone else.

[Bug c++/110291] New: [11.1 Regression] constraint on friend operator template causes bizarre duplication of RHS template parameter that is passed to the requires expression

2023-06-16 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110291

Bug ID: 110291
   Summary: [11.1 Regression] constraint on friend operator
template causes bizarre duplication of RHS template
parameter that is passed to the requires expression
   Product: gcc
   Version: 11.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: waffl3x at protonmail dot com
  Target Milestone: ---

template
struct fn { using type = decltype(L{} + R{}); };

struct no_self {};
no_self operator+(int, no_self);

void operator+(no_self, no_self) = delete;

template
struct expr {
template
requires requires {typename fn::type;}
friend void operator/(expr, expr);
};

using X = decltype(expr{} / expr{});

https://godbolt.org/z/on1KdfY9T
`error: use of deleted function 'void operator+(no_self, no_self)'`
Working in GCC 9.5 and GCC 10.4, broken in 11.1 and onward. Not too much of a
monologue from me this time, I couldn't beat much interesting information out
of it. Best I can tell is it's definitely related to the constraint (note that
separating it into a concept does not fix the issue), and it being a friend
operator is relevant. I am pretty sure the addition operator overload is not
related, it's just related to what I was doing when I encountered the bug. I'm
pretty sure there is another layer that could be peeled off here, but it
started to hurt my head and for a small bug I think this should be good enough.

It almost seems like it's caching U and preemptively evaluating the RHS as a
LHS with the cached U type. I wanted to confirm this somehow, but like I said,
it just wasn't cooperating. My experimenting was just resulting in much much
more complicated examples,so I decided to just call it here.

[Bug c++/110122] [13/14 Regression] using an aggregate with a member variable with a user defined copy constructor in a class NTTP causes capture and use of the `this` pointer in a generic lambda to p

2023-06-07 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110122

--- Comment #5 from waffl3x  ---
(In reply to Patrick Palka from comment #4)
> 
> Yes, it seems the original testcase is exhibiting two bugs (one of which a
> GCC 13 regression), whereas the second testcase exhibits one
> (non-regression) bug.
> 
> In your original testcase Bar's copy constructor shouldn't be needed since
> the template parameter V isn't being copied anywhere, but we're somehow end
> up with an illegitimate use of the constructor (bug #1) and then we're also
> failing to synthesize it (bug #2).
> 
> In the second testcase Bar's copy constructor is legitimately needed since
> we're arguably making a copy of V when writing the specialization
> Doppelganger, but we fail to synthesize the constructor (bug #2).
> 

Ah okay got it, bug #1 is pretty harmless then isn't it, because there should
never be a situation where the illegitimate use of the constructor will be an
error, it only popped up because bug #2 happened.
On the other hand, this makes me wonder about what's going on during class
template instantiation, at worst it's probably an inefficiency rather than
anything potentially harmful though.
> 
> Ah, does it work for you to give Bar an explicitly defaulted copy and
> default ctor?
Yes actually, that does seem to do the trick.
https://godbolt.org/z/x7eYzY6dz

[Bug c++/110122] [13/14 Regression] using an aggregate with a member variable with a user defined copy constructor in a class NTTP causes capture and use of the `this` pointer in a generic lambda to p

2023-06-05 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110122

--- Comment #3 from waffl3x  ---
Very cool, thanks, since your test case seems to cause problems in GCC 11 and
GCC 12 does that mean the bug goes deeper than I thought?

(In reply to Patrick Palka from comment #2)
> It seems only the first testcase exhibits a 13 regression, we never accepted
> the second testcase.

Is that what you meant here btw, that since your second test case triggers the
bug in 11 and 12 that it belongs as a different regression test?

Sadly, the workaround doesn't work when `Bar` is a class template.
https://godbolt.org/z/41xWrar5e
So it doesn't work in my specific case :(

I'm still very impressed that you found another way to trigger it as well as a
workaround, it's just a shame I can't use it.

[Bug c++/110122] New: using an aggregate with a member variable with a user defined copy constructor in a class NTTP causes capture and use of the `this` pointer in a generic lambda to produce the fol

2023-06-05 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110122

Bug ID: 110122
   Summary: using an aggregate with a member variable with a user
defined copy constructor in a class NTTP causes
capture and use of the `this` pointer in a generic
lambda to produce the following error "-copy
constructor- used before its definition"
   Product: gcc
   Version: 13.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: waffl3x at protonmail dot com
  Target Milestone: ---

https://godbolt.org/z/c7nnfjzGK

struct Foo {
constexpr Foo() = default;
constexpr Foo(Foo const&) {}
};

struct Bar {
Foo _;
};

template
struct Doppelganger
{
void disguise() {
[this](){ this; }();
}
};

void execute() {
Doppelganger<>{}.disguise();
}

error: 'constexpr Bar::Bar(const Bar&)' used before its definition

The bug is present in GCC 13.0 and 13.1 and in the current trunk.
This was a dreadful one, I am pretty sure there are 2 different bugs at play
here. It took a while to whittle it down to this example, as I was reducing my
code, I was shocked to find that removing a innocuous looking copy constructor
"fixed" the bug. It seemed like the user declared copy constructor is being
produced late.
The bug does not manifest when passing `Foo` directly to `Doppelganger`'s
non-type template parameter, which I also found odd.
Finally, capturing and using the `this` pointer in the body of a generic lambda
(the bug does not manifest with a regular lambda) finally causes the bug to pop
up. I was not able to find a more reduced version.
I found it strange that a generic lambda is required, I would have thought that
it being a generic lambda would delay when the copy constructor definition was
required, but instead it seems to speed it up. As far as I've observed this
seems to be what's happening, as omitting the call to the member function
avoids triggering the bug. 
One final thing to note, declaring the copy constructor as default also avoids
the bug, while a user declared default constructor has no effect at all.

If anyone manages to reduce it further I would be very interested to see it, I
spent a lot of time at it and couldn't seem to find any way to get it to work
when passing an object of `Foo` directly to `Doppelganger` despite that it
feels like it should be irrelevant. Perhaps it being a member of `Bar` moves up
when the definition of the copy constructor is required?

As an aside, even when deleting the copy constructor, the diagnostic for the
correctly rejected code is still rather unhelpful. It confused me for quite a
while as it points to the use of the `this` pointer, or any uses of member
variables, almost as if the compiler was mistaking the expression for the non
type template parameter, `Bar` in this case. I now realize that use of the
`this` pointer probably requires the full type be instantiated from the class
template, or I should say thats my guess.
My point is, perhaps the compiler should be bailing out earlier, like when the
class template is being instantiated with a NTTP that would be invalid.
Upon saying that I realized I should test whether it does or not, and I found
that it was previously the case, maybe not as early as it could be, but I'm
sure the trade off was made for a reason.
Unfortunately, this is not the case in GCC 13.1 and GCC trunk.
https://godbolt.org/z/8b7Mj91xM
I haven't checked if this bug was reported yet, or if it is a bug at all, I
will have to look into whether the decision to require copy constructors for
NTTP's got overturned or not. You can find that topic being discussed here,
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104577 , as of a few months ago it
seems like NTTP's require copy constructors. Once I have confirmed that I can
make another report for this bug if there are no objections, as despite being
relevant to this bug, it seems to be slightly different.

To recap, I believe there are at least 2 bugs here, the first being the delayed
(or perhaps completely omitted) definition of class `Foo`'s user defined copy
constructor. The second being a class with an undefined copy constructor is
incorrectly accepted as a NTTP, even when an object of that type is
initialized. (I have also confirmed that accessing said object does not change
that outcome. https://godbolt.org/z/fhsoPGEda )
And finally, there is a 3rd possible bug here involving generic lambdas (as a
regular lambda does not trigger the bug), however, despite how problematic
generic lambdas seem to be, I am not confident that it is actually responsible
for any problems here. It might just be that the time the generic lambda's call
operator is instantiated is before the delayed definition of the copy
constructor of `Foo`, which isn't because the lambda is instantiating 

[Bug c++/109181] requires expression type requirement rejects valid type when it is a nested member template

2023-03-21 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109181

--- Comment #5 from waffl3x  ---
(In reply to Patrick Palka from comment #3)
> A workaround is to just remove the unneeded 'template' after the :: in this
> case.  Or is there an example where the template keyword is needed that we
> incorrectly reject?

In my original use case, A in `inline constexpr bool go = requires{typename
A::template B;};` would have been dependent, I included the template
keyword because of that but it should have occurred to me that the example I
presented doesn't need it, I'm not sure what the standard requires for this
sort of thing though.

When I reduce I just remove everything that isn't required to get the result
I'm looking for, I should have realized that changing the semantics of the
example might create confusion and in the future I think I will also include a
reduced version that comes closer to the problem I actually encountered, I
imagine that it will be helpful even if it's not actually the most reduced
version.

I'll try to create an example that reflects my use case better as soon as I
can.

[Bug c++/109181] requires expression type requirement rejects valid type when it is a nested member template

2023-03-18 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109181

--- Comment #2 from waffl3x  ---
(In reply to Andrew Pinski from comment #1)
> Confirmed.
> Goes away the way back when -fconcepts support was originally added in GCC
> 6. You can see that with this testcase:
> ```
> struct A {
> template
> using B = int;
> };
> 
> template
> bool go = requires{typename A::template B;};
> ```
> 
> Note back in GCC 6, you needed `-std=c++17 -fconcepts` and also requires was
> only allowed for templates too ..

Ah damn, I'll try to keep in mind that I can use the old enabling flags to go
further back. I'm glad this one wasn't a duplicate, heres hoping I don't find
another bug today

[Bug c++/109181] New: requires expression type requirement rejects valid type when it is a nested member template

2023-03-18 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109181

Bug ID: 109181
   Summary: requires expression type requirement rejects valid
type when it is a nested member template
   Product: gcc
   Version: 10.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: waffl3x at protonmail dot com
  Target Milestone: ---

https://godbolt.org/z/5hG9Eqhc9

struct A {
template
using B = int;
};

inline constexpr bool go = requires{typename A::template B;};

error: 'typename A::B' names 'template using B = int', which is not a
type

I believe this is not a regression as the bug exists all the way back to 10.1
(assuming I understand what regression means)

Clang and MSVC accept this code, I assume GCC is incorrect since I couldn't
find anything specifying that a member template is not allowed, however I also
haven't found anything that specifies that it is allowed so I am not certain.

The behavior exists in all versions I checked since GCC 10.1

[Bug c++/109168] New: bogus error: 'X' is not a valid template argument of type 'Y' because 'X' is not a variable

2023-03-16 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109168

Bug ID: 109168
   Summary: bogus error: 'X' is not a valid template argument of
type 'Y' because 'X' is not a variable
   Product: gcc
   Version: 13.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: waffl3x at protonmail dot com
  Target Milestone: ---

https://godbolt.org/z/5xxPhhno7

struct stores_fptr {
void (*fptr)();
};

void func() {}

struct holds_value {
static constexpr auto value = stores_fptr{};
};

template struct takes_value {};

using go = takes_value;

There are a few workarounds for this that I could find, the most obvious being
the following changes (working example): https://godbolt.org/z/81xr36bYc

template struct takes_value {};

inline constexpr auto f = holds_value::value.fptr;
using go = takes_value;

I want to note, the bug is still present in the broken example if `takes_value`
takes a deduced (auto) non type template parameter, I explicitly state the type
just to reduce the example further.

The first (broken) snippit works in clang, and is broken in gcc trunk, gcc
12.2, and gcc 11.2, I was not able to test on MSVC. I'm mildly concerned that
this is one of those cases where clang is wrong to accept the code, but I was
able to find enough workarounds that I feel like I'm not incorrect.

The code also fails on my system with version: g++ (GCC) 13.0.1 20230219
(experimental)

Here is the gcc version on compiler explorer at the time of writing: g++
(Compiler-Explorer-Build-gcc-0c061da91a3657afdb3fac68e4595af685909a1a-binutils-2.38)
13.0.1 20230316 (experimental)

BTW, should I be selecting the oldest version that a bug occurs or the newest
version? I observed the behavior all the way back to 10.1, which appears to be
when support for C++20 starts. I guess the better question to ask is how do I
assign multiple versions?

[Bug c++/108998] [13 Regression] ICE in tsubst, at cp/pt.cc:16037

2023-03-02 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108998

--- Comment #3 from waffl3x  ---
I made a mistake in my previous comment, the version on my system that fails is
12.2.1, sorry for any possible confusion.

[Bug c++/108998] ICE in tsubst, at cp/pt.cc:16037

2023-03-02 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108998

--- Comment #1 from waffl3x  ---
I ran it on my local system, just to get some line numbers, and I accidentally
ran it on an older version (12.1) and found that it has a similar result, I'm
posting the output of -v and the error of both here. As a reminder, gcc 12.2 on
godbolt does not ICE.

[waffl3x@waffl3x-manjaro-desktop gcc]$ /opt/compiler/bin/g++ -v
Using built-in specs.
COLLECT_GCC=/opt/compiler/bin/g++
COLLECT_LTO_WRAPPER=/opt/compiler/libexec/gcc/x86_64-pc-linux-gnu/13.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc-13-20230115/configure --enable-languages=c,c++,lto
--enable-bootstrap --prefix=/opt/compiler --mandir=/usr/share/man
--infodir=/usr/share/info --with-linker-hash-style=gnu --enable-__cxa_atexit
--enable-cet=auto --enable-checking=release --enable-default-pie
--enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object
--enable-link-serialization=1 --enable-linker-build-id --enable-lto
--enable-plugin --enable-shared --enable-threads=posix --disable-libssp
--disable-werror --enable-clocale=gnu --enable-libstdcxx-backtrace
--enable-multilib --disable-libstdcxx-pch --with-build-config=bootstrap-lto
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.0.0 20230115 (experimental) (GCC) 

[waffl3x@waffl3x-manjaro-desktop gcc]$ /opt/compiler/bin/g++ test.cpp
test.cpp: In instantiation of ‘ice(int):: [with int I = 0]’:
test.cpp:11:34:   required from ‘void ice(T) [with T = int]’
test.cpp:15:8:   required from here
test.cpp:7:10: internal compiler error: in tsubst, at cp/pt.cc:16025
7 | auto aa = a;
  |  ^~
0x635279 tsubst(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:16025
0x8278de tsubst_decl
../../gcc-13-20230115/gcc/cp/pt.cc:15194
0x8302c8 tsubst_copy
../../gcc-13-20230115/gcc/cp/pt.cc:17267
0x8200fc tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:21530
0x8248c8 tsubst(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:16547
0x829de5 tsubst_template_args(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:13659
0x821322 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:20299
0x80d340 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:19764
0x80e512 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:18711
0x80e512 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:19041
0x80eb23 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:18711
0x80eb23 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:19105
0x80eb23 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:18711
0x80eb23 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:19105
0x80d0d9 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
../../gcc-13-20230115/gcc/cp/pt.cc:26702
0x80d0d9 instantiate_body
../../gcc-13-20230115/gcc/cp/pt.cc:26702
0x81219d instantiate_decl(tree_node*, bool, bool)
../../gcc-13-20230115/gcc/cp/pt.cc:26992
0x6ffcb3 maybe_instantiate_decl(tree_node*)
../../gcc-13-20230115/gcc/cp/decl2.cc:5448
0x6ffcb3 maybe_instantiate_decl(tree_node*)
../../gcc-13-20230115/gcc/cp/decl2.cc:5435
0x718092 mark_used(tree_node*, int)
../../gcc-13-20230115/gcc/cp/decl2.cc:5747

[waffl3x@waffl3x-manjaro-desktop gcc]$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/12.2.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure
--enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++,d --enable-bootstrap
--prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man
--infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/
--with-build-config=bootstrap-lto --with-linker-hash-style=gnu
--with-system-zlib --enable-__cxa_atexit --enable-cet=auto
--enable-checking=release --enable-clocale=gnu --enable-default-pie
--enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object
--enable-libstdcxx-backtrace --enable-link-serialization=1
--enable-linker-build-id --enable-lto --enable-multilib --enable-plugin
--enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch
--disable-werror
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 12.2.1 20230111 (GCC) 

[waffl3x@waffl3x-manjaro-desktop gcc]$ g++ test.cpp
test.cpp: In instantiation of ‘ice(int):: [with int I = 0]’:
test.cpp:11:34:   required from ‘void ice(T) [with T = int]’
test.cpp:15:8:   required from 

[Bug c++/108998] New: ICE in tsubst, at cp/pt.cc:16037

2023-03-02 Thread waffl3x at protonmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108998

Bug ID: 108998
   Summary: ICE in tsubst, at cp/pt.cc:16037
   Product: gcc
   Version: 13.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: waffl3x at protonmail dot com
  Target Milestone: ---

Created attachment 54573
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=54573=edit
the output of -v on godbolt at the time of posting this report

template
inline constexpr bool templ = false;

template
void ice(T a)
{
auto aa = a;
auto lambda = [](){
if constexpr (templ) {}
};
lambda.template operator()<0>();
}

void go() {
ice(0);
}

https://godbolt.org/z/4qn9s6cad

The conditions for this were rather complicated, this was as far as I could
reduce it. Some things to note,
it does not trigger when the lambda's template parameter is a type parameter,
it does not trigger with an auto function parameter,
it does not trigger outside of if constexpr,
and it does not trigger when the first argument to templ is not a lambda's
template parameter.
I couldn't find a way to trigger it without a lambda's non type template
parameter.

: In instantiation of 'ice(int):: [with int I = 0]':
:11:34:   required from 'void ice(T) [with T = int]'
:15:8:   required from here
:7:10: internal compiler error: in tsubst, at cp/pt.cc:16037
7 | auto aa = a;
  |  ^~
0x247996e internal_error(char const*, ...)
???:0
0xae93fe fancy_abort(char const*, int, char const*)
???:0
0xd11fdd tsubst(tree_node*, tree_node*, int, tree_node*)
???:0
0xd13f4d tsubst_template_args(tree_node*, tree_node*, int, tree_node*)
???:0
0xd09c65 instantiate_decl(tree_node*, bool, bool)
???:0
0xbdf731 maybe_instantiate_decl(tree_node*)
???:0
0xbe11be mark_used(tree_node*, int)
???:0
0xb16f0e build_new_method_call(tree_node*, tree_node*, vec**, tree_node*, int, tree_node**, int)
???:0
0xd09c65 instantiate_decl(tree_node*, bool, bool)
???:0
0xd35ffb instantiate_pending_templates(int)
???:0
0xbe4325 c_parse_final_cleanups()
???:0
0xe215f8 c_common_parse_file()
???:0