[Bug c++/99631] decltype of non-type template-parameter shouldn't be const

2023-09-24 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99631

--- Comment #14 from danakj at orodu dot net ---
Thank you =)

[Bug c++/110158] Cannot use union with std::string inside in constant expression

2023-09-06 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110158

--- Comment #6 from danakj at orodu dot net ---
In case it is of help, here's an even smaller repro that clang reports the
error in libstdc++. For whatever reason gcc does not notice the libstdc++ bug
here.

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

```
#include 

struct S {
constexpr ~S() {}

std::string s;
};

constexpr std::string foo(const S& s) { return s.s; }

static_assert(foo(S("hi")) == "hi");  // Fails.
static_assert(foo(S("a longer string works")) == "a longer string works");

int main() {}
```

The error:
```
:11:15: error: static assertion expression is not an integral constant
expression
static_assert(foo(S("hi")) == "hi");
  ^~~~
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/basic_string.h:356:10:
note: assignment to member '_M_local_buf' of union with no active member is not
allowed in a constant expression
__c = _CharT();
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/basic_string.tcc:229:4:
note: in call to '(("hi")).s->_M_use_local_data()'
  _M_use_local_data();
  ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/basic_string.h:642:2:
note: in call to '(("hi")).s->_M_construct(&"hi"[0], &"hi"[2], {{}})'
_M_construct(__s, __end, forward_iterator_tag());
^
:11:21: note: in call to 'basic_string(&"hi"[0],
std::allocator())'
static_assert(foo(S("hi")) == "hi");
^
1 error generated.
```

[Bug c++/110158] Cannot use union with std::string inside in constant expression

2023-09-06 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110158

--- Comment #5 from danakj at orodu dot net ---
As a means to work around #4 in static asserts, making your string long enough
that it avoids the SSO will allow the compiler to accept it.

[Bug c++/110999] New: GCC rejects static variable with constexpr storage from inline method definition

2023-08-11 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110999

Bug ID: 110999
   Summary: GCC rejects static variable with constexpr storage
from inline method definition
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

Godbolt: https://godbolt.org/z/srvhxjqqz

GCC will accept it if the method definition comes after the `constexpr` storage
definition. But it rejects it if the method definition is inline in the class.

```
struct OutOfLine {
static const OutOfLine kConstant;
constexpr int f();
int i = 2;
};
inline constexpr OutOfLine OutOfLine::kConstant;
// Accepted.
constexpr int OutOfLine::f() { return kConstant.i; }

struct InLine {
static const InLine kConstant;
// Rejected.
constexpr int f() { return kConstant.i; }
int i = 2;
};
inline constexpr InLine InLine::kConstant;

int main() {
constexpr int x = OutOfLine().f();
constexpr int y = InLine().f();
}
```

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

2023-08-06 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110927

Bug ID: 110927
   Summary: GCC fails to parse dependent type in concept through
partial specialization
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

Repro: https://godbolt.org/z/rWbbGzWdb

```
#include 
#include 

template 
struct Foo;

template <>
struct Foo {
template 
using Type = U;
};

struct S {
template 
using Type = U;
};

template 
concept C1 = requires { typename Foo::template Type; };

template 
concept C2 = requires { typename T::template Type; };

int main() {
static_assert(C1);  // Fails with `the required type 'typename
Foo::Type' is invalid`
static_assert(C2);  // Passes.
}
```

This is accepted by Clang and MSVC.

[Bug c++/110905] GCC rejects constexpr code that may re-initialize union member

2023-08-04 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110905

--- Comment #4 from danakj at orodu dot net ---
Ok it only happens if the VecIntoIter class has a base class, even when it's
empty the bug reproduces. But when I remove the IteratorBase base class, then
GCC compiles it correctly.

It's getting hard to remove anything and keep it to repro at this point.
Replacing Option with std::optional also made it stop, for whatever reason.

https://godbolt.org/z/a9PcsKTMf

```
#include 
#include 
#include 
#include 

template 
class Vec;

constexpr int from_sum(auto&& it) noexcept {
auto p = int(0);
while (true) {
auto i = it.next();
if (!i.has_value()) break;
p += *i;
}
return p;
}

template 
struct Storage final {
constexpr ~Storage()
requires(std::is_trivially_destructible_v)
= default;
constexpr ~Storage()
requires(!std::is_trivially_destructible_v)
{}

constexpr Storage(const Storage&)
requires(std::is_trivially_copy_constructible_v)
= default;
constexpr Storage& operator=(const Storage&)
requires(std::is_trivially_copy_assignable_v)
= default;
constexpr Storage(Storage&&)
requires(std::is_trivially_move_constructible_v)
= default;
constexpr Storage& operator=(Storage&&)
requires(std::is_trivially_move_assignable_v)
= default;

constexpr Storage() {}
constexpr Storage(const std::remove_cvref_t& t)
: val_(t), state_(true) {}
constexpr Storage(std::remove_cvref_t& t) : val_(t), state_(true) {}
constexpr Storage(std::remove_cvref_t&& t)
: val_(std::move(t)), state_(true) {}

__attribute__((pure)) constexpr const T& val() const { return val_; }
__attribute__((pure)) constexpr T& val_mut() { return val_; }

__attribute__((pure)) constexpr inline bool state() const noexcept {
return state_;
}

constexpr inline void construct_from_none(const T& t) noexcept
requires(std::is_copy_constructible_v)
{
std::construct_at(_, t);
state_ = true;
}
constexpr inline void construct_from_none(T&& t) noexcept {
std::construct_at(_, std::move(t));
state_ = true;
}

constexpr inline void set_some(const T& t) noexcept
requires(std::is_copy_constructible_v)
{
if (state_ == false)
construct_from_none(t);
else
val_ = t;
state_ = true;
}
constexpr inline void set_some(T&& t) noexcept {
if (state_ == false)
construct_from_none(std::move(t));
else
val_ = std::move(t);
state_ = true;
}

[[nodiscard]] constexpr inline T replace_some(T&& t) noexcept {
return std::exchange(val_, std::move(t));
}

[[nodiscard]] constexpr inline T take_and_set_none() noexcept {
state_ = false;
auto taken = T(static_cast(val_));
val_.~T();
return taken;
}

constexpr inline void set_none() noexcept {
state_ = false;
val_.~T();
}

constexpr inline void destroy() noexcept { val_.~T(); }

