[Bug c++/86577] non-ADL name lookup for operator<< at instantiation time?

2020-06-08 Thread leni536 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86577

Lénárd Szolnoki  changed:

   What|Removed |Added

 CC||leni536 at gmail dot com

--- Comment #1 from Lénárd Szolnoki  ---
Other operators seem to be affected as well. This lookup error can be escalated
from accepts-invalid to wrong-code:

#include 

void calls_templated();
void calls_nontemplated();

namespace a {
struct A {};
}

namespace {
template
std::enable_if_t, bool>
operator==(const T&, const T &) {
calls_templated();
return true;
}

template
bool test(const T&t1, const T &t2) {
return t1==t2;
}

bool operator==(const a::A&, const a::A&) {
calls_nontemplated();
return true;
}
}

int main() {
const a::A a;
test(a, a);
}

gcc 10.1 compiles the code above and calls 'calls_nontemplated()'.

[Bug c++/86577] non-ADL name lookup for operator<< at instantiation time?

2020-06-08 Thread leni536 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86577

--- Comment #3 from Lénárd Szolnoki  ---
(In reply to Jonathan Wakely from comment #2)
> Is this a dup of PR 51577 ?

Yes, seems like it is.

[Bug c++/95686] New: undefined reference to static local variable within inline function

2020-06-15 Thread leni536 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95686

Bug ID: 95686
   Summary: undefined reference to static local variable within
inline function
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

The following code produces an "undefined reference to `foo()::i'" linker
error:

template 
struct S {
static constexpr const int* value = ptr;
};

inline
auto foo() {
static const int i = 0;
return S<&i>{};
}

#include 

int main() {
std::cout << decltype(foo())::value;
}

[Bug c++/95686] undefined reference to static local variable within inline function

2020-06-16 Thread leni536 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95686

--- Comment #2 from Lénárd Szolnoki  ---
I failed to mention that I compiled the example in -std=c++17. With this
compiler option it compiles but fails to link in gcc. It compiles, links and
runs as expected in clang.

The linkage requirement for reference/pointer non-type template arguments were
lifted in C++17.

[Bug c++/95701] New: undefined enum conversion accepted in constant expression

2020-06-16 Thread leni536 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95701

Bug ID: 95701
   Summary: undefined enum conversion accepted in constant
expression
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

gcc accepts the following code:

enum E {
one = 1
};

constexpr E foo() {
return static_cast(0x);
}

void bar() {
constexpr auto e = foo();
}

Relevant parts of the standard:

https://timsong-cpp.github.io/cppwp/n4659/expr.const#2.6

https://timsong-cpp.github.io/cppwp/n4659/expr.static.cast#10
> The value is unchanged if the original value is within the range of the 
> enumeration values ([dcl.enum]). Otherwise, the behavior is undefined.

https://timsong-cpp.github.io/cppwp/n4659/dcl.enum#8
Following the wording here the "range of the enumeration values" is [0, 1].

[Bug c++/93711] ICE: [[no_unique_address] when constructing via template helper

2020-06-17 Thread leni536 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93711

Lénárd Szolnoki  changed:

   What|Removed |Added

 CC||leni536 at gmail dot com

--- Comment #3 from Lénárd Szolnoki  ---
A smaller example:

struct S {
S(S&&) = delete;
};

S foo();

struct A {
[[no_unique_address]] S s = foo();
};

A a{};

Version:
11.0.0 20200616

Command line options:
-std=c++20 -Wall -Wextra -pedantic

Diagnostics:
during RTL pass: expand
: In function 'void __static_initialization_and_destruction_0(int,
int)':
:11:5: internal compiler error: in assign_temp, at function.c:984
   11 | A a{};
  | ^

[Bug c++/89757] New: accepts returning with reference to temporary in constant expression

2019-03-18 Thread leni536 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89757

Bug ID: 89757
   Summary: accepts returning with reference to temporary in
constant expression
   Product: gcc
   Version: 8.3.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

g++ accepts this ill-formed code:

constexpr const int& foo(int x, int y) {
const int& z = x+y;
return z;
}

constexpr int&& bar(int x, int y) {
int&& z = x+y;
return static_cast(z);
}

int main() {
constexpr int a = foo(1,2);
constexpr int b = bar(1,2);
return a+b;
}

This is invalid because both foo and bar return with a reference to a local
temporary object and expressions containing UB when evaluated are not constant
expressions.

$ g++ -std=c++14 -Wall -Wextra -pedantic -o gcc_bug gcc_bug.cpp && ./gcc_bug;
echo $?
6

Note: I tested it on 8.3.0 on my own machine, but it seems to be the same for
all versions on godbolt.

[Bug c++/89761] New: [9.0 Regression] ICE: tree check: expected class 'expression', have 'exceptional' (argument_pack_select)

2019-03-18 Thread leni536 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89761

Bug ID: 89761
   Summary: [9.0 Regression] ICE: tree check: expected class
'expression', have 'exceptional'
(argument_pack_select)
   Product: gcc
   Version: 9.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
      Reporter: leni536 at gmail dot com
  Target Milestone: ---

The following code triggers an ICE in g++ 9.0.1:

template  struct seq {};
template  struct S {
template 
constexpr static void call(Args&&...) {}
};

template 
auto foo (seq, Args&& ...args) {
return (S::call(args), ...);
}

void bar() {
foo(seq<0,1,2>{}, 1,2,3);
}

I'm not sure about the validity of the code above.

Tested on godbolt.org with "-std=c++17" flag:

: In instantiation of 'auto foo(seq, Args&& ...) [with int
...Idx = {0, 1, 2}; Args = {int, int, int}]':
:13:28:   required from here
:9:20: internal compiler error: tree check: expected class
'expression', have 'exceptional' (argument_pack_select) in tree_operand_check,
at tree.h:3674
9 | return (S::call(args), ...);
  |^~~
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://gcc.gnu.org/bugs/> for instructions.

