[Bug c++/80039] `constexpr` member function calls in a `constexpr` constructor are ignored if the object is defined locally

2021-03-29 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80039

David Stone  changed:

   What|Removed |Added

 CC||david at doublewise dot net

--- Comment #1 from David Stone  ---
Here's another reproduction

```
struct s {
int m_value = 0;

constexpr int value() const {
return m_value;
}

constexpr s()
{
value();
m_value = 1;
}
};

constexpr auto x = s();
static_assert(x.value() == 1);
```

Still a problem on trunk.

This example shows it's not just that side effects are ignored, but also that
the return value is cached. My guess is that there is some code path that
memoizes calls to constexpr functions, replacing them with their return value,
and that code is getting invoked when it shouldn't be.

[Bug c++/99018] Comparing address of array element not considered a constant expression in certain contexts

2021-03-10 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99018

--- Comment #2 from David Stone  ---
Simpler test case

```
struct s {
constexpr ~s() {
}
};

constexpr bool f(s const (&)[1]) {
return true;
}

static_assert(f({s()}));
```

Message

```
:10:16: error: non-constant condition for static assertion
   10 | static_assert(f({s()}));
  |   ~^~~
:10:22: error: '(((const s*)(&)) != 0)' is not a constant
expression
   10 | static_assert(f({s()}));
  |  ^
Compiler returned: 1
```

See it live: https://godbolt.org/z/YGYjfh

You can get the same error by making the function parameter
`std::initializer_list` as well. Especially interesting in this reduction is
that the code complains about a comparison, but there is no comparison anywhere
in the code.

[Bug c++/99018] Comparing address of array element not considered a constant expression in certain contexts

2021-02-09 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99018

David Stone  changed:

   What|Removed |Added

 CC||david at doublewise dot net

--- Comment #1 from David Stone  ---
Here's a simpler test case

```
struct s {
constexpr ~s() {
if (this) {
}
}
};

constexpr bool f(s (&&)[1]) {
return true;
}

static_assert(f(
{s()}
));
```

Message:

```
:12:16: error: non-constant condition for static assertion
   12 | static_assert(f(
  |   ~^
   13 | {s()}
  | ~   
   14 | ));
  | ~   
:14:1: error: '(((s*)(&)) != 0)' is not a constant
expression
   14 | ));
  | ^
Compiler returned: 1
```

[Bug c++/99031] New: Comparing pointers to heap-allocated memory is not a constant expression

2021-02-09 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99031

Bug ID: 99031
   Summary: Comparing pointers to heap-allocated memory is not a
constant expression
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: david at doublewise dot net
  Target Milestone: ---

The following valid translation unit

```
constexpr bool f() {
auto a = new int;
auto b = new int;
if (a == b) {
}
delete b;
delete a;
return true;
}

static_assert(f());
```

is rejected with

```
:11:16: error: non-constant condition for static assertion
   11 | static_assert(f());
  |   ~^~
:11:16:   in 'constexpr' expansion of 'f()'
:4:15: error: '(((int*)(& heap )) == ((int*)(& heap )))' is not a
constant expression
4 | if (a == b) {
  | ~~^~~~
Compiler returned: 1
```

See it live: https://godbolt.org/z/of45no

[Bug c++/96333] [10/11 Regression] Regression on concepts constraint checking

2021-02-08 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96333

David Stone  changed:

   What|Removed |Added

 CC||david at doublewise dot net

--- Comment #5 from David Stone  ---
*** Bug 98987 has been marked as a duplicate of this bug. ***

[Bug c++/98987] Concept subsumption doesn't work with by-value vs. by-reference parameters

2021-02-08 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98987

David Stone  changed:

   What|Removed |Added

 CC||david at doublewise dot net
 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |DUPLICATE

--- Comment #2 from David Stone  ---
I agree, this is a duplicate of that other issue.

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

[Bug c++/99018] New: Comparing address of array element not considered a constant expression in certain contexts

2021-02-08 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99018

Bug ID: 99018
   Summary: Comparing address of array element not considered a
constant expression in certain contexts
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: david at doublewise dot net
  Target Milestone: ---

The following valid translation unit

```
struct s {
constexpr s() = default;

constexpr s(s const & other) {
if (this == ) {
}
}
};

constexpr auto f() {
s init[2];
for (auto & element : init) {
s foo = element;
}
return true;
}

static_assert(f());
```

is rejected by gcc with

```
:18:16: error: non-constant condition for static assertion
   18 | static_assert(f());
  |   ~^~
:18:16:   in 'constexpr' expansion of 'f()'
:13:11:   in 'constexpr' expansion of 's((*(const s*)(& element)))'
:5:26: error: '(((const s*)(& foo)) == (((const s*)(& init)) + 1))' is
not a constant expression
5 | if (this == ) {
  | ~^
Compiler returned: 1
```