   private:
union {
T val_;
};
bool state_ = false;
};

template 
class Option final {
static_assert(!std::is_reference_v);
static_assert(!std::is_const_v);

   public:
inline constexpr Option() noexcept = default;

static inline constexpr Option with(const T& t) noexcept
requires(std::is_copy_constructible_v)
{
return Option(t);
}

static inline constexpr Option with(T&& t) noexcept {
if constexpr (std::is_move_constructible_v) {
return Option(std::move(t));
} else {
return Option(t);
}
}

constexpr ~Option() noexcept
requires(std::is_trivially_destructible_v)
= default;

constexpr inline ~Option() noexcept
requires(!std::is_trivially_destructible_v)
{
if (t_.state()) t_.destroy();
}

constexpr Option(Option&& o)
requires(std::is_trivially_move_constructible_v)
= default;

constexpr Option(Option&& o) noexcept
requires(!std::is_trivially_move_constructible_v)
{
if (o.t_.state()) t_.construct_from_none(o.t_.take_and_set_none());
}

constexpr Option(Option&& o)
requires(!std::is_move_constructible_v)
= delete;

constexpr Option& operator=(Option&& o)
requires(std::is_trivially_move_assignable_v)
= default;

constexpr Option& operator=(Option&& o) noexcept
requires(!std::is_trivially_move_assignable_v)
{
if (o.t_.state())
t_.set_some(o.t_.take_and_set_none());
else if (t_.state())
t_.set_none();
return *this;
}

constexpr Option& operator=(Option&& o)
requires(!std::is_move_constructible_v)
= delete;

__attribute__((pure)) constexpr bool has_value() const noexcept {
return t_.state();
}


[Bug c++/110905] GCC rejects constexpr code that may re-initialize union member

2023-08-04 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110905

--- Comment #3 from danakj at orodu dot net ---
Repro down from 37k to under 1000 lines now: https://godbolt.org/z/enMxaqjb6

[Bug c++/110905] GCC rejects constexpr code that may re-initialize union member

2023-08-04 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110905

--- Comment #2 from danakj at orodu dot net ---
Ah ok. Here's a big reproduction: https://godbolt.org/z/Kj7Tcd6P4

/opt/compiler-explorer/gcc-trunk-20230804/include/c++/14.0.0/bits/stl_construct.h:97:14:
  in 'constexpr' expansion of
'((sus::containers::VecIntoIter*))->sus::containers::VecIntoIter::VecIntoIter((*
& std::forward >((* & __args#0'
:32895:22: error: use of deleted function
'sus::option::__private::Storage,
false>()'
32895 | struct [[nodiscard]] VecIntoIter final
  |  ^~~
:3015:9: note:
'sus::option::__private::Storage,
false>()' is implicitly deleted because the
default definition would be ill-formed:
 3015 |   union {
  | ^
:3015:9: error: no matching function for call to
'sus::containers::VecIntoIter::VecIntoIter()'
:32953:13: note: candidate: 'constexpr
sus::containers::VecIntoIter::VecIntoIter(sus::containers::Vec&&,
sus::num::usize, sus::num::usize) [with ItemT = sus::num::i32]'
32953 |   constexpr VecIntoIter(Vec&& vec, usize front, usize back)
noexcept
  | ^~~
:32953:13: note:   candidate expects 3 arguments, 0 provided
:32951:13: note: candidate: 'constexpr
sus::containers::VecIntoIter::VecIntoIter(sus::containers::Vec&&)
[with ItemT = sus::num::i32]'
32951 |   constexpr VecIntoIter(Vec&& vec) noexcept :
vec_(::sus::move(vec)) {}
  | ^~~
:32951:13: note:   candidate expects 1 argument, 0 provided
:32895:22: note: candidate: 'constexpr
sus::containers::VecIntoIter::VecIntoIter(sus::containers::VecIntoIter&&)'
32895 | struct [[nodiscard]] VecIntoIter final
  |  ^~~
:32895:22: note:   candidate expects 1 argument, 0 provided
Compiler returned: 1


I will try to shrink it now.

[Bug c++/110905] New: GCC rejects constexpr code that may re-initialize union member

2023-08-04 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110905

Bug ID: 110905
   Summary: GCC rejects constexpr code that may re-initialize
union member
   Product: gcc
   Version: 13.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

Godbolt: https://gcc.godbolt.org/z/v5anxqnP1

This repro contains a std::optional (which has a union) and it sets the union
in a loop. Doing so causes GCC to reject the code as not being a constant
expression. The error I was getting in my project was far more descriptive,
with it trying to call the deleted constructor of the union.

error: use of deleted function
‘sus::option::__private::Storage,
false>()’

In my more minimal test case the error is more terse and less clear.

:62:59: error: non-constant condition for static assertion
   62 | static_assert(Flatten({{1, 2, 3}, {}, {4, 5}}).sum() == 1 + 2 + 3
+ 4 + 5);
  |  
^~~~
:62:51: error: '(((const std::vector
>*)(&)) != 0)' is not a constant expression
   62 | static_assert(Flatten({{1, 2, 3}, {}, {4, 5}}).sum() == 1 + 2 + 3
+ 4 + 5);
  |   

```cpp
#include 
#include 

template 
struct VectorIter {
constexpr std::optional next() {
if (front == back) return std::optional();
T& item = v[front];
front += 1u;
return std::optional(std::move(item));
}

constexpr VectorIter(std::vector v2) : v(std::move(v2)), front(0u),
back(v.size()) {}
VectorIter(VectorIter&&) = default;
VectorIter& operator=(VectorIter&&) = default;

std::vector v;
size_t front;
size_t back;
};

template 
struct Flatten {
constexpr Flatten(std::vector> v) : vec(std::move(v)) {}

constexpr std::optional next() {
std::optional out;
while (true) {
// Take an item off front_iter_ if possible.
if (front_iter_.has_value()) {
out = front_iter_.value().next();
if (out.has_value()) return out;
front_iter_ = std::nullopt;
}
// Otherwise grab the next vector into front_iter_.
if (!vec.empty()) {
std::vector v = std::move(vec[0]);
vec.erase(vec.begin());
front_iter_.emplace([](auto&& iter) {
return VectorIter(std::move(iter));
}(std::move(v)));
}
if (!front_iter_.has_value()) break;
}
return out;
}

constexpr T sum() && {
T out = T();
while (true) {
std::optional i = next();
if (!i.has_value()) break;
out += *i;
}
return out;
}

std::vector> vec;
std::optional> front_iter_;
};

static_assert(Flatten({{1, 2, 3}, {}, {4, 5}}).sum() == 1 + 2 + 3 + 4 +
5);

int main() {}

```

When the Flatten::next() method is simplified a bit, so that it can see the
union is only initialized once, the GCC compiler no longer rejects the code.
https://gcc.godbolt.org/z/szfGsdxb7

```cpp
#include 
#include 

template 
struct VectorIter {
constexpr std::optional next() {
if (front == back) return std::optional();
T& item = v[front];
front += 1u;
return std::optional(std::move(item));
}

constexpr VectorIter(std::vector v2) : v(std::move(v2)), front(0u),
back(v.size()) {}
VectorIter(VectorIter&&) = default;
VectorIter& operator=(VectorIter&&) = default;

std::vector v;
size_t front;
size_t back;
};

template 
struct Flatten {
constexpr Flatten(std::vector v) : vec(std::move(v)) {}

constexpr std::optional next() {
std::optional out;
while (true) {
// Take an item off front_iter_ if possible.
if (front_iter_.has_value()) {
out = front_iter_.value().next();
if (out.has_value()) return out;
front_iter_ = std::nullopt;
}
// Otherwise grab the next vector into front_iter_.
if (!moved) {
std::vector v = std::move(vec);
moved = true;
front_iter_.emplace([](auto&& iter) {
return VectorIter(std::move(iter));
}(std::move(v)));
}
if (!front_iter_.has_value()) break;
}
return out;
}

constexpr T sum() && {
T out = T();
while (true) {
std::optional i = next();
if (!i.has_value()) break;
out += *i;
}
return out;
}

bool moved = false;
std::vector vec;
std::optional> front_iter_;
};

static_assert(Flatten({1, 2, 3}).sum() == 1 + 2 + 3);

int main() {}
```

Yet in the first example, the GCC 

[Bug libstdc++/110900] std::string initializes SSO object subfield without making the SSO object active in the union

2023-08-04 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110900

--- Comment #6 from danakj at orodu dot net ---
Thanks for the link, I used the godbolt from that bug to set up the right
environment and that let me minimize it. I posted it into the dupe bug.

[Bug c++/110158] Cannot use union with std::string inside in constant expression

2023-08-04 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110158

--- Comment #4 from danakj at orodu dot net ---
Here's a repro without the std::string inside a union. It is the SSO union
inside the string that causes the error.

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

```
#include 

template 
constexpr T fold(T init, I i, S s, F f) {
while (true) {
if (i == s)
return init;
else
init = f(std::move(init), *i++);
}
}

constexpr char v[] = {'a', 'b', 'c'};
static_assert(fold(std::string(), std::begin(v), std::end(v),
   [](std::string acc, char v) {
   acc.push_back(v);
   return acc;
   }) == "abc");

int main() {}
```

:18:23: error: non-constant condition for static assertion
   14 | static_assert(fold(std::string(), std::begin(v), std::end(v),
  |   ~~~
   15 |[](std::string acc, char v) {
  |~
   16 |acc.push_back(v);
  |~
   17 |return acc;
  |~~~
   18 |}) == "abc");
  |~~~^~~~
:18:32:   in 'constexpr' expansion of 'fold(T, I, S, F) [with T =
std::__cxx11::basic_string; I = const char*; S = const char*; F =
](std::begin(v), std::end(v), ((),
()))'
:18:32:   in 'constexpr' expansion of
'std::__cxx11::basic_string((* &
std::move<__cxx11::basic_string&>(init)))'
:18:23: error: accessing 'std::__cxx11::basic_string_M_allocated_capacity' member instead of initialized
'std::__cxx11::basic_string_M_local_buf' member in
constant expression
ASM generation compiler returned: 1