Version:
g++ (Compiler-Explorer-Build) 9.0.1 20190316 (experimental)

[Bug c++/89857] New: list-initialization of unnamed, non-const reference type

2019-03-27 Thread leni536 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89857

Bug ID: 89857
   Summary: list-initialization of unnamed, non-const reference
type
   Product: gcc
   Version: 8.3.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

gcc doesn't compile the following well-formed program:

void foo () {
using T = int&;
int i{};
T{i};
}

$ g++ -std=c++17 -c gcc_bug2.cpp 
gcc_bug2.cpp: In function ‘void foo()’:
gcc_bug2.cpp:4:8: error: invalid cast of an rvalue expression of type ‘int’ to
type ‘T’ {aka ‘int&’}
 T{i};

Quoting from the standard draft:

http://eel.is/c++draft/dcl.init.list#3.9

Otherwise, if the initializer list has a single element of type E and either T
is not a reference type or its referenced type is reference-related to E, the
object or reference is initialized from that element (by copy-initialization
for copy-list-initialization, or by direct-initialization for
direct-list-initialization); if a narrowing conversion (see below) is required
to convert the element to T, the program is ill-formed.

According to the error, it looks like gcc skips this and tries to apply the
next rule:

Otherwise, if T is a reference type, a prvalue of the type referenced by T is
generated.
The prvalue initializes its result object by copy-list-initialization.
The prvalue is then used to direct-initialize the reference.
[ Note: As usual, the binding will fail and the program is ill-formed if the
reference type is an lvalue reference to a non-const type.
— end note ]

Note: The current behavior was originally a defect in the C++11 standard that
was corrected in CWG1288.
http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1288

[Bug c++/77875] C++ core issue 1288

2019-03-28 Thread leni536 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77875

--- Comment #3 from Lénárd Szolnoki  ---
A more worrisome example presumably for this same bug, it's a miscompilation:

template 
decltype(auto) as_const(T& t) {
using const_ref = const T&;
return const_ref{t};
}

int main() {
int i = 42;
return as_const(i);
}

$ g++ -std=c++17 -O0 -fsanitize=undefined -Wall -pedantic main.cpp && ./a.out
main.cpp: In instantiation of 'decltype(auto) as_const(T&) [with T = int]':
main.cpp:9:22:   required from here
main.cpp:4:23: warning: returning reference to temporary [-Wreturn-local-addr]
 return const_ref{t};
   ^
main.cpp:4:23: runtime error: reference binding to null pointer of type 'const
int'
main.cpp:9:22: runtime error: load of null pointer of type 'const int'
bash: line 7:   802 Segmentation fault  (core dumped) ./a.out

An UB is added where should be none.

[Bug c++/90254] New: ice on aggregate initialization of unmovable base

2019-04-25 Thread leni536 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90254

Bug ID: 90254
   Summary: ice on aggregate initialization of unmovable base
   Product: gcc
   Version: 8.3.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

The compiler bumps into an internal compiler error on the following, valid
code:

//aggregate base class
struct A1 {
A1() = default;

A1(const A1&) = delete;
A1(A1&&) = delete;
};

//non-aggregate base class
struct A2 {
A2() {};
A2(const A2&) = delete;
A2(A2&&) = delete;
};

