[Bug c++/86577] non-ADL name lookup for operator<< at instantiation time?
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?
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
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
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
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
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
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)
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
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
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
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)
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]
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
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
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
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)
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
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.
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.
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
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
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
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
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
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]
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
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
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
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)
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
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
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
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
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
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
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