[Bug libstdc++/110900] std::string initializes SSO object subfield without making the SSO object active in the union

2023-08-04 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110900

--- Comment #5 from danakj at orodu dot net ---
> Can you please read https://gcc.gnu.org/bugs/ on what we need?

Yeah, sorry I can't reproduce this locally on my Mac or Windows machine. It
reproduces on github Linux CI bots, and I have diagnosed it from there.

https://github.com/chromium/subspace/actions/runs/5758764036/job/15611774084?pr=306

This job is using gcc 13.1.0, and it installs libstdc++-13-dev.

Here's the command that fails:

/usr/bin/g++-13  -I/home/runner/work/subspace/subspace
-I/home/runner/work/subspace/subspace/third_party/googletest
-I/home/runner/work/subspace/subspace/third_party/fmt/include -isystem
/home/runner/work/subspace/subspace/third_party/googletest/googletest/include
-isystem /home/runner/work/subspace/subspace/third_party/googletest/googletest
-isystem /usr/include/c++/13 -isystem /usr/include/x86_64-linux-gnu/c++/13
-isystem /usr/include/c++/13/backward -isystem
/usr/lib/gcc/x86_64-linux-gnu/13/include -isystem /usr/local/include -isystem
/usr/include/x86_64-linux-gnu -isystem /usr/include -O3 -DNDEBUG -std=gnu++20
-fno-rtti -Werror -MD -MT
sus/CMakeFiles/subspace_unittests.dir/iter/iterator_unittest.cc.o -MF
sus/CMakeFiles/subspace_unittests.dir/iter/iterator_unittest.cc.o.d -o
sus/CMakeFiles/subspace_unittests.dir/iter/iterator_unittest.cc.o -c
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc

I think it's simplest to just do a git clone and build that though... as I
can't easily minmize this.

[Bug libstdc++/110900] std::string initializes SSO object subfield without making the SSO object active in the union

2023-08-04 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110900

--- Comment #4 from danakj at orodu dot net ---
The error message is the same as 110158 but to be clear the std::string is not
in a union. The error message is about the union _inside_ std::string.

[Bug c++/110900] std::string initializes SSO object subfield without making the SSO object active in the union

2023-08-04 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110900

--- Comment #1 from danakj at orodu dot net ---
I am going to try work around this by not using std::string in constant
expressions..

So in the meantime I pushed a branch where this bug will continue to reproduce.

With gcc-13:

git clone --recurse-submodules https://github.com/danakj/subspace
cd subspace
git checkout test origin/libstd-bug-sso
CXX=path/to/gcc-13 cmake -B out -DSUBSPACE_BUILD_TESTS=ON
cmake --build out -j 20

[Bug c++/110900] New: std::string initializes SSO object subfield without making the SSO object active in the union

2023-08-04 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110900

Bug ID: 110900
   Summary: std::string initializes SSO object subfield without
making the SSO object active in the union
   Product: gcc
   Version: 11.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

Specific errors by clang:

note: construction of subobject of member '_M_local_buf' of union with no
active member is not allowed in a constant expression

error: accessing ‘std::__cxx11::basic_string_M_allocated_capacity’ member instead of initialized
‘std::__cxx11::basic_string_M_local_buf’ member in
constant expression

Specific error by GCC:

error: accessing ‘std::__cxx11::basic_string_M_allocated_capacity’ member instead of initialized
‘std::__cxx11::basic_string_M_local_buf’ member in
constant expression

Full errors:

Here's the clang 17 error:

/usr/include/c++/12/bits/stl_construct.h:97:14: note: construction of subobject
of member '_M_local_buf' of union with no active member is not allowed in a
constant expression
   97 | { return ::new((void*)__location)
_Tp(std::forward<_Args>(__args)...); }
  |  ^
/usr/include/c++/12/bits/char_traits.h:262:6: note: in call to
'construct_at(&[]() {
std::string acc;
sus::Array::with('a', 'b', 'c', 'd',
'e').into_iter().for_each([&](char v) {
acc.push_back(v);
});
return acc;
}().._M_local_buf[0], acc.._M_local_buf[0])'
  262 | std::construct_at(__s1 + __i, __s2[__i]);
  | ^
/usr/include/c++/12/bits/char_traits.h:429:11: note: in call to 'copy(&[]() {
std::string acc;
sus::Array::with('a', 'b', 'c', 'd',
'e').into_iter().for_each([&](char v) {
acc.push_back(v);
});
return acc;
}().._M_local_buf[0], _M_local_buf[0], 6)'
  429 |   return __gnu_cxx::char_traits::copy(__s1, __s2,
__n);
  |  ^