//aggregate derived classes
struct B1 : A1 {};
struct B2 : A2 {};

A1 f1() {
return A1();
}

A2 f2() {
return A2();
}

int main() {
A1 a1{f1()}; // OK
B1 b1_1{{}}; // OK
B1 b1_2{A1{}}; // OK
B1 b1_3{A1()}; // OK
B1 b1_4{f1()}; // ICE

A2 a2{f2()}; // OK
B2 b2_1{{}}; // OK
B2 b2_2{A2{}}; // OK
B2 b2_3{A2()}; // OK
B2 b2_4{f2()}; // ICE
}

It is valid because each element of the aggregate is copy-initialized from the
corresponding initializer-clause. If it is a prvalue then no temporary is
materialized.

Some argue that this is a defect in the standard and the code above should be
rejected:
https://bugs.llvm.org/show_bug.cgi?id=34516

[Bug c++/100189] New: rejects valid conditional operators involving conversions to arrays of unknown bound (P0388)

2021-04-21 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100189

Bug ID: 100189
   Summary: rejects valid conditional operators involving
conversions to arrays of unknown bound (P0388)
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

Version: g++ (Compiler-Explorer-Build) 12.0.0 20210420 (experimental)
Flags: -std=c++20  -O2 -pedantic-errors

Consider the following snippet:

```
void foo() {
auto ptr = true
? (int (*)[]) nullptr
: (int (*)[42]) nullptr;
}
```

https://godbolt.org/z/nKbzvaY3h

Since the third argument is convertible to the second argument, but not the
other way around, this should be accepted.

https://timsong-cpp.github.io/cppwp/n4861/expr.cond#4.3.3

Also consider the following snippet:

```
template 
using pointer_to = T*;

template 
using array_of_ub = T[];

template 
using array_of = T[N];

void foo() {
using t1 =
pointer_to<
array_of_ub<
pointer_to<
array_of<10,
int
>>>>;
using t2 =
pointer_to<
array_of<10,
pointer_to<
array_of_ub<
int
>>>>;
auto ptr = true
? (t1)nullptr
: (t2)nullptr;
}
```

https://godbolt.org/z/s1rnher9G

This should also be accepted following
https://timsong-cpp.github.io/cppwp/n4861/expr.cond#7.3 and
https://timsong-cpp.github.io/cppwp/n4861/expr.type#3.5 . I am a bit less sure
about this one, but I believe the type of `ptr` in this case should be
`pointer_to>>>` after applying
https://timsong-cpp.github.io/cppwp/n4861/conv.qual#3 and removing a redundant
`const`.

[Bug c++/97643] New: Accepts invalid qualification conversion involving array of unknown bound [P0388]

2020-10-30 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97643

Bug ID: 97643
   Summary: Accepts invalid qualification conversion involving
array of unknown bound [P0388]
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

version: g++ (Compiler-Explorer-Build) 11.0.0 20201029 (experimental)

https://godbolt.org/z/a8sKr3

In C++20 the following code is ill-formed, but gcc accepts it:

void foo(int (*arr)[10]);

void bar(int (*arr)[]) {
int (* ptr)[10];
int (** ptr2)[] = &ptr; // not allowed
*ptr2 = arr;
foo(ptr);
}

The conversion happens from T1 = int (**)[10] to T2 = int (**)[] .

The cv-decomposition of the two types are:
T1 = pointer to | pointer to | array of 10   | int
T2 = pointer to | pointer to | array of unknown bound of | int

The cv-combined type is:
T3 = pointer to | const pointer to | array of unknown bound of | int
= int (*const*)[]

[Bug c++/97645] New: Rejects valid subscript expression on array of unknown bound in constant expression

2020-10-30 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97645

Bug ID: 97645
   Summary: Rejects valid subscript expression on array of unknown
bound in constant expression
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

version: g++ (Compiler-Explorer-Build) 11.0.0 20201029 (experimental)

g++ rejects the following program in -std=c++20:

constexpr
int foo(const int (&arr)[]) {
return arr[1];
}

constexpr
int bar(const int (&arr)[10]) {
return foo(arr);
}

constinit auto x = bar({});

https://godbolt.org/z/Mq1GGf

This was possibly impossible prior to C++20 to subscript an array of unknown
bound in constexpr context. As of P0388 conversion from T[N] to T[] can happen
in constexpr context.

[Bug c++/97647] New: Accepts undefined delete expression in constant expression

2020-10-30 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97647

Bug ID: 97647
   Summary: Accepts undefined delete expression in constant