See it live: https://godbolt.org/z/xG5dv5

[Bug c++/99016] New: Internal compiler error from decltype of binary operator when one operand is a prvalue function call

2021-02-08 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99016

Bug ID: 99016
   Summary: Internal compiler error from decltype of binary
operator when one operand is a prvalue function call
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: david at doublewise dot net
  Target Milestone: ---

The following valid translation unit

```
struct integer {};

integer f();

int operator+(integer, integer);

using max_type = decltype(f() + f());
```

Causes gcc to crash with

```
:7:35: internal compiler error: in build_over_call, at cp/call.c:9244
7 | using max_type = decltype(f() + f());
  |   ^
0x1ce6f09 internal_error(char const*, ...)
???:0
0x6b6f43 fancy_abort(char const*, int, char const*)
???:0
0x6df89c build_new_method_call(tree_node*, tree_node*, vec**, tree_node*, int, tree_node**, int)
???:0
0x6e1000 build_special_member_call(tree_node*, tree_node*, vec**, tree_node*, int, int)
???:0
0x6e2760 build_new_op(op_location_t const&, tree_code, int, tree_node*,
tree_node*, tree_node*, tree_node**, int)
???:0
0x9c121d build_x_binary_op(op_location_t const&, tree_code, tree_node*,
tree_code, tree_node*, tree_code, tree_node**, int)
???:0
0x8de23d c_parse_file()
???:0
0xa5b7c2 c_common_parse_file()
???:0
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See  for instructions.
Compiler returned: 1
```

This worked in gcc 10.2. See it live: https://godbolt.org/z/oxj437

[Bug c++/98995] New: Copy elision not applied to members declared with [[no_unique_address]]

2021-02-07 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98995

Bug ID: 98995
   Summary: Copy elision not applied to members declared with
[[no_unique_address]]
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: david at doublewise dot net
  Target Milestone: ---

The following valid translation unit is rejected by gcc 11:

```
struct non_movable {
non_movable() = default;
non_movable(non_movable &&) = delete;
};

struct wrapper {
constexpr explicit wrapper(auto function):
m(function())
{
}

[[no_unique_address]] non_movable m;
};

constexpr auto w = wrapper{[]{ return non_movable(); }};
```

with the error message

```
: In instantiation of 'constexpr wrapper::wrapper(auto:1) [with auto:1
= ]':
:15:55:   required from here
:8:17: error: use of deleted function
'non_movable::non_movable(non_movable&&)'
8 | m(function())
  | ^
:3:9: note: declared here
3 | non_movable(non_movable &&) = delete;
  | ^~~
Compiler returned: 1
```

See it live: https://godbolt.org/z/o1TbY9

This was accepted in gcc 10.2.

[Bug c++/98994] New: Empty type with [[no_unique_address]] in union with constructor is not a constant expression

2021-02-07 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98994

Bug ID: 98994
   Summary: Empty type with [[no_unique_address]] in union with
constructor is not a constant expression
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: david at doublewise dot net
  Target Milestone: ---

The following valid translation unit:

```
struct empty {};

union U {
constexpr U():
a()
{
}

[[no_unique_address]] empty a;
};

constexpr U u;
```

is incorrectly rejected by gcc 11 with the error:

```
:12:13: error: 'U()' is not a constant expression
   12 | constexpr U u;
  | ^
:12:13: error: 'U()' is not a constant expression because it refers to
an incompletely initialized variable
Compiler returned: 1
```

See it live: https://godbolt.org/z/PWcco3

This code was accepted in gcc 10.2.

[Bug c++/98990] Internal compiler error when two overloaded functions return `auto &&` and one accepts an `auto` parameter

2021-02-07 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98990

David Stone  changed:

   What|Removed |Added

 CC||david at doublewise dot net

--- Comment #1 from David Stone  ---
To trigger this bug, the return type can be declared `auto &&`, `auto const &`,
or `auto &`. If it is `auto` or `decltype(auto)`, the bug is not triggered.
Whichever form is used, the same form must be used for both declarations.

[Bug c++/98990] New: Internal compiler error when two overloaded functions return `auto &&` and one accepts an `auto` parameter

2021-02-07 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98990

Bug ID: 98990
   Summary: Internal compiler error when two overloaded functions
return `auto &&` and one accepts an `auto` parameter
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: david at doublewise dot net
  Target Milestone: ---

The following valid translation unit

```
constexpr int x = 0;

constexpr auto && f() {
return x;
}
constexpr auto && f(auto) {
return x;
}
```

causes gcc to crash with