/usr/include/c++/12/bits/basic_string.h:675:6: note: in call to 'copy(&[]() {
std::string acc;
sus::Array::with('a', 'b', 'c', 'd',
'e').into_iter().for_each([&](char v) {
acc.push_back(v);
});
return acc;
}().._M_local_buf[0], _M_local_buf[0], 6)'
  675 | traits_type::copy(_M_local_buf, __str._M_local_buf,
  | ^
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1864:12:
note: in call to 'basic_string(acc)'
 1864 | return acc;
  |^
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1859:17:
note: in call to '[]() {
std::string acc;
sus::Array::with('a', 'b', 'c', 'd',
'e').into_iter().for_each([&](char v) {
acc.push_back(v);
});
return acc;
}.operator()()'
 1859 |   static_assert([]() {
  | ^

Here's the g++ 13 error:
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:24:
error: non-constant condition for static assertion
 1787 |   static_assert(sus::Array::with('a', 'b', 'c', 'd', 'e')
  | ~~
 1788 | .into_iter()
  | 
 1789 | .fold(std::string(), [](std::string acc, char v) {
  | ~~
 1790 |   acc.push_back(v);
  |   ~
 1791 |   return acc;
  |   ~~~
 1792 | }) == "abcde");
  | ~~~^~
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:35:   in
‘constexpr’ expansion of ‘sus::iter::IteratorBase::fold(B, F) &&
[with B = std::__cxx11::basic_string; F =
{anonymous}::Iterator_Fold_Test::TestBody()::; Iter
= sus::containers::ArrayIntoIter; ItemT =
char](std::__cxx11::basic_string(), ({anonymous}::Iterator_Fold_Test::TestBody()::(), {anonymous}::Iterator_Fold_Test::TestBody()::()))’
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:35:   in
‘constexpr’ expansion of ‘sus::fn::call_mut(F&&, Args&& ...) [with F =
{anonymous}::Iterator_Fold_Test::TestBody()::&; Args
= {std::__cxx11::basic_string,
std::allocator >, char}]((* &
sus::mem::move&>(init)), (&
sus::mem::move&>(o))->sus::option::Option::unwrap())’
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:35:   in
‘constexpr’ expansion of ‘std::invoke(_Callable&&, _Args&& ...) [with _Callable
= {anonymous}::Iterator_Fold_Test::TestBody()::&; _Args =
{__cxx11::basic_string, allocator >, char};
invoke_result_t<_Fn, _Args ...> = __cxx11::basic_string]((* &
sus::mem::forward >((* & args#0))), (* &
sus::mem::forward((* & args#1’
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:35:   in
‘constexpr’ 

[Bug c++/110245] constant evaluation fails with uninitialized union and default constructor

2023-06-13 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110245

--- Comment #1 from danakj at orodu dot net ---
Note that GCC has no problem with doing this constexpr construction if the
object is not stored as an lvalue.

```
struct Store {
constexpr Store() {}
union {
int i;
};
bool b = false;
};

struct C {
constexpr C() = default;

Store s;
};

int main() {
constexpr auto c = C(); // Fails.
constexpr auto b = C().s.b; // OK
}
```

https://godbolt.org/z/31MTenKoo

[Bug c++/110245] New: constant evaluation fails with uninitialized union and default constructor

2023-06-13 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110245

Bug ID: 110245
   Summary: constant evaluation fails with uninitialized union and
default constructor
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

```
struct Store {
constexpr Store() {}
union {
int i;
};
bool b = false;
};

struct C {
constexpr C() = default;

Store s;
};

int main() {
constexpr auto c = C(); //
}
```

This should compile but does not, GCC complains that it refers to an
incompletely initialized variable. Union members are not required to be active.

https://godbolt.org/z/G9vcosTG1

Reproduced on GCC trunk and GCC 11.

[Bug c++/103760] Invalid expression inside lambda inside compound requirement causes an error instead of concept satisfaction failure

2023-06-12 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103760

danakj at orodu dot net changed:

   What|Removed |Added

 CC||danakj at orodu dot net

--- Comment #7 from danakj at orodu dot net ---
MSVC and Clang both accept this code, which GCC rejects. Is it the same issue
and GCC is compliant here?

```
#include 

template 
concept C = requires() {
{
[](T t) constexpr { t.foo(1); }()
};
};

void bad_call(const char*);

struct Foo {
consteval void foo(int i) {
if (i > 0) {
bad_call("positive_value");
}
}
};

static_assert(!C);
```

https://godbolt.org/z/bdrPve4rT

[Bug c++/99599] [11/12/13/14 Regression] Concepts requirement falsely reporting cyclic dependency, breaks tag_invoke pattern

2023-06-07 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99599

--- Comment #16 from danakj at orodu dot net ---
Well for anyone who hits the same issue, it appears that GCC _does_ follow
Clang and MSVC in not considering the overload and chasing through the concept
resolution if the non-concept types are templates and do not match the caller's
arguments.

So you need to do:

1) For non-GCC just use:

  template auto invoke_tag(bar_tag, T it);

2) For GCC non-template type bar_tag use:

  template T, fooable U> auto invoke_tag(T, U it);

3) For GCC template type bar_tag, back to 1)

  template auto invoke_tag(bar_tag, T it);


Note also that 2) uses same_as, not convertible_to as in Comment #6, otherwise
you can get ambiguous overload resolution if multiple types convert to one,
which does not occur in Clang/MSVC with the regular type parameter. This _does_
again result in more code that will compile in Clang/MSVC than in GCC, as it
prevents conversions from types that don't have an overload.

The macros to do this get rather exciting, if that's of interest to someone in
the future:
https://github.com/chromium/subspace/pull/253/commits/719500c4d2cbfcfd238d7ee3c5b3d371f40e46c1

[Bug c++/99599] [11/12/13/14 Regression] Concepts requirement falsely reporting cyclic dependency, breaks tag_invoke pattern

2023-06-07 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99599

--- Comment #15 from danakj at orodu dot net ---
The workaround listed in Comment #6 does not work for templated types,
unfortunately, making Clang and MSVC more expressive here than GCC.

https://godbolt.org/z/obhsqhrbx

```
#include 
#include 
#include 

#if defined(__GNUC__) && !defined(__clang__)
#define COMPILER_IS_GCC 1
#else
#define COMPILER_IS_GCC 0
#endif

namespace sus::string::__private {
template 
A& format_to_stream(A&, B);

template 
concept StreamCanReceiveString = requires(T& t, std::basic_string s) {
{ operator<<(t, s) };
};

/// Consumes the string `s` and streams it to the output stream `os`.
template  S>
S& format_to_stream(S& os, const std::basic_string& s) {
os << s;
return os;
}

}  // namespace sus::string::__private

namespace sus::option {
template 
class Option {};

using namespace ::sus::string::__private;
template <
class T, 
#if COMPILER_IS_GCC
std::same_as > Sus_ValueType,  // Does not deduce T.  *
#endif
StreamCanReceiveString Sus_StreamType
>
inline Sus_StreamType& operator<<(
Sus_StreamType& stream,
#if COMPILER_IS_GCC
const Sus_ValueType& value
#else
const ::sus::option::Option& value  // Does deduce T.   
#endif
) {
return format_to_stream(stream, std::string());
}

}  // namespace sus::option

int main() {
std::stringstream s;
s << sus::option::Option();
}
```

[Bug c++/110160] g++ rejects concept as cyclical with non-matching function signature

2023-06-07 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110160

danakj at orodu dot net changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |DUPLICATE

--- Comment #3 from danakj at orodu dot net ---
Okay I've got a workaround based on
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99599#c6. It's probably worse for
compile times, but it is what it is.

Thanks for the link.

*** This bug has been marked as a duplicate of bug 99599 ***

[Bug c++/99599] [11/12/13/14 Regression] Concepts requirement falsely reporting cyclic dependency, breaks tag_invoke pattern

2023-06-07 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99599

danakj at orodu dot net changed:

   What|Removed |Added

 CC||danakj at orodu dot net

--- Comment #14 from danakj at orodu dot net ---
*** Bug 110160 has been marked as a duplicate of this bug. ***

[Bug c++/110160] g++ rejects concept as cyclical with non-matching function signature

2023-06-07 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110160

--- Comment #2 from danakj at orodu dot net ---
Ugh, yeah, I guess it is. It means you can't redirect through a template
function that uses concepts with G++.

[Bug c++/110160] New: g++ rejects concept as cyclical with non-matching function signature

2023-06-07 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110160

Bug ID: 110160
   Summary: g++ rejects concept as cyclical with non-matching
function signature
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

Godbolt: https://godbolt.org/z/d4PhfMqvq

Code:
```
#include 
#include 

template 
concept StreamCanReceiveString = requires(T& t, std::string s) {
{ t << s };
};

struct NotAStream {};
struct UnrelatedType {};

template 
S& operator<<(S& s, UnrelatedType) {
return s;
}

static_assert(!StreamCanReceiveString);

static_assert(StreamCanReceiveString);
```

What happens here is GCC fails to be able to resolve the expression
`StreamCanReceiveString`.

1. StreamCanReceiveString tries to do NotAStream << std::string.
2. There is a templated operator<< that takes `StreamCanReceiveString` and
`UnrelatedType`
3. Since `UnrelatedType` is not std::string, this is not an overload candidate.
4. Clang and MSVC therefore do not try to recursively solve
`StreamCanReceiveString` and reject the code. But GCC tries to
solve the concept and then fails due to recursion.

[Bug c++/108897] Comparing pointer to field in rvalue class is not considered constant expression

2023-02-22 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108897

--- Comment #2 from danakj at orodu dot net ---
Thank you for the workaround!

[Bug c++/108897] New: Comparing pointer to field in rvalue class is not considered constant expression

2023-02-22 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108897

Bug ID: 108897
   Summary: Comparing pointer to field in rvalue class is not
considered constant expression
   Product: gcc
   Version: 13.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

This reproduces on godbolt in GCC 10, 11, 12, and trunk.

A pointer to a field of a structure that is constructed as an rvalue temporary
object can not be compared in a constant expression.

```
struct S {
int i;
int *p = 
constexpr const int* ptr() const { return  }
};

// Not constant expression in GCC.
static_assert(S{2}.ptr() != nullptr);
static_assert(S{2}.p != nullptr);

// Is a constant expression.
static_assert(*S{2}.ptr() == 2);
static_assert(*S{2}.p == 2);

static_assert([]() constexpr {
S r(2);

// Is a constant expression.
return r.ptr() != nullptr && r.p != nullptr;
}());
```

Errors:
:8:26: error: non-constant condition for static assertion
8 | static_assert(S{2}.ptr() != nullptr);
  |   ~~~^~
:8:26: error: '((&.S::i) != 0)' is not a constant expression
:9:22: error: non-constant condition for static assertion
9 | static_assert(S{2}.p != nullptr);
  |   ~~~^~
:9:22: error: '((&.S::i) != 0)' is not a constant expression


- Generates errors for comparing `ptr()` or `p` to nullptr.
- Dereferencing the pointer does not generate an error.
- If the object S is stored as an lvalue, then the pointer comparison is a
constant expression.

Godbolt: https://godbolt.org/z/P9GGKeb3Y

[Bug c++/108775] Move construction clobbers data through [[no_unique_address]]

2023-02-13 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108775

--- Comment #1 from danakj at orodu dot net ---
This occurs on 12.2.0 Linux, as well as GCC trunk on Godbolt in C++20 mode.

[Bug c++/108775] New: Move construction clobbers data through [[no_unique_address]]

2023-02-13 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108775

Bug ID: 108775
   Summary: Move construction clobbers data through
[[no_unique_address]]
   Product: gcc
   Version: 12.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

Clang also clobbers data in the same way:
https://github.com/llvm/llvm-project/issues/60711

(MSVC does not)

```
#include 

#include 
#include 
#include 

struct S2 {
uint64_t a;
};

struct S : public S2 {
S(uint8_t b, uint64_t a) : S2(a), b(b) {}
uint8_t b;
// 3 bytes padding.
};
static_assert(sizeof(S) == 16);

union U {
U() {}
[[no_unique_address]] S s;
};
static_assert(sizeof(U) == 16);

struct D {
D(uint8_t i) : i(i) {}

[[no_unique_address]] U u;
uint8_t i;
};
static_assert(sizeof(D) == 16);

int main() {
D d(1u);
std::cout << (int)d.i << "\n";

// Regular construction into `D::u` doesn't touch `D::i`. Good.
new () S(2, 3);
std::cout << (int)d.i << "\n";

S s(4, 5);
// Move construction into `D::u` overwrites `D::i`. Bad.
new () S(std::move(s));
std::cout << (int)d.i << "\n";
return d.i;
}
```

Godbolt: https://godbolt.org/z/YzrM59E5a

[Bug c++/108169] class type template parameters are const in GCC (differs from other compilers)

2022-12-19 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108169

--- Comment #1 from danakj at orodu dot net ---
Sorry I inverted my logic.

In Clang and MSVC an `auto` class-type template parameter is not const. In GCC
it is.

[Bug c++/108169] New: class type template parameters are non-const in GCC (differs from other compilers)

2022-12-19 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108169

Bug ID: 108169
   Summary: class type template parameters are non-const in GCC
(differs from other compilers)
   Product: gcc
   Version: 13.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

Reproduces on GCC 10, 11, 12 and Trunk.

An auto template parameter's type is const in Clang and MSVC, but is considered
non-const in GCC. This does not occur with primitive types, but it does with
class types.

This is a C++20 bug, as C++20 introduced class type template parameters. With
-std=c++17, gcc states as such:
```
:15:26: error: non-type template parameters of class type only
available with '-std=c++20' or '-std=gnu++20'
```

Source code:
```
#include 

template 
struct S {
static constexpr bool is_const = std::is_const_v;
};

struct W {
constexpr W(int i) : i(i) {}
int i;
};

int main() {
static_assert(!S<1>::is_const);  // pass
static_assert(!S::is_const);  // fail
}
```

Godbolt: https://godbolt.org/z/WEbPcjzcK

[Bug c++/108067] Miscompilation with friend function with parameter pack: mismatched argument pack lengths

2022-12-11 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108067

--- Comment #1 from danakj at orodu dot net ---
Notably, this occurs with friend operator== or operator<=>.

[Bug c++/108067] New: Miscompilation with friend function with parameter pack: mismatched argument pack lengths

2022-12-11 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108067

Bug ID: 108067
   Summary: Miscompilation with friend function with parameter
pack: mismatched argument pack lengths
   Product: gcc
   Version: 12.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

The following code compiles in Clang and MSVC but not in GCC.

Repros in GCC 10, 11, 12, and trunk.

```
template 
static constexpr bool C = true;

template 
struct Foo {
template 
requires((... && C))
void bar(const Foo& r) {}

template 
requires((... && C))
friend void baz(const Foo& l, const Foo& r) {}
};

int main() {
Foo x;

x.bar(Foo());  // Works.

baz(x, Foo());  // Doesn't work.
}
```

godbolt: https://godbolt.org/z/3Ybofbcoc

: In instantiation of 'struct Foo':
:16:19:   required from here
:12:17: error: mismatched argument pack lengths while expanding 'C'
   12 | friend void baz(const Foo& l, const Foo& r) {}
  | ^~~
ASM generation compiler returned: 1
: In instantiation of 'struct Foo':
:16:19:   required from here
:12:17: error: mismatched argument pack lengths while expanding 'C'
   12 | friend void baz(const Foo& l, const Foo& r) {}
  | ^~~
Execution build compiler returned: 1

[Bug c++/108066] ICE in use_pack_expansion_extra_args_p, at cp/pt.cc:12661

2022-12-11 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108066

danakj at orodu dot net changed:

   What|Removed |Added

Version|12.2.0  |13.0

--- Comment #1 from danakj at orodu dot net ---
This does not reproduce in 12.2, but it does on trunk.

[Bug c++/108066] New: ICE in use_pack_expansion_extra_args_p, at cp/pt.cc:12661

2022-12-11 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108066

Bug ID: 108066
   Summary: ICE in use_pack_expansion_extra_args_p, at
cp/pt.cc:12661
   Product: gcc
   Version: 12.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

```
template 
struct Foo;

template 
concept C = true;

template 
struct Foo {
template 
requires ((... && C))
friend void bar(Foo, Foo) {}
};

int main() {
Foo x;
bar(x, Foo());
}
```

godbolt: https://godbolt.org/z/KozobKa1q

: In instantiation of 'struct Foo':
:15:14:   required from here
:10:27: internal compiler error: in use_pack_expansion_extra_args_p, at
cp/pt.cc:12661
   10 | requires ((... && C))
  |  ~^
0x22efc1e internal_error(char const*, ...)
???:0
0xa4af9a fancy_abort(char const*, int, char const*)
???:0
0xabf850 tsubst_constraint(tree_node*, tree_node*, int, tree_node*)
???:0
0xabf939 maybe_substitute_reqs_for(tree_node*, tree_node const*)
???:0
0xc7c12c instantiate_class_template(tree_node*)
???:0
0xafe1a3 start_decl_1(tree_node*, bool)
???:0
0xb1ffb7 start_decl(cp_declarator const*, cp_decl_specifier_seq*, int,
tree_node*, tree_node*, tree_node**)
???:0
0xc242c7 c_parse_file()
???:0
0xd5e809 c_common_parse_file()
???:0
Please submit a full bug report, with preprocessed source (by using
-freport-bug).
Please include the complete backtrace with any bug report.
See  for instructions.
ASM generation compiler returned: 1
: In instantiation of 'struct Foo':
:15:14:   required from here
:10:27: internal compiler error: in use_pack_expansion_extra_args_p, at
cp/pt.cc:12661
   10 | requires ((... && C))
  |  ~^
0x22efc1e internal_error(char const*, ...)
???:0
0xa4af9a fancy_abort(char const*, int, char const*)
???:0
0xabf850 tsubst_constraint(tree_node*, tree_node*, int, tree_node*)
???:0
0xabf939 maybe_substitute_reqs_for(tree_node*, tree_node const*)
???:0
0xc7c12c instantiate_class_template(tree_node*)
???:0
0xafe1a3 start_decl_1(tree_node*, bool)
???:0
0xb1ffb7 start_decl(cp_declarator const*, cp_decl_specifier_seq*, int,
tree_node*, tree_node*, tree_node**)
???:0
0xc242c7 c_parse_file()
???:0
0xd5e809 c_common_parse_file()
???:0
Please submit a full bug report, with preprocessed source (by using
-freport-bug).
Please include the complete backtrace with any bug report.
See  for instructions.
Execution build compiler returned: 1

[Bug c++/107544] Friended struct with concept gives different output in clang/gcc/MSVC

2022-11-06 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107544

--- Comment #4 from danakj at orodu dot net ---
It looks related but I am not sure it is a duplicate. In this case, the concept
is being used from a non-friend context first and still accessing the private
data. In that bug, they demonstrate clang having the same output, but here
clang and GCC differ as well.

```
std::cout << HasTag << "\n";
std::cout << check_tag::value() << "\n";
```

Reordering these statements does not change the output.

[Bug c++/107544] Friended struct with concept gives different output in clang/gcc/MSVC

2022-11-06 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107544

--- Comment #1 from danakj at orodu dot net ---
Clang report: https://github.com/llvm/llvm-project/issues/58833

[Bug c++/107544] New: Friended struct with concept gives different output in clang/gcc/MSVC

2022-11-06 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107544

Bug ID: 107544
   Summary: Friended struct with concept gives different output in
clang/gcc/MSVC
   Product: gcc
   Version: 12.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

I don't know which compiler is right, but all three give a different output. So
I will report it here, as the GCC result looks wrong and exposes private data.

https://godbolt.org/z/7Pq3eWhc8

```
#include 
#include 
#include 

template 
concept HasTag = requires {
T::Tag;
requires std::same_as;
};

template 
struct check_tag final {
static constexpr bool value()
requires(!HasTag)
{
return false;
}

static constexpr bool value()
requires(HasTag)
{
return T::Tag;
};
};

struct S {
   private:
template 
friend struct check_tag;
static constexpr bool Tag = true;
};

int main() {
std::cout << HasTag << "\n";
std::cout << check_tag::value() << "\n";
}
```

Clang output (the concept sees private data if used in friend):
0
1

GCC output (the concept always sees private data):
1
1

MSVC output (the concept never sees private data):
0
0

[Bug c++/107542] ICE in spaceship_comp_cat, at cp/method.cc:1055

2022-11-06 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107542

--- Comment #3 from danakj at orodu dot net ---
> Note please next time also attach the testcase (or put it inline) and not 
> just link against godbolt.

Will do, thanks for attaching it for me.

[Bug c++/107542] ICE in spaceship_comp_cat, at cp/method.cc:1055

2022-11-06 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107542

--- Comment #2 from danakj at orodu dot net ---
The same thing works okay with operator== instead of operator<=>

https://godbolt.org/z/qnPx3bYT4

```
#include 
#include 

template 
concept Ord = requires(const Lhs& lhs, const Rhs& rhs) {
{ lhs <=> rhs } -> std::same_as;
};

template 
concept Eq = requires(const Lhs& lhs, const Rhs& rhs) {
{ lhs == rhs } -> std::same_as;
};

template 
struct S {
T* p;
};

template 
requires(Eq)
bool operator==(const S& l, const S& r) {
return l.p == r.p;
}

template 
requires(Ord)
constexpr inline auto operator<=>(const S& l, const S& r) noexcept {
return l.p <=> r.p;
}

static_assert(Ord, S>);  // Works.
// static_assert(!Ord, S>>);  // ICE.

static_assert(Eq, S>);  // Works.
static_assert(!Eq, S>);  // Works.
```

[Bug c++/107542] New: ICE in spaceship_comp_cat, at cp/method.cc:1055

2022-11-06 Thread danakj at orodu dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107542

Bug ID: 107542
   Summary: ICE in spaceship_comp_cat, at cp/method.cc:1055
   Product: gcc
   Version: 12.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: danakj at orodu dot net
  Target Milestone: ---

Repro: https://godbolt.org/z/KPfsn8hPf

Reproduces in 12.2 and trunk on Godbolt.org.

Output:
: In substitution of 'template  requires  Ord constexpr auto operator<=>(const S&, const S&) [with T =
int; U = char]':
:6:11:   required from here
:6:11: internal compiler error: in spaceship_comp_cat, at
cp/method.cc:1055
6 | { lhs <=> rhs } -> std::same_as;
  |   ^~~
0x2393c6e internal_error(char const*, ...)
???:0
0xaa9b58 fancy_abort(char const*, int, char const*)
???:0
0xd4a507 cp_build_binary_op(op_location_t const&, tree_code, tree_node*,
tree_node*, int)
???:0
0xadb22c build_new_op(op_location_t const&, tree_code, int, tree_node*,
tree_node*, tree_node*, tree_node*, tree_node**, int)
???:0
0xd3b412 build_x_binary_op(op_location_t const&, tree_code, tree_node*,
tree_code, tree_node*, tree_code, tree_node*, tree_node**, int)
???:0
0xb25576 tsubst_requires_expr(tree_node*, tree_node*, int, tree_node*)
???:0
0xb27052 constraints_satisfied_p(tree_node*, tree_node*)
???:0
0xcdd84a fn_type_unification(tree_node*, tree_node*, tree_node*, tree_node*
const*, unsigned int, tree_node*, unification_kind_t, int, conversion**, bool,
bool)
???:0
0xadaefe build_new_op(op_location_t const&, tree_code, int, tree_node*,
tree_node*, tree_node*, tree_node*, tree_node**, int)
???:0
0xd3b412 build_x_binary_op(op_location_t const&, tree_code, tree_node*,
tree_code, tree_node*, tree_code, tree_node*, tree_node**, int)
???:0
0xb25576 tsubst_requires_expr(tree_node*, tree_node*, int, tree_node*)
???:0
0xb2715f evaluate_concept_check(tree_node*)
???:0
0xb18962 maybe_constant_value(tree_node*, tree_node*, bool)
???:0
0xcfdb3f finish_unary_op_expr(unsigned int, tree_code, cp_expr, int)
???:0
0xc872a7 c_parse_file()
???:0
0xdd0579 c_common_parse_file()
???:0
Please submit a full bug report, with preprocessed source (by using
-freport-bug).
Please include the complete backtrace with any bug report.
See  for instructions.