expression
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

version: g++ (Compiler-Explorer-Build) 11.0.0 20201029 (experimental)
options: -std=c++20 -O2 -pedantic-errors

g++ accepts the following program:

struct Base {};
struct Derived : Base{
int i = 0;
};

constexpr int foo() {
Base* ptr = new Derived{};
delete ptr; //UB
return 0;
}

constexpr int x = foo();

https://godbolt.org/z/MEnbM6

Deleting a Derived object through Base* is undefined behaviour.

[Bug c++/86373] Destructor shall not be instantiated in C++17 mode for prvalue

2020-10-30 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86373

Lénárd Szolnoki  changed:

   What|Removed |Added

 CC||leni536 at gmail dot com

--- Comment #1 from Lénárd Szolnoki  ---
By DR2227 the destructor is potentially invoked here.

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2227

[Bug c++/97648] New: Rejects valid direct initialization from prvalue (private destructor)

2020-10-30 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97648

Bug ID: 97648
   Summary: Rejects valid direct initialization from prvalue
(private destructor)
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

version: g++ (Compiler-Explorer-Build) 11.0.0 20201029 (experimental)
options: -std=c++17 -O2 -pedantic-errors

g++ rejects the following well-formed program:

struct A {
private:
~A();

public:
static A f();
};

A* foo() {
return new A(A::f());
}

https://godbolt.org/z/hffYq7

On the return line no destructor is invoked or potentially invoked.

[Bug c++/97645] Rejects valid subscript expression on array of unknown bound in constant expression

2020-12-05 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97645

--- Comment #2 from Lénárd Szolnoki  ---
(In reply to Lénárd Szolnoki from comment #0)
> This was possibly impossible prior to C++20 to subscript an array of unknown
> bound in constexpr context. As of P0388 conversion from T[N] to T[] can
> happen in constexpr context.

A C++11 example:

```
extern const int arr[];
constexpr const int (&arrref)[] = arr;

constexpr int arr[2] = {1,2};

constexpr int x = arrref[0];
```

error: nonzero array subscript '0' is used with array of type 'const int []'
with unknown bounds

arrref[0] replaced with ((int*)arrref)[0] is accepted.

[Bug c++/98163] New: ICE symtab_node::verify failed, auto& NTTP specialized with same entity but different type.

2020-12-06 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98163

Bug ID: 98163
   Summary: ICE symtab_node::verify failed, auto& NTTP specialized
with same entity but different type.
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

g++ (Compiler-Explorer-Build) 11.0.0 20201205 (experimental)

command line flags: -std=c++17 -pedantic-errors

```
template 
struct S {};

template 
void foo(T) {}

extern const int arr[];

// arr is const int[]
void bar(S s) {
foo(s);
}

const int arr[2] = {1,2};

// arr is const int[2]
void baz(S s) {
foo(s);
}
```

source>:19:1: error: Two symbols with same comdat_group are not linked by the
same_comdat_group list.
   19 | }
  | ^
_Z3fooI1SIL_Z3arrEEEvT_/4 (void foo(T) [with T = S]) @0x7f7216d81330
  Type: function definition analyzed
  Visibility: no_reorder public weak comdat
comdat_group:_Z3fooI1SIL_Z3arrEEEvT_ one_only
  previous sharing asm name: 3
  References: 
  Referring: 
  Function flags: body
  Called by: _Z3baz1SIL_Z3arrEE/2 
  Calls: 
_Z3fooI1SIL_Z3arrEEEvT_/3 (void foo(T) [with T = S]) @0x7f7216d81220
  Type: function definition analyzed
  Visibility: no_reorder public weak comdat
comdat_group:_Z3fooI1SIL_Z3arrEEEvT_ one_only
  next sharing asm name: 4
  References: 
  Referring: 
  Function flags: body
  Called by: _Z3bar1SIL_Z3arrEE/0 
  Calls: 
:19:1: internal compiler error: symtab_node::verify failed
0x1c39f09 internal_error(char const*, ...)
???:0
0xacca22 symtab_node::verify_symtab_nodes()
???:0
0xae8def symbol_table::finalize_compilation_unit()
???:0
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
Compiler returned: 1

godbolt: https://godbolt.org/z/bKc1c1

[Bug c++/98163] ICE symtab_node::verify failed, auto& NTTP specialized with same entity but different type.

2020-12-07 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98163

--- Comment #4 from Lénárd Szolnoki  ---
Other example in the same spirit, but not using array of unknown bound:

```
template 
struct S {};

template 
void foo(T) {}

int i;
constexpr const int& iref = i;

template void foo(S);
template void foo(S);
```