```
:6:25: internal compiler error: same canonical type node for different
types 'auto&&' and 'auto&&'
6 | constexpr auto && f(auto) {
  | ^
0x1ce6f09 internal_error(char const*, ...)
???:0
0x9c60ce comptypes(tree_node*, tree_node*, int)
???:0
0x78ef77 decls_match(tree_node*, tree_node*, bool)
???:0
0x7c003c cplus_decl_attributes(tree_node**, tree_node*, int)
???:0
0x79f277 grokdeclarator(cp_declarator const*, cp_decl_specifier_seq*,
decl_context, int, tree_node**)
???:0
0x7a3916 start_function(cp_decl_specifier_seq*, cp_declarator const*,
tree_node*)
???:0
0x8de23d c_parse_file()
???:0
0xa5b7c2 c_common_parse_file()
???:0
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See  for instructions.
Compiler returned: 1
```

See it live: https://godbolt.org/z/bnszYo

This code was accepted in gcc 10.2, but it is rejected by the upcoming 11.0.

[Bug c++/98988] New: delete is not a constant expression with -fsanitize=undefined

2021-02-07 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98988

Bug ID: 98988
   Summary: delete is not a constant expression with
-fsanitize=undefined
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: david at doublewise dot net
  Target Milestone: ---

The following valid translation unit:

```
constexpr bool f() {
auto ptr = new int();
delete ptr;
return true;
}

static_assert(f());
```

is incorrectly rejected when compiled with `-fsanitize=undefined`, complaining
about

```
:7:16: error: non-constant condition for static assertion
7 | static_assert(f());
  |   ~^~
:7:16:   in 'constexpr' expansion of 'f()'
:3:9: error: '(((int*)(& heap )) != 0)' is not a constant expression
3 | delete ptr;
  | ^~
Compiler returned: 1
```

See it live: https://godbolt.org/z/Yf67G7

[Bug c++/79751] Concept placeholder on another concept does not work

2021-02-07 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79751

David Stone  changed:

   What|Removed |Added

 CC||david at doublewise dot net

--- Comment #2 from David Stone  ---
Resolved in gcc 10.1. It now correctly rejects this code.

[Bug c++/98987] New: Concept subsumption doesn't work with by-value vs. by-reference parameters

2021-02-07 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98987

Bug ID: 98987
   Summary: Concept subsumption doesn't work with by-value vs.
by-reference parameters
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: david at doublewise dot net
  Target Milestone: ---

The following translation unit

```
template
concept A = true;

template
concept B = A and true;

constexpr bool f(A auto) {
return false;
}

constexpr bool f(B auto const &) {
return true;
}

static_assert(f(0));
```

should compile successfully. Instead, gcc reports

```
:15:18: error: call of overloaded 'f(int)' is ambiguous
   15 | static_assert(f(0));
  |  ^
:7:16: note: candidate: 'constexpr bool f(auto:1) [with auto:1 = int]'
7 | constexpr bool f(A auto) {
  |^
:11:16: note: candidate: 'constexpr bool f(const auto:2&) [with auto:2
= int]'
   11 | constexpr bool f(B auto const &) {
  |^
Compiler returned: 1
```

Changing the first `f` overload to accept `A auto const &` or changing the
second to accept `B auto` resolves the ambiguity error.

See it live: https://godbolt.org/z/9aYo64

[Bug tree-optimization/80738] dead first stmt in a=0;a=b;b=0 whatever the aliasing

2020-12-14 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80738

David Stone  changed:

   What|Removed |Added

 CC||david at doublewise dot net

--- Comment #6 from David Stone  ---
All of the standard library types in C++ have a hand-written version of
std::swap to work around the problem. Fundamental types do not need anything
set to 0 in the middle so they don't show the problem. The simplest case to
show this would probably be a struct containing a unique_ptr (although it
applies to any resource-owning type that doesn't have a swap written
specifically for it):

```
#include 
#include 

struct wrapper {
std::unique_ptr ptr;
};

void slow(wrapper & lhs, wrapper & rhs) {
std::swap(lhs, rhs);
}

void fast(wrapper & lhs, wrapper & rhs) {
std::swap(lhs.ptr, rhs.ptr);
}
```

At `-O3`, this generates the assembly

```
slow(wrapper&, wrapper&):
mov rax, QWORD PTR [rdi]
mov QWORD PTR [rdi], 0
mov rdx, QWORD PTR [rsi]
mov QWORD PTR [rsi], 0
mov QWORD PTR [rdi], rdx
mov rdi, QWORD PTR [rsi]
mov QWORD PTR [rsi], rax
testrdi, rdi
je  .L1
mov esi, 4
jmp operator delete(void*, unsigned long)
.L1:
ret
fast(wrapper&, wrapper&):
mov rax, QWORD PTR [rdi]
mov rdx, QWORD PTR [rsi]
mov QWORD PTR [rdi], rdx
mov QWORD PTR [rsi], rax
ret
```