[Bug c++/98326] New: ICE: in create_tmp_var, at gimple-expr.c:482, converting stateless generic-lambda to function pointer

2020-12-16 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98326

Bug ID: 98326
   Summary: ICE: in create_tmp_var, at gimple-expr.c:482,
converting stateless generic-lambda to function
pointer
   Product: gcc
   Version: 10.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

version: g++ (Compiler-Explorer-Build) 10.2.0
arguments: -O2 -std=c++17 -pedantic-errors

```
struct A {
A() = default;
A(const A&) {}
};

void (*fptr)(A) = [](auto){};
```

: In static member function 'static constexpr decltype
(((const*)0)->operator()(static_cast()))::_FUN(auto:1)
[with auto:1 = A]':
:6:28: internal compiler error: in create_tmp_var, at gimple-expr.c:482
6 | void (*fptr)(A) = [](auto){};
  |^


The ICE seems to happen when the by-value parameter's type is not trivially
copyable. It can also be reproduced with a non-trivial destructor.

If the copy-constructor is deleted then it fails to compile with a non-ice
error.

Related: PR 86943

In my understanding gcc tries to copy/move the by-value parameter in the free
function to pass it to `closure{}(args)`. I don't think that copying/moving the
by-value argument is correct. The effect of calling the resulting function
pointer should be equivalent to calling the operator() on the closure object,
it's not expressed in terms of forwarding the parameters:

https://timsong-cpp.github.io/cppwp/n4659/expr.prim.lambda.closure#8

It's more precisely spelled out in C++20, as there it can be expressed it in
terms of a default constructed object of the closure type:

http://eel.is/c++draft/expr.prim.lambda.closure#10.sentence-1

[Bug c++/98419] New: wrong code when destructor of local variable modifies returned object

2020-12-22 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98419

Bug ID: 98419
   Summary: wrong code when destructor of local variable modifies
returned object
   Product: gcc
   Version: 10.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

Version:
g++ (Compiler-Explorer-Build) 10.2.0

Command line options:
-std=c++17 -O2 -pedantic-errors


```
struct A {
int i;
A(int ** iptrptr): i(1) {
*iptrptr = &i;
}
};

struct B {
int* iptr;
B(): iptr(0) {}
~B() {
*iptr = 2;
}
};

A foo() {
B b;
return A(&b.iptr);
}
```

Observed behavior:
foo() returns an object with its `i` member having the value 1.

https://godbolt.org/z/Yhcjo9

Expected behavior:
foo() to return an object with its `i` member having the value 2.

The destruction of `b` is sequenced before the initialization of the returned
object. The constructor of A sets the int* contained in `b` to point within the
returned object (there is no temporary created with type A, C++17's mandatory
copy elision is assumed here). ~B() then sets the `i` member of the returned
object to 2.

Other observations:
With command line options `-std=c++17 -O0 -pedantic-errors -fsanitize=address`
~B() tramples the stack:

https://godbolt.org/z/M5ETa9

When A has a user-defined copy-constructor or destructor then I get the
expected behavior:

https://godbolt.org/z/osqbfz
https://godbolt.org/z/ozzPaf

Presumably when the returned type is trivially copyable then the copy isn't
elided, with the assumption that it's not observable. In C++17 the copy elision
is mandatory, and it is observable even for trivially copyable types, as shown
in this example.

[Bug c++/98419] wrong code when destructor of local variable modifies returned object

2020-12-22 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98419

--- Comment #2 from Lénárd Szolnoki  ---
This is probably invalid, I wasn't aware of
http://eel.is/c++draft/class.temporary#3

> When an object of class type X is passed to or returned from a function, if X 
> has at least one eligible copy or move constructor ([special]), each such 
> constructor is trivial, and the destructor of X is either trivial or deleted, 
> implementations are permitted to create a temporary object to hold the 
> function parameter or result object.

[Bug c++/103333] [accepts-invalid] function template argument deduction for incompatible 'transformed A' / 'deduced A' pair

2021-11-22 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=10

--- Comment #1 from Lénárd Szolnoki  ---
This can be turned into wrong-code.

C++11 example without includes:

```
template 
struct enable_if {};

template 
struct enable_if {
using type = T;
};

template 
using enable_if_t = typename enable_if::type;

template 
struct type_identity {
using type = T;
};

template 
using type_identity_t = typename type_identity::type;

template 
struct is_const {
static constexpr bool value = false;
};

template 
struct is_const {
static constexpr bool value = true;
};

template
struct S{
template::value>>
operator S() { return {}; }

operator int() { return 0; }
};

inline int f(int, int) {
return 1;
}

template
int f(S, b1>,
   S) {
return 2;
}

int main() {
S s1{};
S s2{};
return f(s1, s2); // returns 2, should return 1
}
```