Where `fast` is better only because the C++ standard library maintainers
hand-wrote a faster version.

[Bug c++/97388] constexpr evaluator incorrectly claims double delete with function parameter

2020-10-12 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97388

--- Comment #2 from David Stone  ---
That is what seems to be happening here. It looks like by-value function
parameters have all modifications rolled back before the object is destroyed.
The following code is also erroneously rejected:

```
struct S {
int m;

constexpr S():
m(1)
{
}
constexpr ~S() noexcept(false) {
if (m == 1) {
throw;
}
}
};

constexpr bool test(S v) {
v.m = 2;
return true;
}

static_assert(test(S()));
```

See it live: https://godbolt.org/z/qMjEfo

[Bug c++/97388] constexpr evaluator incorrectly claims double delete with function parameter

2020-10-12 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97388

David Stone  changed:

   What|Removed |Added

 CC||david at doublewise dot net

--- Comment #1 from David Stone  ---
This seems like it could be the same issue. The following code should be
rejected, but it's accepted.

```
#include 

struct S {
int * m_ptr;

constexpr S():
m_ptr(new int)
{
}
S(const S&) = delete;
S& operator=(const S&) = delete;
constexpr ~S() {
delete m_ptr;
}
};

constexpr bool test(S v) {
v.m_ptr = nullptr;
return true;
}

static_assert(test(S()));
```

Here, we have a memory leak that fails to be reported. It seems like changes to
by-value function parameters are not maintained for the destructor?

[Bug c++/97388] New: constexpr evaluator incorrectly claims double delete with function parameter

2020-10-12 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97388

Bug ID: 97388
   Summary: constexpr evaluator incorrectly claims double delete
with function parameter
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: david at doublewise dot net
  Target Milestone: ---

The following translation unit

```
struct S {
int * m_ptr;

constexpr S():
m_ptr(new int())
{
}
constexpr S(S && other) noexcept:
m_ptr(other.m_ptr)
{
other.m_ptr = nullptr;
}
constexpr ~S() noexcept {
delete m_ptr;
}
};

constexpr bool test(S v) {
auto x = static_cast(v);
return true;
}

static_assert(test(S()));
```

is rejected with 

```
:23:19: error: non-constant condition for static assertion

   23 | static_assert(test(S()));

  |   ^

Compiler returned: 1
```

This problem does not occur if `v` is turned into a local variable instead of a
function parameter.

The error message is also not helpful in this case. It gives a much more
helpful (but still erroneous) error message if `std::allocator` is used instead
of `new` and `delete`:

```
:28:19: error: non-constant condition for static assertion

   28 | static_assert(test(S()));

  |   ^

In file included from
/opt/compiler-explorer/gcc-trunk-20201012/include/c++/11.0.0/memory:64,

 from :1:

:28:25:   in 'constexpr' expansion of '(&)->S::~S()'

:17:36:   in 'constexpr' expansion of
'std::allocator().std::allocator::deallocate(((S*)this)->S::m_ptr,
1)'

/opt/compiler-explorer/gcc-trunk-20201012/include/c++/11.0.0/bits/allocator.h:183:30:
error: deallocation of already deallocated storage

  183 | ::operator delete(__p);

  | ~^

Compiler returned: 1
```

See it live: https://godbolt.org/z/hcv88h

[Bug c++/97052] Internal compiler error with substitution failure in template parameter list of concept declaration

2020-10-01 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97052

David Stone  changed:

   What|Removed |Added

 CC||david at doublewise dot net

--- Comment #2 from David Stone  ---
Turns out the substitution failure is a red herring. Here is a simpler
reproduction:

```
template
concept foo = true;

void f(foo auto) {
}
```

[Bug c++/97195] construct_at on a union member is not a constant expression

2020-09-27 Thread david at doublewise dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97195

David Stone  changed:

   What|Removed |Added

 CC||david at doublewise dot net

--- Comment #1 from David Stone  ---
This is actually a broader bug in construct_at, unrelated to unions:


```
#include 

constexpr bool test() {
int a = 5;
std::construct_at(
,
-1
);
return true;
}
constexpr bool b = test();
```

is also rejected. See it live: https://godbolt.org/z/KWK8n1

The real problem here appears to be that std::construct_at is not a constant
expression for values with non-constant addresses. The following code, for
example, is accepted:

```
#include 

struct S {
constexpr S() {
std::construct_at(
,
-1
);
}

int m;
};

constexpr S s;
```

See it live: https://godbolt.org/z/Wdx9Kx