https://godbolt.org/z/h8b75P7GK

[Bug c/103343] Invalid codegen when comparing pointer to one past the end and then dereferencing that pointer

2021-11-22 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103343

--- Comment #4 from Lénárd Szolnoki  ---
A complete program example:

f.h:
```
#pragma once
extern int x[1];
extern int y;

int f(int* p, int* q);
```

f.cpp:
```
#include "f.h"

int f(int* p, int* q) {
*q = y;
if (p == (x + 1)) {
*p = 2;
return y;
}
return 0;
}
```

x_y.cpp:
```
#include "f.h"

int y;
int x[1];
```

main.cpp:
```
#include "f.h"

int main() {
y=1;
int i;
return f(&y, &i);
}
```

Compile with `g++ -o main main.cpp f.cpp x_y.cpp`.
https://godbolt.org/z/G4KTKc7hE

The well-formed program above has two possible evaluations, due to the
unspecified comparison. In one evaluation `main` returns 0, in the other it
returns 2. Compiled with g++ the program returns 1.

Within the single invocation of `f` `p` is pointer to an object, namely `y`.
Even after the unspecified comparison evaluates to true, `p` remains a pointer
to `y`. Therefore dereferencing `p` is still valid in that branch.

I don't think that it is a duplicate of bug 61502. The program does not rely on
the object representation of the pointer objects, their printed value or their
value converted to uintptr_t. The only thing that is questionable is the
comparison with pointer past the end of an object, which is merely unspecified.

[Bug c++/101486] New: Rejects valid qualification conversion involving array of unknown bound in function template argument [P0388]

2021-07-17 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101486

Bug ID: 101486
   Summary: Rejects valid qualification conversion involving array
of unknown bound in function template argument [P0388]
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

Version:

g++
(Compiler-Explorer-Build-gcc-48e8a7a677b8356df946cd12fbb215538828e747-binutils-2.36.1)
12.0.0 20210707 (experimental)

Flags: -std=c++20 -pedantic-errors

Observed behavior:

Rejects the following code:

```
template 
void f1(const T(*)[10]);

template 
void f2(T(*)[]);

void bar(int (*ptr)[10]) {
f1(ptr); // accepts
f2(ptr); // rejects
}
```

Expected behavior:

Accept both function calls. Qualification conversions are allowed when deducing
template arguments in a pointer function parameter
(https://timsong-cpp.github.io/cppwp/n4868/temp.deduct#call-4.2). As of C++20
(P0388) converting `int (*)[10]` to `int (*)[]` is a valid qualification
conversion.

Exhibits:

https://godbolt.org/z/rcbMhEf45

[Bug c++/111286] New: ICE on functional cast to const array reference

2023-09-04 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111286

Bug ID: 111286
   Summary: ICE on functional cast to const array reference
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

With g++ 13.2.0
with flags: -std=c++20

The following code:

```
struct A {
A() noexcept {}
};

void foo() {
using T = const A (&)[1];
T{};
}
```

Produces the following compiler output:

: In function 'void foo()':
:7:7: internal compiler error: in cp_build_addr_expr_1, at
cp/typeck.cc:7147
7 | T{};
  |   ^
0x1ce7bde internal_error(char const*, ...)
???:0
0x7290fc fancy_abort(char const*, int, char const*)
???:0
0x74b040 perform_implicit_conversion_flags(tree_node*, tree_node*, int, int)
???:0
0x8e9510 finish_compound_literal(tree_node*, tree_node*, int, fcl_t)
???:0
0x89fd5b c_parse_file()
???:0
0x98c5d9 c_common_parse_file()
???:0


https://godbolt.org/z/MaWTTv4Y7

[Bug c++/111440] New: wrong-code for ternary with reference-compatible arguments

2023-09-17 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111440

Bug ID: 111440
   Summary: wrong-code for ternary with reference-compatible
arguments
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

version: g++ 13.2.0
flags: -std=c++20 -O2 -pedantic-errors

Consider the following code:

```
template 
void foo();,

bool bar() {
int * ptr = nullptr;
const int * const cptr = nullptr;
decltype(auto) res = true ? ptr : cptr;
foo(); // calls void();
return &res == &ptr; // returns false
}
```

https://godbolt.org/z/cW5bxch5K

The observed behavior is described in the code comments.

The expected behavior is that the ternary expression is an lvalue of type
`const int * const` and the result refers to `ptr`.

https://timsong-cpp.github.io/cppwp/n4868/expr.cond#4.1 applies. The target
type is `const int * const&`, E1 is an lvalue of type `int *`.

`int *` is reference-compatible with `const int * const`, as `int**` is
convertible to `const int * const *`.

https://timsong-cpp.github.io/cppwp/n4868/dcl.init.ref#5.1.1 applies, a
reference of type `const int * const&` can be initialized by an lvalue of type
`int*`, and the reference binds directly.

The wording for "reference-compatible" was changed in the resolution of
https://cplusplus.github.io/CWG/issues/2352.html, so earlier standard modes are
probably similarly affected.

[Bug c++/111440] wrong-code for ternary with reference-compatible arguments due to C++ defect report 2352

2023-09-17 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111440

--- Comment #3 from Lénárd Szolnoki  ---
Note that GCC seems to implement CWG2352 outside of ternary operators.

https://godbolt.org/z/rnMcPqE7b

```
template 
void foo();

bool bar() {
int * ptr = nullptr;
const int * const &ref = ptr;
return &ref == &ptr; // returns true
}
```

from GCC 10 `bar` returns true.

[Bug c/102989] Implement C2x's n2763 (_BitInt)

2023-04-09 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102989

Lénárd Szolnoki  changed:

   What|Removed |Added

 CC||leni536 at gmail dot com

--- Comment #33 from Lénárd Szolnoki  ---
(In reply to jos...@codesourcery.com from comment #32)
> On Fri, 28 Oct 2022, jakub at gcc dot gnu.org via Gcc-bugs wrote:
> 
> > > That said, if C allows us to limit to 128bits then let's do that for now.
> > > 32bit targets will still see all the complication when we give that a 
> > > stab.
> > 
> > I'm afraid once we define BITINT_MAXWIDTH, it will become part of the ABI, 
> > so
> > we can't increase it afterwards.
> 
> I don't think it's part of the ABI; I think it's always OK to increase 
> BITINT_MAXWIDTH, as long as the wider types don't need more alignment than 
> the previous choice of max_align_t.

It's not part of the ABI until people put _BitInt(BITINT_MAXWIDTH) on ABI
boundaries of their libraries. If a ridiculously large BITINT_MAXWIDTH does
nothing more than discourages usages of _BitInt(BITINT_MAXWIDTH) in general,
than that's already great. We don't need an other intmax.

Also I don't want to think about the max N for _BitInt(N), similarly how I
don't want to think about the max N for int[N]. There might be implementation
limits, but it should be high enough so I don't have to think about those for
everyday coding.

> Thus, starting with a 128-bit limit (or indeed a 64-bit limit on 32-bit 
> platforms, so that all the types fix within existing modes supported for 
> arithmetic), and adding support for wider _BitInt later, would be a 
> reasonable thing to do.

I disagree.

> (You still have ABI considerations even with such a limit: apart from the 
> padding question, on x86_64 the ABI says _BitInt(128) is 64-bit aligned 
> but __int128 is 128-bit aligned.)
> 
> > Anyway, I'm afraid we probably don't have enough time to implement this
> > properly in stage1, so might need to target GCC 14 with it.  Unless somebody
> > spends on it
> > the remaining 2 weeks full time.
> 
> I think https://gcc.gnu.org/pipermail/gcc/2022-October/239704.html is 
> still current as a list of C2x language features likely not to make it 
> into GCC 13.  (I hope to get auto and constexpr done in the next two 
> weeks, and the other C2x language features not on that list are done.)

gcc-bugs@gcc.gnu.org

2024-04-28 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114877

Bug ID: 114877
   Summary: wrong-code for frexp(NAN, &uninitialized)
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

arch: x86_64
command line arguments: -std=c17 -O2 -pedantic-errors

#include 
#include 

int frexp_test(bool b) {
if (b) {
int x;
(void)frexp(NAN, &x);
int y = x;
return y - x;
}
return 42;
}

https://godbolt.org/z/a1cn4cPqr

Observed behavior:

gcc optimizes the above function to always return 42 regardless of the value of
`b`. `frexp_test(true)` has defined behavior and must return 0.

Expected behavior:

The C standard seems to be unambiguous that an unspecified value is written to
`x` when `frexp` is called. Therefore `frexp_test(true)` has defined behavior
and must return 0.


GCC's semantics of `frexp(NAN, &x)` seems to be that it doesn't write to `x` at
all. This is a valid optimization of `x` is not uninitialized, this would be
equivalent to `*x = *x`, so the unspecified value produce by `frexp` can be the
same value that was already there. However this isn't valid when `x` was not
initialized in the first place and subsequent optimizations treat `x` as still
uninitialized.

gcc-bugs@gcc.gnu.org

2024-04-30 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114877

--- Comment #3 from Lénárd Szolnoki  ---
(In reply to Richard Biener from comment #2)
> The standard says the results are unspecified, it doesn't say *p is written
> to,
> so I'm not sure there's a bug here.

C17 (N2176) says in the library section:

"The frexp functions break a floating-point number into a normalized fraction
and an integral power of 2. They store the integer in the int object pointed to
by exp."

"If value is not a floating-point number or if the integral power of 2 is
outside the range of int, the results are unspecified. Otherwise, the frexp
functions return the value x, such that x has a magnitude in the interval [1/2,
1) or zero, and value equals x × 2*exp . If value is zero, both parts of
the result are zero."

This might be a little bit ambiguous, but my reading is that an int value is
always stored, but sometimes the "results are unspecified", where I assume
"results" refer to the fractional part and the integer exponent. An unspecified
result then is stored to the object pointed to by exp.

However further down in Annex F (relevant for targets with IEC 60559, such as
x86_64):

"frexp(±∞, exp) returns ±∞, and stores an unspecified value in the object
pointed to by exp."

"frexp(NaN, exp) stores an unspecified value in the object pointed to by exp
(and returns a NaN)."

This is a lot less ambiguous.

[Bug c++/111776] New: ICE on delete expression with multiple viable destroying operator delete

2023-10-11 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111776

Bug ID: 111776
   Summary: ICE on delete expression with multiple viable
destroying operator delete
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: leni536 at gmail dot com
  Target Milestone: ---

version: gcc 13.2.0
flags: -std=c++20 -O2 -pedantic-errors

```
#include 

struct B {
void operator delete(B* ptr, std::destroying_delete_t);
};

struct D : B {
void operator delete(D* ptr, std::destroying_delete_t);
using B::operator delete;
};

void bar(D* ptr) {
delete ptr;
}
```

internal compiler error: in build_op_delete_call, at cp/call.cc:7914
   13 | delete ptr;
  |^~~
0x1ce7bde internal_error(char const*, ...)
???:0
0x7290fc fancy_abort(char const*, int, char const*)
???:0
0x7eb68c build_delete(unsigned int, tree_node*, tree_node*,
special_function_kind, int, int, int)
???:0
0x7d3757 delete_sanity(unsigned int, tree_node*, tree_node*, bool, int, int)
???:0
0x89fd5b c_parse_file()
???:0
0x98c5d9 c_common_parse_file()
???:0

https://godbolt.org/z/8rh7h7EWz

I'm not entirely sure what should actually happen here. I didn't find a
disambiguating rule at https://timsong-cpp.github.io/cppwp/n4868/expr.delete#10
.

[Bug c++/111776] ICE on delete expression with multiple viable destroying operator delete

2023-10-13 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111776

--- Comment #2 from Lénárd Szolnoki  ---
Same ICE without destroying delete:

```
struct A {
void operator delete(void *);
};

struct B {
void operator delete(void *);
};

struct C : A, B {
using A::operator delete;
using B::operator delete;
};

void f(C* ptr) {
delete ptr;
}
```

This goes back to GCC 7.

GCC 6 accepts it and calls `A::operator delete`, which is not much better.

https://godbolt.org/z/cczfdKoqb

[Bug c++/111776] ICE on delete expression with multiple viable destroying operator delete

2023-11-15 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111776

--- Comment #3 from Lénárd Szolnoki  ---
The C++ standard currently doesn't specify what the behavior of these program
snippets are. This is CWG2805.

https://cplusplus.github.io/CWG/issues/2805.html

[Bug c++/106371] Bogus narrowing conversion reported due to bitfield

2023-12-19 Thread leni536 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106371

Lénárd Szolnoki  changed:

   What|Removed |Added

 CC||leni536 at gmail dot com

--- Comment #4 from Lénárd Szolnoki  ---
Rejects valid code when -pedantic-errors is added:

struct S {
long l : 8;
};

int main() {
S s;
int i = {s.l};
}

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

Produces wrong code when it's used as a constraint:

struct S {
long l : 8;
};

template 
requires requires (T t) {
int{t.l};
}
void foo(T); // 1

void foo(...); // 2

int main() {
foo(S{}); // calls 2
}

https://godbolt.org/z/We4M1MP1M