[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Peter Dimov changed: What|Removed |Added CC||pdimov at gmail dot com --- Comment #30 from Peter Dimov --- I was going to ask the stupid question "why not just use the straightforward double-checked locking here" but the answer is probably "ABI break".
[Bug c++/92985] missed optimization opportunity for switch linear transformation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92985 --- Comment #1 from Peter Dimov --- Reformulating the switch in terms of integral offsets struct X2 { int x, y, z; int operator[]( std::size_t i ) const noexcept { std::ptrdiff_t k0 = &x - &x; std::ptrdiff_t k1 = &y - &x; std::ptrdiff_t k2 = &z - &x; std::ptrdiff_t k; switch( i ) { case 0: k = k0; break; case 1: k = k1; break; case 2: k = k2; break; default: __builtin_unreachable(); } return *( &x + k ); } }; results in the desired f2(X2 const&, unsigned long): mov eax, DWORD PTR [rdi+rsi*4] ret (https://godbolt.org/z/YxhNSx)
[Bug c++/92985] missed optimization opportunity for switch linear transformation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92985 --- Comment #2 from Peter Dimov --- Two more reformulations that activate the linear transformation are: int operator[]( std::size_t i ) const noexcept { std::ptrdiff_t offset; switch( i ) { case 0: offset = offsetof(X, x); break; case 1: offset = offsetof(X, y); break; case 2: offset = offsetof(X, z); break; default: __builtin_unreachable(); } return *(int const*)((char const*)this + offset); } (https://godbolt.org/z/cJDB_m) and int operator[]( std::size_t i ) const noexcept { int X::* p; switch( i ) { case 0: p = &X::x; break; case 1: p = &X::y; break; case 2: p = &X::z; break; default: __builtin_unreachable(); } return this->*p; } (https://godbolt.org/z/xfsKh5)
[Bug c++/89029] New: __builtin_constant_p erroneously true
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89029 Bug ID: 89029 Summary: __builtin_constant_p erroneously true Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- In the following code: ``` inline bool assert_static_check( bool ev ) { return __builtin_constant_p( ev ) && !ev; } struct X1 { int v1_; }; inline bool operator==( X1 const& x1, X1 const& x2 ) { return x1.v1_ == x2.v1_; } int compare( X1 s1, X1 s2 ) { return assert_static_check( s1 == s2 ); } struct X2 { int v1_; int v2_; }; inline bool operator==( X2 const& x1, X2 const& x2 ) { return x1.v1_ == x2.v1_ && x1.v2_ == x2.v2_; } int compare( X2 s1, X2 s2 ) { return assert_static_check( s1 == s2 ); } ``` the generated code for the first compare function is, correctly, ``` compare(X1, X1): xor eax, eax ret ``` but for the second, it is ``` compare(X2, X2): mov eax, 1 cmp edi, esi je .L6 ret .L6: sar rdi, 32 sar rsi, 32 xor eax, eax cmp edi, esi setne al ret ``` which is incorrect, as `s1 == s2` isn't a constant here. (g++ -std=c++17 -O3, https://godbolt.org/z/nn0-4k) (This is simplified from an attempt to create a statically-diagnosed assert facility that would warn when the asserted expression is known to be false: https://godbolt.org/z/i5SXSd. Would've been cool if it worked.)
[Bug c++/89029] __builtin_constant_p erroneously true
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89029 --- Comment #4 from Peter Dimov --- (In reply to Jonathan Wakely from comment #3) > c.f. https://gcc.gnu.org/ml/libstdc++/2018-03/msg00031.html and the replies Yes, pretty much. > I doubt we would catch many bugs that way, as most bugs would involve > non-constant indices and vectors that have changed size dynamically at > run-time. It's still pretty cool when it works, f.ex. here: https://godbolt.org/z/fHCB16 Annoying that we're so close to useful static analysis but it doesn't _quite_ work. (Also note how the code for g() goes straight to assert without telling anyone.) >RESOLVED INVALID Too bad. FWIW, Clang trunk doesn't seem to suffer from the false positive problem. It also "proves" the assertion failure in g, but not in f: https://godbolt.org/z/92WyvR. (It also doesn't support __attribute((error)), which makes this technique limited in value.) Maybe the correct way to go about this is just to mark __assert_fail in some manner ("warn if unconditionally called"), instead of trying to (ab)use __builtin_constant_p.
[Bug c++/86354] New: Address comparison not a constant expression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86354 Bug ID: 86354 Summary: Address comparison not a constant expression Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- The following code: ``` struct X {}; struct Y: X {}; struct Z: X {}; extern Y y; extern Z z; constexpr X const& x1() { return y; } constexpr X const& x2() { return z; } static_assert( &x1() != &x2() ); ``` yields (with g++ 7.3 and 8.1) ``` testbed2017.cpp:12:1: error: non-constant condition for static assertion static_assert( &x1() != &x2() ); ^ testbed2017.cpp:12:22: error: '(((const X*)(& y)) != ((const X*)(& z)))' is not a constant expression static_assert( &x1() != &x2() ); ~~^~~~ ``` but other compilers accept it.
[Bug c++/86355] New: Internal compiler error with pack expansion and fold expression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86355 Bug ID: 86355 Summary: Internal compiler error with pack expansion and fold expression Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- The following code ``` #include template using mp_bool = std::integral_constant; using mp_true = mp_bool; template using mp_all = mp_bool<(static_cast(T::value) && ...)>; template using check2 = mp_all, mp_all..., mp_all...>>>; static_assert( std::is_same, mp_true>::value ); ``` with g++ 7.3 (and 8.1) yields ``` testbed2017.cpp: In substitution of 'template using check2 = mp_all, std::integral_constant(T::value) && ...)> > [with V = void; T = {int, float}]': testbed2017.cpp:10:52: required from here testbed2017.cpp:8:156: internal compiler error: Segmentation fault template using check2 = mp_all, mp_all..., mp_all...>>>; ^ ``` clang++ accepts it.
[Bug c++/86356] New: "invalid use of pack expansion" with fold expressions
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86356 Bug ID: 86356 Summary: "invalid use of pack expansion" with fold expressions Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- The code ``` #include template using mp_bool = std::integral_constant; template using mp_all = mp_bool<(static_cast(T::value) && ...)>; template using mp_any = mp_bool<(static_cast(T::value) || ...)>; template struct variant_base_impl {}; template using variant_base = variant_base_impl...>::value, mp_any...>, std::is_nothrow_default_constructible...>::value, T...>; int main() { variant_base(); } ``` yields with g++ 7.3 (and 8.1) ``` testbed2017.cpp: In substitution of 'template using variant_base = variant_base_impl(std::is_trivially_destructible::value) && ...)>::value, std::integral_constant(std::integral_constant(std::is_nothrow_move_constructible::value) && ...)>::value) || static_cast(std::is_nothrow_default_constructible::value) ...)>::value, T ...> [with T = {void, int, float}]': testbed2017.cpp:13:31: required from here testbed2017.cpp:6:82: error: invalid use of pack expansion expression template using mp_any = mp_bool<(static_cast(T::value) || ...)>; ^ ``` clang++ accepts.
[Bug c++/92005] New: switch code generation regression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92005 Bug ID: 92005 Summary: switch code generation regression Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- The following code: ``` template struct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded; struct T0 {}; struct T1 {}; struct T2 {}; struct T3 {}; struct T4 {}; struct variant { unsigned index_; union { T0 t0_; T1 t1_; T2 t2_; T3 t3_; T4 t4_; }; }; template int visit( F f, variant const& v ) { switch( v.index_ ) { case 0: return f( v.t0_ ); case 1: return f( v.t1_ ); case 2: return f( v.t2_ ); case 3: return f( v.t3_ ); case 4: return f( v.t4_ ); default: __builtin_unreachable(); } } int do_visit(variant const& v) { return visit(overloaded{ [](T0 val) { return 3; }, [](T1 val) { return 5; }, [](T2 val) { return 8; }, [](T3 val) { return 9; }, [](T4 val) { return 10; } }, v); } ``` (https://godbolt.org/z/uxQ6KF) generates ``` do_visit(variant const&): mov eax, DWORD PTR [rdi] jmp [QWORD PTR .L4[0+rax*8]] .L4: .quad .L8 .quad .L7 .quad .L9 .quad .L5 .quad .L3 .L9: mov eax, 8 ret .L7: mov eax, 5 ret .L8: mov eax, 3 ret .L5: mov eax, 9 ret .L3: mov eax, 10 ret ``` with the current gcc trunk on godbolt.org (g++ (Compiler-Explorer-Build) 10.0.0 20191005 (experimental)) and ``` do_visit(variant const&): mov eax, DWORD PTR [rdi] mov eax, DWORD PTR CSWTCH.7[0+rax*4] ret CSWTCH.7: .long 3 .long 5 .long 8 .long 9 .long 10 ``` with gcc 9.2.
[Bug c++/92005] [10 Regression] switch code generation regression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92005 --- Comment #2 from Peter Dimov --- r276416 makes -O2 inline less, and -O3 does fix this specific case. However, there appears to be some deeper issue here. I've reduced the number of cases from 10 to 5 for the example, but when I increase them back to 10 as in https://godbolt.org/z/VyCeWQ, gcc 9.2 still generates a simple lookup table at -O2, whereas gcc 10 generates a jump table even at -O3: https://godbolt.org/z/qJqNDh. ``` template struct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded; struct T0 {}; struct T1 {}; struct T2 {}; struct T3 {}; struct T4 {}; struct T5 {}; struct T6 {}; struct T7 {}; struct T8 {}; struct T9 {}; struct variant { unsigned index_; union { T0 t0_; T1 t1_; T2 t2_; T3 t3_; T4 t4_; T5 t5_; T6 t6_; T7 t7_; T8 t8_; T9 t9_; }; }; template int visit( F f, variant const& v ) { switch( v.index_ ) { case 0: return f( v.t0_ ); case 1: return f( v.t1_ ); case 2: return f( v.t2_ ); case 3: return f( v.t3_ ); case 4: return f( v.t4_ ); case 5: return f( v.t5_ ); case 6: return f( v.t6_ ); case 7: return f( v.t7_ ); case 8: return f( v.t8_ ); case 9: return f( v.t9_ ); default: __builtin_unreachable(); } } int do_visit(variant const& v) { return visit(overloaded{ [](T0 val) { return 3; }, [](T1 val) { return 5; }, [](T2 val) { return 8; }, [](T3 val) { return 9; }, [](T4 val) { return 10; }, [](T5 val) { return 11; }, [](T6 val) { return 12; }, [](T7 val) { return 13; }, [](T8 val) { return 14; }, [](T9 val) { return 233; } }, v); } ```
[Bug c++/83835] New: constexpr constructor rejected in c++17 mode (regression WRT c++14)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83835 Bug ID: 83835 Summary: constexpr constructor rejected in c++17 mode (regression WRT c++14) Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- This code: ``` class X { public: virtual ~X(); }; class Y { private: class Z: public X { private: Y const * p_; public: constexpr explicit Z( Y const * p ): p_( p ) {} }; Z z_; public: constexpr Y() noexcept: z_( this ) {} }; int main() { } ``` is accepted in C++14 mode, and in C++1z mode by g++ 5 or 6, but fails in C++17 mode under g++ 7 or 8 with ``` error: temporary of non-literal type 'Y::Z' in a constant expression ```
[Bug c++/87205] New: Inefficient code generation for switch
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87205 Bug ID: 87205 Summary: Inefficient code generation for switch Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- For the following code: ``` void f( int x ); void h( unsigned ix ) { switch( ix ) { case 0: f(42); break; case 1: f(42); break; case 2: f(42); break; case 3: f(42); break; case 4: f(42); break; case 5: f(42); break; default: __builtin_unreachable(); } } ``` g++ 9.0 -O2, -O3 generates: ``` h(unsigned int): cmp edi, 5 jbe .L5 .L5: mov edi, 42 jmp f(int) ``` https://godbolt.org/z/4I_Chu The initial part that compares edi to 5 is redundant. At -O1 the result is a jump table that doesn't check edi, as expected: ``` h(unsigned int): sub rsp, 8 mov edi, edi jmp [QWORD PTR .L4[0+rdi*8]] ``` This is a simplified example; I've stripped the metaprogramming that produces it. :-) For comparison, g++ 8.2 produces ``` h(unsigned int): cmp edi, 5 ja .L2 mov edi, 42 jmp f(int) h(unsigned int) [clone .cold.0]: .L2: ```
[Bug tree-optimization/87205] Inefficient code generation for switch
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87205 --- Comment #4 from Peter Dimov --- If the code is not the same the jump table is not optimized out and there's no extra check. But it also happens with code that is not the same on the C++ side, for example: ``` struct X { int v; }; template struct Y: X { }; void f( X* x ); void h( unsigned ix, void* p ) { switch( ix ) { case 0: f( (Y<0>*)p ); break; case 1: f( (Y<1>*)p ); break; case 2: f( (Y<2>*)p ); break; case 3: f( (Y<3>*)p ); break; case 4: f( (Y<4>*)p ); break; case 5: f( (Y<5>*)p ); break; default: __builtin_unreachable(); } } ``` ``` h(unsigned int, void*): cmp edi, 5 jbe .L5 .L5: mov rdi, rsi jmp f(X*) ``` https://godbolt.org/z/2Lh_GZ A variation on the same theme, which demonstrates another kind of missed optimization: ``` struct X { int v; }; template struct Y: X { }; int h( unsigned ix, void* p ) { switch( ix ) { case 0: return ((Y<0>*)p)->v; case 1: return ((Y<1>*)p)->v; case 2: return ((Y<2>*)p)->v; case 3: return ((Y<3>*)p)->v; case 4: return ((Y<4>*)p)->v; case 5: return ((Y<5>*)p)->v; default: __builtin_unreachable(); } } ``` ``` h(unsigned int, void*): mov edi, edi mov eax, DWORD PTR [rsi] jmp [QWORD PTR .L4[0+rdi*8]] .L4: .quad .L9 .quad .L8 .quad .L7 .quad .L6 .quad .L5 .quad .L3 .L5: ret .L3: ret .L9: ret .L8: ret .L7: ret .L6: ret ``` https://godbolt.org/z/lCzlR2 There's a table, so there's no redundant check.
[Bug tree-optimization/87205] Inefficient code generation for switch
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87205 --- Comment #5 from Peter Dimov --- Another: ``` struct X { int v; }; template struct Y: X { }; void f( int v ); void h( unsigned ix, void* p ) { switch( ix ) { case 0: f( ((Y<0>*)p)->v ); break; case 1: f( ((Y<1>*)p)->v ); break; case 2: f( ((Y<2>*)p)->v ); break; case 3: f( ((Y<3>*)p)->v ); break; case 4: f( ((Y<4>*)p)->v ); break; case 5: f( ((Y<5>*)p)->v ); break; default: __builtin_unreachable(); } } ``` ``` h(unsigned int, void*): mov edi, edi jmp [QWORD PTR .L4[0+rdi*8]] .L4: .quad .L3 .quad .L3 .quad .L3 .quad .L3 .quad .L3 .quad .L3 .L3: mov edi, DWORD PTR [rsi] jmp f(int) ``` https://godbolt.org/z/pGVx6W This however demonstrates a different problem, so it may need to go into a separate bug.
[Bug tree-optimization/87205] Inefficient code generation for switch
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87205 --- Comment #8 from Peter Dimov --- (In reply to Martin Liška from comment #7) > I'm not sure here Y are different types here and member access based on > the type is distinct. Yes, one could argue that, I suppose. But in the `return ((Y<0>*)p)->v;` case the member access _is_ lifted outside the jump table. If that's correct there, it should also be correct here. :-)
[Bug tree-optimization/87205] Inefficient code generation for switch
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87205 --- Comment #9 from Peter Dimov --- For more context, see https://godbolt.org/z/SzfpKr ``` #include template struct variant { std::aligned_union_t<0, T...> storage_; unsigned index_; }; template auto visit( variant& v, F f ) { switch( v.index_ ) { case 0: return f( (T0&)v.storage_ ); case 1: return f( (T1&)v.storage_ ); case 2: return f( (T2&)v.storage_ ); case 3: return f( (T3&)v.storage_ ); case 4: return f( (T4&)v.storage_ ); case 5: return f( (T5&)v.storage_ ); default: __builtin_unreachable(); } } struct X { int v; }; template struct Y: X { }; using V = variant, Y<1>, Y<2>, Y<3>, Y<4>, Y<5>>; void f( X& ); int g( int ); int h1( V& v ) { return visit( v, [](X const& x){ return x.v; } ); } int h2( V& v ) { return visit( v, [](auto&& x){ return x.v; } ); } void h3( V& v ) { return visit( v, [](auto&& x){ f(x); } ); } int h4( V& v ) { return visit( v, [](auto&& x){ return g(x.v); } ); } ``` This generates ``` h1(variant, Y<1>, Y<2>, Y<3>, Y<4>, Y<5> >&): mov eax, DWORD PTR [rdi] ret h2(variant, Y<1>, Y<2>, Y<3>, Y<4>, Y<5> >&): mov eax, DWORD PTR [rdi] ret h3(variant, Y<1>, Y<2>, Y<3>, Y<4>, Y<5> >&): cmp DWORD PTR [rdi+4], 5 jbe .L15 .L15: jmp f(X&) h4(variant, Y<1>, Y<2>, Y<3>, Y<4>, Y<5> >&): cmp DWORD PTR [rdi+4], 5 jbe .L19 .L19: mov edi, DWORD PTR [rdi] jmp g(int) ``` so the member access is folded in both cases (which is good!), even though the first occurs through X& and the second through Y&. I've been unable to determine what makes the optimizations misfire. This code should in principle be the same as the simplified one, but it isn't.
[Bug c++/81311] New: An std::ref argument calls copy constructor instead of template constructor in C++17 mode
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81311 Bug ID: 81311 Summary: An std::ref argument calls copy constructor instead of template constructor in C++17 mode Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- In the following code: ``` #include #include struct function { function() { std::cout << "function()\n"; } template function( F ) { std::cout << "function(F)\n"; } function( function const& ) { std::cout << "function(function const&)\n"; } }; int main() { function f1; function f2( std::ref(f1) ); } ``` g++ 7.1 and 8 with -std=c++1z/17 call the copy constructor, whereas with -std=c++14 they call the template constructor (as do other compilers in all language modes.)
[Bug middle-end/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #7 from pdimov at gmail dot com 2010-05-17 19:10 --- (In reply to comment #6) > Basically the middle-end sees this the same as > int i = 1, j; > float *p = new (&i) float(0.0); > j = i; > return *reinterpret_cast(&j); > and you expect to return 0.0. The int/float example does violate the aliasing rules, but I don't think that it properly describes what's happening. I see it more like a combination of the following two examples: #include struct X { char data[ sizeof( float ) ]; }; int main() { X x1; new( &x1.data ) float( 3.14f ); X x2 = x1; std::cout << *(float const*)&x2.data << std::endl; } and #include union Y { int i; float f; }; int main() { Y y1; y1.f = 3.14f; Y y2 = y1; std::cout << y2.f << std::endl; } I don't think either of them violates the standard. -- pdimov at gmail dot com changed: What|Removed |Added ---------------- CC||pdimov at gmail dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #9 from pdimov at gmail dot com 2010-05-17 20:12 --- But the standard says in [basic.types] that "For any trivially copyable type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if the underlying bytes (1.7) making up obj1 are copied into obj2,40 obj2 shall subsequently hold the same value as obj1." "float" is a trivially copyable type. Copying X results in copying the bytes of X::data (because the default copy constructor of a class does a memberwise copy, and the default copy constructor of an array does an elementwise copy). Therefore, the underlying bytes of the object of type float, initialized at x1.data, are copied into x2.data, which then must, if interpreted as a float, hold the same value as the original object. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug c++/21528] New: Boost shared_ptr_test.cpp fails with -O3
The following portion of shared_ptr_test.cpp: #include #include int main() { boost::shared_ptr pi(new int); boost::shared_ptr pv(pi); boost::shared_ptr pi2 = boost::static_pointer_cast(pv); BOOST_TEST(pi.get() == pi2.get()); BOOST_TEST(!(pi < pi2 || pi2 < pi)); BOOST_TEST(pi.use_count() == 3); BOOST_TEST(pv.use_count() == 3); BOOST_TEST(pi2.use_count() == 3); return boost::report_errors(); } (using the current Boost CVS HEAD that will become 1.33 soon) fails the three use_count() tests with g++ 4.0.0 -O3, but not with -O0, 1, 2. It seems that a reference count increment is being optimized away. This does not happen if BOOST_TEST is replaced with assert. -- Summary: Boost shared_ptr_test.cpp fails with -O3 Product: gcc Version: 4.0.0 Status: UNCONFIRMED Severity: normal Priority: P2 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: pdimov at gmail dot com CC: gcc-bugs at gcc dot gnu dot org GCC target triplet: i686-pc-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21528
[Bug c++/21528] Boost shared_ptr_test.cpp fails with -O3
--- Additional Comments From pdimov at gmail dot com 2005-05-12 08:42 --- Created an attachment (id=8871) --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=8871&action=view) Preprocessed source -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21528
[Bug c++/99495] constexpr virtual destructor is used before its definition
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99495 Peter Dimov changed: What|Removed |Added CC||pdimov at gmail dot com --- Comment #1 from Peter Dimov --- Simplified: ``` struct Base { constexpr virtual ~Base() = default; }; constexpr Base b; ``` https://godbolt.org/z/qGn1nx9ET
[Bug c++/97464] New: Missed redundant store optimization opportunity
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97464 Bug ID: 97464 Summary: Missed redundant store optimization opportunity Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- The code void f( int& x, float& y ) { ++x; y = 1; --x; } compiles to f(int&, float&): mov eax, DWORD PTR [rdi] mov DWORD PTR [rsi], 0x3f80 mov DWORD PTR [rdi], eax ret (https://godbolt.org/z/so4h3v) but the load from, and the store to, [rdi] are redundant. It's obvious that TBAA is active, but it for some reason doesn't go far enough. This is a simplified example from "realer" code where x is a reference count whose unnecessary manipulations could have been optimized out entirely.
[Bug c++/63707] Brace initialization of array sometimes fails if no copy constructor
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63707 Peter Dimov changed: What|Removed |Added CC||pdimov at gmail dot com --- Comment #14 from Peter Dimov --- FWIW, I just hit this problem as well when trying to make changes to Boost.Variant2. My reduced test case is https://godbolt.org/z/zG6ddP; I was going to submit that as a bug but found this one. I support the petition to have this fixed.
[Bug c++/98649] New: Trivial jump table not eliminated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98649 Bug ID: 98649 Summary: Trivial jump table not eliminated Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- Trivial jump tables where all entries are the same are sometimes not eliminated. E.g. the following example ``` struct Base { virtual void run( float f ) = 0; }; struct T0: Base { void run( float f ); }; struct T1: Base { void run( float f ); }; struct T2: Base { void run( float f ); }; struct T3: Base { void run( float f ); }; struct T4: Base { void run( float f ); }; template struct mp_int {}; struct variant { unsigned index_; union { T0 t0_; T1 t1_; T2 t2_; T3 t3_; T4 t4_; }; T0& get( mp_int<0> ) { return t0_; } T1& get( mp_int<1> ) { return t1_; } T2& get( mp_int<2> ) { return t2_; } T3& get( mp_int<3> ) { return t3_; } T4& get( mp_int<4> ) { return t4_; } }; template decltype(auto) get( variant& v ) { return v.get( mp_int() ); } void f1( variant& v, float f ) { switch( v.index_ ) { case 0: get<0>(v).run( f ); break; case 1: get<1>(v).run( f ); break; case 2: get<2>(v).run( f ); break; case 3: get<3>(v).run( f ); break; case 4: get<4>(v).run( f ); break; default: __builtin_unreachable(); } } ``` (https://godbolt.org/z/MxzGh8) results in ``` f1(variant&, float): mov eax, DWORD PTR [rdi] lea r8, [rdi+8] jmp [QWORD PTR .L4[0+rax*8]] .L4: .quad .L3 .quad .L3 .quad .L3 .quad .L3 .quad .L3 .L3: mov rax, QWORD PTR [rdi+8] mov rdi, r8 mov rax, QWORD PTR [rax] jmp rax ``` This case may seem contrived, but it's not that rare in practice, because code using std::variant or equivalent (such as Boost.Variant2, from which the example has been reduced) is becoming more and more common nowadays.
[Bug tree-optimization/14721] jump optimization involving a sibling call within a jump table
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14721 Peter Dimov changed: What|Removed |Added CC||pdimov at gmail dot com --- Comment #5 from Peter Dimov --- It's becoming more common with the use of std::variant and compatible libraries (such as Boost.Variant2.) https://godbolt.org/z/414e6j shows a reduced example.
[Bug c++/100827] New: Compiler crash with Boost.Bimap and Boost.Xpressive
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100827 Bug ID: 100827 Summary: Compiler crash with Boost.Bimap and Boost.Xpressive Product: gcc Version: 11.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- I'm seeing a compiler crash with g++ 10/11 in -std=c++03 mode https://godbolt.org/z/h4dY9oKGc https://godbolt.org/z/o1P6nrhqG when compiling one file from the Boost.Bimap test suite: ``` #include #include #include #include #include using namespace boost::bimaps; using namespace boost::xpressive; namespace xp = boost::xpressive; int main() { //[ code_bimap_and_boost_xpressive typedef bimap< std::string, int > bm_type; bm_type bm; std::string rel_str("one <--> 1 two <--> 2 three <--> 3"); sregex rel = ( (s1= +_w) >> " <--> " >> (s2= +_d) ) [ xp::ref(bm)->*insert( xp::construct(s1, as(s2)) ) ]; sregex relations = rel >> *(+_s >> rel); regex_match(rel_str, relations); assert( bm.size() == 3 ); //] return 0; } ``` (https://github.com/boostorg/bimap/blob/03bf1d222914d0c15563414f2e51b6a4ce0e0f69/example/bimap_and_boost/xpressive.cpp) Trunk no longer has the issue, and neither do earlier versions or language modes. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94938 looks related, but is considered fixed in GCC 10.
[Bug c++/100827] Compiler crash with Boost.Bimap and Boost.Xpressive
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100827 --- Comment #1 from Peter Dimov --- Update: GCC 10.2 doesn't have the issue, but 10.1 and 10.3 do. :-)
[Bug libstdc++/108836] New: std::mutex disappears in single-threaded libstdc++ builds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108836 Bug ID: 108836 Summary: std::mutex disappears in single-threaded libstdc++ builds Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- We've been getting reports in Boost that our uses of and std::mutex don't work in a single-threaded build of libstdc++, so we had to add configuration macros to avoid these issues. One example is https://github.com/boostorg/system/commit/53c00841fc0d892bf43cda60e3ea2f05c4362b32, another https://github.com/boostorg/url/issues/684. Is there a reason not to make std::mutex available in single threaded builds, with its operations being no-ops?
[Bug libstdc++/108836] std::mutex disappears in single-threaded libstdc++ builds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108836 --- Comment #2 from Peter Dimov --- That's good to hear, but I don't think the issue is specific to mingw32. The other report, https://github.com/boostorg/system/issues/92, was about "B&R PLC", whatever this means. :-)
[Bug libstdc++/108836] std::mutex disappears in single-threaded libstdc++ builds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108836 --- Comment #4 from Peter Dimov --- A compromise between no mutex at all, and a mutex that is silently a no-op, could be a no-op mutex with [[deprecated]] members, although the atomic_flag is probably better.
[Bug libstdc++/108952] Regression in uses_allocator_construction_args for pair of rvalue references
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108952 Peter Dimov changed: What|Removed |Added CC||pdimov at gmail dot com --- Comment #4 from Peter Dimov --- An easy fix is to use `std::get<0>` instead of `.first`.
[Bug c++/104867] New: Base class matching ignores type of `auto` template parameter
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104867 Bug ID: 104867 Summary: Base class matching ignores type of `auto` template parameter Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- The following program ``` enum class Foo { A1 }; enum class Bar { B1 }; template struct enum_ { }; template struct list {}; struct enum_type_map: list, int>, list, double> {}; template V f( list, V> const& ) { return {}; } int main() { f( enum_type_map() ); } ``` yields ``` : In function 'int main()': :26:6: error: no matching function for call to 'f(enum_type_map)' 26 | f( enum_type_map() ); | ~^~~ :19:21: note: candidate: 'template V f(const list, V>&)' 19 | template V f( list, V> const& ) | ^ :19:21: note: template argument deduction/substitution failed: :26:6: note: 'const list, V>' is an ambiguous base class of 'enum_type_map' 26 | f( enum_type_map() ); | ~^~~ ``` which is caused by `A1` and `B1` having the same value 0, even though their types differ. (https://godbolt.org/z/3854zrY7x) Clang successfully compiles the code (https://godbolt.org/z/eKEdf1zdo). This is a distilled version of a bug report against `mp_map_find` from Mp11: https://github.com/boostorg/mp11/issues/72
[Bug libstdc++/104945] New: std::hash ignores the top 32 bits when size_t is 32 bit
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104945 Bug ID: 104945 Summary: std::hash ignores the top 32 bits when size_t is 32 bit Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- A benchmark in Boost.Unordered uses uint64_t keys of the form `i << 40`: https://github.com/boostorg/unordered/blob/33f81fd49039bccd1aa3dfd5a29ef6073b93009c/benchmark/uint64.cpp#L65 which leads to pathological behavior with std::unordered_map in 32 bit mode, because std::hash ignores the top 32 bits: https://godbolt.org/z/PncKbT7aq I'm not entirely sure whether this would be considered a bug, but decided that it's worth reporting. Ideally, std::hash ought to take into account all bits of the integral input, instead of truncating it to size_t.
[Bug c++/104426] New: -fsanitize=undefined causes constexpr failures
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104426 Bug ID: 104426 Summary: -fsanitize=undefined causes constexpr failures Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- The following program ``` struct category { constexpr bool failed() const noexcept { return true; } }; inline constexpr category s_cat; struct condition { category const* cat_; constexpr bool failed() const noexcept { if( cat_ ) { return cat_->failed(); } else { return false; } } }; int main() { constexpr condition cond{ &s_cat }; static_assert( cond.failed() ); } ``` compiles without -fsanitize=undefined (https://godbolt.org/z/Pn9M5ocfz), but fails with it (https://godbolt.org/z/KKc8Tb9qe) with ``` : In function 'int main()': :31:31: error: non-constant condition for static assertion 31 | static_assert( cond.failed() ); |~~~^~ :31:31: in 'constexpr' expansion of 'cond.condition::failed()' :17:13: error: '((& s_cat) != 0)' is not a constant expression 17 | if( cat_ ) | ^~~~ ``` This happens under all GCC versions starting from 7. (The above is an extract from the test suite for boost::system::error_condition.)
[Bug c++/104426] -fsanitize=undefined causes constexpr failures
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104426 --- Comment #4 from Peter Dimov --- FWIW, I agree with everything Martin Sebor says in PR71962. -fallow-address-zero is an entirely separate feature, and shouldn't be implied by -fsanitize=undefined.
[Bug c++/102350] New: __builtin_source_location not available in earlier language modes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102350 Bug ID: 102350 Summary: __builtin_source_location not available in earlier language modes Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- Currently, `__builtin_source_location` requires (a) `` to be included and (b) -std=c++20. Are there good reasons for these restrictions? The builtin would still be extremely valuable in earlier language modes. Libraries that still support 03/11/14/17 (Boost.System, for instance) could transparently supply source locations by using a default `void const* loc = __builtin_source_location()` argument.
[Bug c++/102350] __builtin_source_location not available in earlier language modes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102350 --- Comment #2 from Peter Dimov --- (In reply to Jakub Jelinek from comment #1) > __builtin_source_location doesn't require -std=c++20, but indeed does > require or some compatible definition of > std::source_location::__impl class, and as it doesn't have hardcoded layout > of that structure but instead matches whatever the source header provides > (looks up fields it needs in there and uses whatever types and layout they > have), there is no way around that. That was my guess. I suppose that's inevitable then, and there's nothing to ask for on the compiler side, just needs to not disable itself completely for pre-C++20 as it does now. (It's not going to work, but it can still provide __impl so that the builtin can see it.)
[Bug c++/102350] __builtin_source_location not available in earlier language modes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102350 --- Comment #4 from Peter Dimov --- On the surface this looks not hard to fix - use ::__source_location_impl (or std::__source_location_impl) instead of std::source_location:__impl as the layout struct - but I'm not sure whether this would pose some further problems.
[Bug c++/102350] __builtin_source_location not available in earlier language modes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102350 --- Comment #7 from Peter Dimov --- (In reply to Jonathan Wakely from comment #5) > Sure. It's just a question of whether we're trying to provide a general > purpose extension available for users, or an internal helper for the > std::lib. IIRC we explicitly decided we only cared about supporting the > latter. Yes, of course. It's just that __builtin_source_location is so painfully close to exactly what I want - it gives a single pointer representing the location - that it would be a pity not being able to use it without -std=c++20.
[Bug c++/102350] __builtin_source_location not available in earlier language modes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102350 --- Comment #8 from Peter Dimov --- (In reply to Jakub Jelinek from comment #6) > Note, having the struct somewhere else isn't that useful unless you know > exactly how its non-static data members are named and what they mean, so > ideally a class with accessor methods, which is what std::source_location > provides currently. I was going to undefined-behavior my way to victory by making boost::source_location layout-compatible with the internal struct, and just casting the result of __builtin_source_location to boost::source_location const*. I think this works under the GCC object model?
[Bug c++/102350] __builtin_source_location not available in earlier language modes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102350 --- Comment #10 from Peter Dimov --- (In reply to Jakub Jelinek from comment #9) > That would be an aliasing violation. > The artificial vars created by __builtin_source_location have the > std::source_location::__impl type, so accessing those using some other > dynamic type is invalid. In that case, the only valid way to use the result of __builtin_source_location would just be std::source_location itself. :-/ I wonder whether there's a conformance problem in making it available. It's true that the identifier `source_location` isn't reserved, but only programs that include `` can tell the difference, and these programs (assuming they existed and worked) will probably be broken anyway because now they'll be including the standard header instead of their own.
[Bug c++/102350] __builtin_source_location not available in earlier language modes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102350 --- Comment #15 from Peter Dimov --- (In reply to Jonathan Wakely from comment #13) > It wouldn't work correctly in all cases, as Jakub points out, because > std::source_location::current() is part of the magic. > > And I'm not convinced we want/need to support those uses. I think that users of __builtin_source_location will be content with the subset of uses it supports. :-)
[Bug c++/102350] __builtin_source_location not available in earlier language modes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102350 --- Comment #16 from Peter Dimov --- (In reply to Jakub Jelinek from comment #14) > But we haven't done that that way and how would headers know if the > __builtin_source_location that is available is the old or new one? The header could do namespace std { struct __source_location_impl { ... }; class source_location { using __impl = __source_location_impl; // ... }; } unless the compiler looks specifically for a nested struct, in which case class source_location { struct __impl: __source_location_impl {}; // ... };
[Bug c++/102350] __builtin_source_location not available in earlier language modes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102350 --- Comment #18 from Peter Dimov --- I would use it like this: https://godbolt.org/z/1eqEx6678 #include struct error_category { }; error_category const& system_category(); struct error_code { error_code( int v, error_category const& cat, void const* loc = __builtin_source_location() ); }; int main() { error_code ec( 5, system_category() ); } provided, of course, I have some not-undefined way to interpret its result.
[Bug libstdc++/102425] New: std::error_code() does not compare equal to std::error_condition()
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102425 Bug ID: 102425 Summary: std::error_code() does not compare equal to std::error_condition() Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- As the title says. https://godbolt.org/z/er7qsjvoo.
[Bug c++/102651] New: typeid(X**) instantiates X
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102651 Bug ID: 102651 Summary: typeid(X**) instantiates X Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- Using f.ex. `typeid(std:pair**)` tries to instantiate `std::pair` and fails: https://godbolt.org/z/GhbYe3P8j (One asterisk should be enough, but doesn't work either.) The example without pair is ``` #include template struct S{ T x; }; void foo() { typeid( S** ); } ``` https://godbolt.org/z/nG3Kr3Te7 Interestingly, if `S` is incomplete, it works: ``` #include template struct S; void foo() { typeid( S** ); } ``` https://godbolt.org/z/nK8b5n1qn
[Bug tree-optimization/105545] [12/13 Regression] Warning for string assignment with _GLIBCXX_ASSERTIONS since r12-3347-g8af8abfbbace49e6
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105545 --- Comment #9 from Peter Dimov --- My Godbolt link above no longer reproduces the warning because of https://github.com/boostorg/describe/commit/c8c46bfdf78022a8a7e9e06983d8b04ccb921991, but this one does: https://godbolt.org/z/oT1M31osa. Looks like trunk has fixed the issue, though: https://godbolt.org/z/1GGvYWxKG.
[Bug target/107590] __atomic_test_and_set broken on PowerPC
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107590 Peter Dimov changed: What|Removed |Added CC||pdimov at gmail dot com --- Comment #7 from Peter Dimov --- The spinlock is indeed using an `unsigned char`: https://github.com/boostorg/smart_ptr/blob/c577d68b0272fd0bddc88ea60a8db07219391589/include/boost/smart_ptr/detail/spinlock_gcc_atomic.hpp#L33 That's because `__atomic_test_and_set` is documented to work on either `bool` or `char`: https://gcc.gnu.org/onlinedocs/gcc/extensions-to-the-c-language-family/built-in-functions-for-memory-model-aware-atomic-operations.html#_CPPv421__atomic_test_and_setPvi "bool __atomic_test_and_set(void *ptr, int memorder) This built-in function performs an atomic test-and-set operation on the byte at *ptr. The byte is set to some implementation defined nonzero ‘set’ value and the return value is true if and only if the previous contents were ‘set’. It should be only used for operands of type bool or char. For other types only part of the value may be set." I don't see an alignment requirement being mentioned here.
[Bug target/107590] __atomic_test_and_set broken on PowerPC
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107590 --- Comment #9 from Peter Dimov --- The easiest way to reproduce the issue is with the following test: https://github.com/boostorg/smart_ptr/blob/c577d68b0272fd0bddc88ea60a8db07219391589/test/spinlock_test.cpp This crashes because - presumably - sp2 is on an odd address. The definition of the spinlock class is here: https://github.com/boostorg/smart_ptr/blob/c577d68b0272fd0bddc88ea60a8db07219391589/include/boost/smart_ptr/detail/spinlock_gcc_atomic.hpp
[Bug c++/100157] Support `__type_pack_element` like Clang
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100157 Peter Dimov changed: What|Removed |Added CC||pdimov at gmail dot com --- Comment #11 from Peter Dimov --- Just import mp11 wholesale and use mp_at_c and mp_find :-)
[Bug c++/105482] New: Regression with `>=` in a template argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105482 Bug ID: 105482 Summary: Regression with `>=` in a template argument Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- The current GCC trunk in C++11 or C++14 mode gives an error when including boost/mp11/algorithm.hpp (from Boost 1.79): opt/compiler-explorer/libs/boost_1_79_0/boost/mp11/algorithm.hpp:445:102: error: '>=' should be '> =' to terminate a template argument list 445 | struct mp_take_c_impl, typename std::enable_if= 10>::type> | ^~ | > = /opt/compiler-explorer/libs/boost_1_79_0/boost/mp11/algorithm.hpp:445:107: error: template argument 3 is invalid 445 | struct mp_take_c_impl, typename std::enable_if= 10>::type> | ^ /opt/compiler-explorer/libs/boost_1_79_0/boost/mp11/algorithm.hpp:445:114: error: expected unqualified-id before '>' token 445 | struct mp_take_c_impl, typename std::enable_if= 10>::type> | ^ See e.g. https://godbolt.org/z/nE9754and and https://github.com/boostorg/mp11/issues/73. GCC 11 works, as does trunk in C++17 mode or later.
[Bug c++/102168] -Wnon-virtual-dtor shouldn't fire for protected dtor in a class with a friend declaration
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102168 Peter Dimov changed: What|Removed |Added CC||pdimov at gmail dot com --- Comment #1 from Peter Dimov --- An issue against Boost.System has just been filed as a result of this warning: https://github.com/boostorg/system/issues/83 It took me a while to figure out why the warning fires: because of the `friend class error_code` declaration in `error_category` (https://godbolt.org/z/z6x14P7M4). Please reconsider issuing the warning when the destructor is protected and a friend declaration exists. A protected destructor is a clear indication that the type is intended as a base class.
[Bug c++/102168] -Wnon-virtual-dtor shouldn't fire for protected dtor in a class with a friend declaration
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102168 --- Comment #4 from Peter Dimov --- Warning on a private destructor + a friend declaration makes sense, because a private destructor implies that the type is not intended to be derived from. But warning on a protected destructor + a friend does not.
[Bug c++/102168] -Wnon-virtual-dtor shouldn't fire for protected dtor in a class with a friend declaration
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102168 --- Comment #6 from Peter Dimov --- Yes, I suppose you're right. The warning warns that Derived _can be_ deleted via Base*, and that's correct - if not very useful in practice in this specific case. In fact the private destructor case is even less useful. ~Derived won't compile unless it's Derived that is Base's friend, in which case everything is actually fine. I suppose we'll have to live with it. The annoying part is that there's no warning, and then you add an unrelated friend declaration while refactoring, and the warning appears.
[Bug target/105992] New: memcmp(p, q, 7) == 0 can be optimized better on x86
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105992 Bug ID: 105992 Summary: memcmp(p, q, 7) == 0 can be optimized better on x86 Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- bool eq( char const* p ) { return __builtin_memcmp( p, "literal", 7 ) == 0; } generates eq(char const*): cmp DWORD PTR [rdi], 1702127980 je .L6 .L2: mov eax, 1 testeax, eax seteal ret .L6: xor eax, eax cmp DWORD PTR [rdi+3], 1818325605 jne .L2 testeax, eax seteal ret (https://godbolt.org/z/68MKqGz9T) but LLVM does eq(char const*): # @eq(char const*) mov eax, 1702127980 xor eax, dword ptr [rdi] mov ecx, 1818325605 xor ecx, dword ptr [rdi + 3] or ecx, eax seteal ret (https://godbolt.org/z/jxcb85Ysa) There are similar bugs for ARM (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104611) and AVX512 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104610) but I haven't found one for vanilla x86. Recent changes to std::string::operator== make it use the above pattern: https://godbolt.org/z/8KxqqG9cx
[Bug tree-optimization/105545] [12/13 Regression] Warning for string assignment with _GLIBCXX_ASSERTIONS since r12-3347-g8af8abfbbace49e6
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105545 Peter Dimov changed: What|Removed |Added CC||pdimov at gmail dot com --- Comment #7 from Peter Dimov --- FWIW, I'm getting this warning in one of the Boost.Describe examples (https://godbolt.org/z/WKMjeTdne) from innocent-looking code that concatenates std::strings with op+.
[Bug libstdc++/114865] New: std::atomic::compare_exchange_strong seems to hang under GCC 13 on Ubuntu 23.04
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114865 Bug ID: 114865 Summary: std::atomic::compare_exchange_strong seems to hang under GCC 13 on Ubuntu 23.04 Product: gcc Version: 13.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- I'm getting weird hangs on Github Actions when using `std::atomic::compare_exchange_strong` under GCC 13 on Ubuntu 23.04 (only; GCC 12 and earlier on Ubuntu 22.04 and earlier work). `state_type` is defined as ``` struct state_type { std::uint64_t timestamp; std::uint16_t clock_seq; }; ``` and the code doing the CAS is ``` auto oldst = ps_->load( std::memory_order_relaxed ); for( ;; ) { auto newst = get_new_state( oldst ); if( ps_->compare_exchange_strong( oldst, newst, std::memory_order_relaxed, std::memory_order_relaxed ) ) { state_ = newst; break; } } ``` where `ps` is of type `std::atomic*`. At a glance, I see nothing immediately wrong with the generated code (https://godbolt.org/z/8Ee3hrTz8). However, when I change `state_type` to ``` struct state_type { std::uint64_t timestamp; std::uint16_t clock_seq; std::uint16_t padding[ 3 ]; }; ``` the hangs disappear. This leads me to think that the problem is caused by the original struct having padding, which isn't being handled correctly for some reason. As we know, `std::atomic::compare_exchange_strong` is carefully specified to take and return `expected` by reference, such that it can both compare the entire object as if via `memcmp` (including the padding), and return it as if by `memcpy`, again including the padding. Even though the padding bits of the initial value returned by the atomic load are unspecified, at most one iteration of the loop would be required for the padding bits to converge and for the CAS to succeed. However, going by the symptoms alone, this doesn't seem to be the case here. The problem may well be inside libatomic, of course; I have no way to tell. One GHA run showing the issue is https://github.com/boostorg/uuid/actions/runs/8821753835, where only the GCC 13 job times out.
[Bug libstdc++/114865] std::atomic::compare_exchange_strong seems to hang under GCC 13 on Ubuntu 23.04
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114865 --- Comment #1 from Peter Dimov --- > The problem may well be inside libatomic, of course; I have no way to tell. Narrator: but he did, in fact, have a way to tell. This is a GHA run with GCC 9 to 13 tested on both Ubuntu 23.04 and Ubuntu 23.10, and only GCC 13 hangs. https://github.com/boostorg/uuid/actions/runs/8852038822/job/24309866206 And indeed, the codegen from GCC 12 (https://godbolt.org/z/xc7oT76fn) is radically different from (and much simpler than) the GCC 13 one (https://godbolt.org/z/eP48xv3Mr). I think that the problem has been introduced with this commit: https://github.com/gcc-mirror/gcc/commit/157236dbd621644b3cec50b6cf38811959f3e78c which, ironically enough, was supposed to improve the handling of types with padding bits, but broke them entirely. (I told the committee there was nothing wrong with compare_exchange as specified, but did they listen to me? To ask the question is to answer it.)
[Bug libstdc++/114865] std::atomic::compare_exchange_strong seems to hang under GCC 13 on Ubuntu 23.04
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114865 --- Comment #2 from Peter Dimov --- The issue is also present for GCC 14 on Ubuntu 24.04: https://github.com/boostorg/uuid/actions/runs/8853249656/job/24313667955
[Bug libstdc++/114865] [13/14/15 Regression] std::atomic::compare_exchange_strong seems to hang under GCC 13 on Ubuntu 23.04
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114865 --- Comment #4 from Peter Dimov --- This https://raw.githubusercontent.com/boostorg/uuid/feature/gcc_pr_114865/test/test_gcc_pr114865.cpp exhibits the problem for me on GCC 13/14. I'm only seeing the hang with -std=c++11 -m32 in the CI run because this combination is tested first, but I believe it's independent of standard level and address model.
[Bug libstdc++/114865] [13/14/15 Regression] std::atomic::compare_exchange_strong seems to hang under GCC 13 on Ubuntu 23.04
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114865 --- Comment #8 from Peter Dimov --- (In reply to Andrew Pinski from comment #6) > No it is dependent on the standard level. C++11 fails but C++14, C++17 and > C++20 all pass. That's interesting because I see basically no difference in the generated code on CE between 11 and 14: --- "C++-x86-64 gcc 13.2-1 (1).asm" 2024-04-27 03:25:11.149385400 +0300 +++ "C++-x86-64 gcc 13.2-1.asm" 2024-04-27 03:24:59.207244400 +0300 @@ -76,10 +76,11 @@ jmp .L8 main: pushrbx +mov eax, 8738 mov ebx, 1024 sub rsp, 16 mov QWORD PTR [rsp], 0 -mov QWORD PTR [rsp+8], 8738 +mov WORD PTR [rsp+8], ax .L14: mov rdi, rsp callgenerate(std::atomic*) (https://godbolt.org/z/nexn5W4Ph)
[Bug libstdc++/114865] [13/14/15 Regression] std::atomic::compare_exchange_strong seems to hang under GCC 13 on Ubuntu 23.04
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114865 --- Comment #9 from Peter Dimov --- Oh, my mistake. C++14 does mov QWORD, and C++11 does mov WORD.
[Bug libstdc++/114865] [13/14/15 Regression] std::atomic::compare_exchange_strong seems to hang under GCC 13 for C++11
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114865 --- Comment #11 from Peter Dimov --- So, basically, C++14 and above initialize the padding of ``` std::atomic state{{ 0, 0x }}; ``` in `main` to zero, which masks the problem in `generate`. (The problem in `generate` still exists because the assembly is identical - it just doesn't trigger because the padding is zero. If we manually poke something nonzero into the padding, it would (ought to) still break.) Static variables work for the same reason - the padding is guaranteed zero.
[Bug libstdc++/114865] [13/14/15 Regression] std::atomic::compare_exchange_strong seems to hang under GCC 13 for C++11
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114865 --- Comment #13 from Peter Dimov --- (In reply to Andrew Pinski from comment #10) > #if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) > if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Tp>()) > __builtin_clear_padding(std::__addressof(_M_i)); > #endif > > So yes it is definitely dependent on C++ level ... > That is for C++14+ it is working correctly. Oh, that's the constructor of `atomic`. I thought it was the compiler initializing the padding in C++14 and above. I wonder why `__cplusplus >= 201402L` is here.
[Bug libstdc++/114865] [13/14/15 Regression] std::atomic::compare_exchange_strong seems to hang under GCC 13 for C++11
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114865 --- Comment #19 from Peter Dimov --- This should work. I still don't understand why JF so insisted on all these padding shenanigans.
[Bug c++/114986] New: Seemingly incorrect "ignoring packed attribute" warning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114986 Bug ID: 114986 Summary: Seemingly incorrect "ignoring packed attribute" warning Product: gcc Version: 14.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- The following program ``` #include #include struct uuid { std::uint8_t data[ 16 ] = {}; }; struct __attribute__((packed)) X { uuid a; unsigned char b; unsigned c; unsigned char d; }; static_assert( offsetof(X, c) == 17 ); static_assert( sizeof(X) == 22 ); ``` (https://godbolt.org/z/WvxjM3eqn) gives ``` :11:10: warning: ignoring packed attribute because of unpacked non-POD field 'uuid X::a' ``` However, the attribute is applied, because the static assertions pass. If `__attribute__((packed))` is removed, the assertions (correctly) fail (https://godbolt.org/z/hP4oG98fq). Therefore, the warning seems wrong. GCC 14, 13, 12 warn; 11 and earlier do not.
[Bug c++/109985] New: __builtin_prefetch ignored by GCC 12/13
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109985 Bug ID: 109985 Summary: __builtin_prefetch ignored by GCC 12/13 Product: gcc Version: 13.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- We are investigating a Boost.Unordered performance regression with GCC 12, on the following benchmark: https://github.com/boostorg/boost_unordered_benchmarks/blob/4c717baac1bff8d3e51cb8485b72bbb63d533265/scattered_lookup.cpp and it looks like the reason is that GCC 12 (and 13) ignore a call to `__builtin_prefetch`. While GCC 11 generates this: ``` .L108: mov r8, r12 movdqa xmm0, xmm1 sal r8, 4 lea r14, [r10+r8] pcmpeqb xmm0, XMMWORD PTR [r14] pmovmskbedx, xmm0 and edx, 32767 je .L104 sub r8, r12 sal r8, 4 add r8, QWORD PTR [rbx+32] prefetcht0 [r8] .L106: xor r15d, r15d rep bsf r15d, edx movsx r15, r15d sal r15, 4 add r15, r8 cmp rsi, QWORD PTR [r15] jne .L144 add r9, QWORD PTR [r15+8] mov rax, rdi cmp r11, rdi jne .L145 ``` (https://godbolt.org/z/d663fdM16 - prefetcht0 [r8] right before L106) GCC 12 generates this in the same function: ``` .L108: mov r8, r10 movdqa xmm0, xmm1 sal r8, 4 lea r9, [rbp+0+r8] pcmpeqb xmm0, XMMWORD PTR [r9] pmovmskbedx, xmm0 and edx, 32767 je .L104 mov rdi, QWORD PTR [rsp+16] sub r8, r10 mov QWORD PTR [rsp+24], rax sal r8, 4 mov rdi, QWORD PTR [rdi+32] mov QWORD PTR [rsp+8], rdi mov rax, rdi .L106: xor edi, edi rep bsf edi, edx movsx rdi, edi sal rdi, 4 add rdi, r8 add rdi, rax cmp r11, QWORD PTR [rdi] jne .L143 add rsi, 8 add rbx, QWORD PTR [rdi+8] cmp r12, rsi jne .L109 ``` (https://godbolt.org/z/T7csq7TPz - no prefetcht0 instruction before L106) Simplifying this code unfortunately leads to the prefetcht0 being generated.
[Bug target/110096] New: Would be nice if __builtin_ia32_pause had a portable equivalent as it's applicable to ARM
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110096 Bug ID: 110096 Summary: Would be nice if __builtin_ia32_pause had a portable equivalent as it's applicable to ARM Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- This is more of a feature request than a bug. Currently `__builtin_ia32_pause()` only applies to Intel/AMD CPUs (hence the `ia32` in the name), but it has a straightforward and equivalent meaning for ARM (issue a YIELD instruction, which is the exact ARM equivalent to the PAUSE x86 one.) This forces us to do things like ``` #if __has_builtin(__builtin_ia32_pause) __builtin_ia32_pause(); #elif defined(__GNUC__) && ( (defined(__ARM_ARCH) && __ARM_ARCH >= 8) || defined(__ARM_ARCH_8A__) || defined(__aarch64__) ) __asm__ __volatile__( "yield" : : : "memory" ); // ... ``` (E.g. https://github.com/boostorg/core/blob/3b96d237c0e3ada30c9beca0f60062a2576dcafd/include/boost/core/detail/sp_thread_pause.hpp) This can be solved in one of two ways; one, extend `__builtin_ia32_pause` to do the right thing for ARM - unprincipled because of ia32 in the name, but will automagically "fix" all code using `#if __has_builtin(__builtin_ia32_pause)`. Or two, add a portable spelling for the intrinsic, either `__builtin_pause()` or `__builtin_yield()`. (Failing that, an ARM-specific `__builtin_arm_yield()` would still be an improvement over the above because it at least will allow us to not hardcode the ARM target detection, which we are probably getting wrong.)
[Bug target/110096] Would be nice if __builtin_ia32_pause had a portable equivalent as it's applicable to ARM
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110096 --- Comment #3 from Peter Dimov --- How does the user know when to include `arm_acle.h`?
[Bug target/110096] Would be nice if __builtin_ia32_pause had a portable equivalent as it's applicable to ARM
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110096 --- Comment #5 from Peter Dimov --- This works for the specific case of ARM, even though I don't find it substantially better than just using `asm("yield")`, but the benefit of having a portable intrinsic for this functionality is that as such instructions are added to targets and GCC gains support of them (as has happened with ARM), code would automatically take advantage of them, without having to acquire new ifdefs for each supported target.
[Bug target/110096] Would be nice if __builtin_ia32_pause had a portable equivalent as it's applicable to ARM
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110096 --- Comment #7 from Peter Dimov --- These intrinsics are typically used in spinlocks as in ``` while( flag_.test_and_set() ) { // issue a power-saving NOP here } ``` (where `flag_` is `std::atomic_flag`) and this use is generic and not target-dependent.
[Bug target/110096] Would be nice if __builtin_ia32_pause had a portable equivalent as it's applicable to ARM
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110096 --- Comment #9 from Peter Dimov --- I don't think I want WFE here, based on what I read about it. Putting the core to sleep seems like something to do in an embedded system where I have full control of what cores do, not something to do on the application level, in a portable C++ library.
[Bug target/110096] Would be nice if __builtin_ia32_pause had a portable equivalent as it's applicable to ARM
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110096 --- Comment #13 from Peter Dimov --- Even if we assume that WFE on lock (and SEV on unlock) is the correct approach on ARM instead of YIELD (though this seems very much domain-specific, depending on the expected amount of contention and who knows what else), isn't the existence of pause/yield instructions on MIPS, POWER, and apparently RISC-V (*) enough further evidence in favor of having a portable intrinsic for emitting such an instruction? (*) https://doc.rust-lang.org/src/core/hint.rs.html#178-191 (implementation of https://doc.rust-lang.org/std/hint/fn.spin_loop.html)
[Bug c++/110476] New: constexpr floating point regression with -std=c++XX
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110476 Bug ID: 110476 Summary: constexpr floating point regression with -std=c++XX Product: gcc Version: 13.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- The following program #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) struct X { float f; }; int main() { constexpr X x{ 3.14f }; STATIC_ASSERT( x.f == 3.14f ); } fails under GCC 13/14 with : In function 'int main()': :11:24: error: static assertion failed: x.f == 3.14f 11 | STATIC_ASSERT( x.f == 3.14f ); |^~~~ :1:42: note: in definition of macro 'STATIC_ASSERT' 1 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) | ^~~ :11:24: note: the comparison reduces to '(3.1410490417480469e+0l == 3.141e+0l)' 11 | STATIC_ASSERT( x.f == 3.14f ); |^~~~ when compiled with -m32 -std=c++XX under x86 (https://godbolt.org/z/Ghs7j5Teq). The reason is that -std=c++XX implies -fexcess-precision=standard (https://godbolt.org/z/zx4rn4j5W). Previous versions worked fine.
[Bug c++/110477] New: -fexcess-precision=standard not applied consistently
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110477 Bug ID: 110477 Summary: -fexcess-precision=standard not applied consistently Product: gcc Version: 13.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- The following program float f( float x, int y ) { return x + y; } int main() { return f( 3.14f, 1 ) == 3.14f + 1; } returns different values with -std=c++XX (https://godbolt.org/z/8dK98ondM) and -std=gnu++XX (https://godbolt.org/z/4Y4qfsKzM) under GCC 13/14 -m32, because -fexcess-precision=standard is not consistently applied to both sides of the comparison. Under -fexcess-precision=fast (and hence under previous GCC versions), the comparison always succeeds because both sides use excess precision (https://godbolt.org/z/dzdoxdnM9). This is the runtime equivalent of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110476.
[Bug c++/110477] -fexcess-precision=standard not applied consistently
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110477 --- Comment #1 from Peter Dimov --- Looks like a duplicate of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108742 and is fixed by casting the rhs to (float), but any ordinary programmer would be baffled. For context, I encountered this regression in the Boost.Variant2 test suite when I added GCC 13 to CI.
[Bug c++/110476] constexpr floating point regression with -std=c++XX
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110476 --- Comment #1 from Peter Dimov --- As discussed in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108742, this is a consequence of applying the FLT_EVAL_METHOD=2 rules, and can be fixed by casting 3.14f to (float). That's... incredibly surprising, though. 3.14f is already a float. For context, I encountered this regression in the Boost.Variant2 test suite when I added GCC 13 to CI.
[Bug c++/110477] -fexcess-precision=standard not applied consistently
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110477 --- Comment #3 from Peter Dimov --- That's true, but the normal expectation of anyone using -fexcess-precision=standard would be for it to apply consistently everywhere (that is, as if FLT_EVAL_METHOD is 0.) Of course given that FLT_EVAL_METHOD is in a header, so unaffected by -f options, it's not clear what can be done here.
[Bug c++/110477] -fexcess-precision=standard not applied consistently
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110477 --- Comment #6 from Peter Dimov --- I suppose this is unfixable because there's all sorts of code assuming that the value of (long double)3.14 is 3.14L and not (long double)(double)3.14L. I doubt that anyone sane expects this from (long double)3.14F, but it's not feasible to change one but not the other. Bafflings will continue until morale improves.
[Bug target/108742] Incorrect constant folding with (or exposed by) -fexcess-precision=standard
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108742 --- Comment #13 from Peter Dimov --- I think that https://eel.is/c++draft/lex.fcon#3 disagrees. "If the scaled value is not in the range of representable values for its type, the program is ill-formed. Otherwise, the value of a floating-point-literal is the scaled value if representable, else the larger or smaller representable value nearest the scaled value, chosen in an implementation-defined manner." I don't see any license here for the value of 3.14f to be 3.14L.
[Bug c++/110477] -fexcess-precision=standard not applied consistently
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110477 --- Comment #8 from Peter Dimov --- As I commented on the duplicate bug, I don't think this behavior is allowed by https://eel.is/c++draft/lex.fcon#3. "If the scaled value is not in the range of representable values for its type, the program is ill-formed. Otherwise, the value of a floating-point-literal is the scaled value if representable, else the larger or smaller representable value nearest the scaled value, chosen in an implementation-defined manner." I don't see any license here for the value of 3.14f to be 3.14L.
[Bug c++/110476] constexpr floating point regression with -std=c++XX
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110476 --- Comment #2 from Peter Dimov --- Discussion of FLT_EVAL_METHOD notwithstanding, I think that this behavior is not allowed by https://eel.is/c++draft/lex.fcon#3. "If the scaled value is not in the range of representable values for its type, the program is ill-formed. Otherwise, the value of a floating-point-literal is the scaled value if representable, else the larger or smaller representable value nearest the scaled value, chosen in an implementation-defined manner." I don't see any license here for the value of 3.14f to be 3.14L.
[Bug c++/86355] [10 Regression] Internal compiler error with pack expansion and fold expression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86355 --- Comment #14 from Peter Dimov --- Should I open another bug for the failure to compile the original example?
[Bug libstdc++/113099] locale without RTTI uses dynamic_cast before gcc 13.2 or has ODR violation since gcc 13.2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113099 --- Comment #7 from Peter Dimov --- You don't necessarily need dynamic_cast because facets are always installed and obtained by their exact type, not via a reference to base. You can store the Facet* as given (like shared_ptr does), and return it. The only reason dynamic_cast is needed here is because you can't static_cast from facet* to Facet* when virtual inheritance. But you are not required to store facet* in the actual container; you can store the original Facet* as void*.
[Bug libstdc++/113099] locale without RTTI uses dynamic_cast before gcc 13.2 or has ODR violation since gcc 13.2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113099 --- Comment #10 from Peter Dimov --- Maybe the right thing to do is to use dynamic_cast only for virtual inheritance (either have a trait or check whether static_cast isn't a valid expression), otherwise static_cast, in both cases (standard and user-defined Facet.)
[Bug libstdc++/113200] New: std::char_traits::move is not constexpr when the argument is a string literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113200 Bug ID: 113200 Summary: std::char_traits::move is not constexpr when the argument is a string literal Product: gcc Version: 13.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- ``` #include #include template struct S { char data_[ N ]; using traits_type = std::char_traits; constexpr S( char const* p ): data_{} { std::size_t n = traits_type::length( p ); assert( n < N ); traits_type::move( data_, p, n + 1 ); } }; template S( char const(&)[N] ) -> S; constexpr S s( "test" ); ``` (https://godbolt.org/z/PofY8MP6G) fails with ``` In file included from /opt/compiler-explorer/gcc-trunk-20240102/include/c++/14.0.0/string:42, from :1: :22:23: in 'constexpr' expansion of 'S<5>(((const char*)"test"))' :16:26: in 'constexpr' expansion of 'std::char_traits::move(((char*)(&((S<5>*)this)->S<5>::data_)), p, (n + 1))' /opt/compiler-explorer/gcc-trunk-20240102/include/c++/14.0.0/bits/char_traits.h:423:50: in 'constexpr' expansion of '__gnu_cxx::char_traits::move(__s1, __s2, __n)' /opt/compiler-explorer/gcc-trunk-20240102/include/c++/14.0.0/bits/char_traits.h:230:20: error: '(((const __gnu_cxx::char_traits::char_type*)(& s.S<5>::data_)) == ((const char*)"test"))' is not a constant expression 230 | if (__s1 == __s2) // unlikely, but saves a lot of work | ~^~~ ``` (Reduced from a similar failure in Boost.StaticString.)
[Bug libstdc++/113200] std::char_traits::move is not constexpr when the argument is a string literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113200 --- Comment #3 from Peter Dimov --- I think that the compiler is correct; string literal address comparisons aren't constant expressions. Clang gives the same error: https://godbolt.org/z/xPWEf4z63.
[Bug libstdc++/113200] std::char_traits::move is not constexpr when the argument is a string literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113200 --- Comment #4 from Peter Dimov --- I didn't notice your subsequent comment, sorry. :-)
[Bug c++/113256] New: False -Wdangling-reference positive
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113256 Bug ID: 113256 Summary: False -Wdangling-reference positive Product: gcc Version: 13.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pdimov at gmail dot com Target Milestone: --- The following code ``` #include #include template auto bind( M T::* pm, A a ) { return [=]( auto&& x ) -> M const& { return x.*pm; }; } template struct arg {}; arg<1> _1; int main() { std::pair pair; int const& x = bind( &std::pair::first, _1 )( pair ); assert( &x == &pair.first ); } ``` (https://godbolt.org/z/a555MMTqo) (reduced from a Boost.Bind test case) causes ``` :16:16: warning: possibly dangling reference to a temporary [-Wdangling-reference] 16 | int const& x = bind( &std::pair::first, _1 )( pair ); |^ ``` with GCC 13.2 (but not trunk). There are indeed two temporaries created in that full expression, but `int const&` can't possibly bind to any of them.
[Bug libstdc++/111053] std::ranges::copy is missing important optimizations
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111053 Peter Dimov changed: What|Removed |Added CC||pdimov at gmail dot com --- Comment #2 from Peter Dimov --- Now I wonder whether replacing `std::ranges::copy(r, std::back_inserter(c))` with `c.append_range(r)` is an allowed optimization, all things considered. Unrelated to the above, one additional special case which `std::copy` has and `std::ranges::copy` doesn't is dedicated support for contiguous iterators, as pointed out in bug 118647.
[Bug libstdc++/114865] [13/14/15 Regression] std::atomic::compare_exchange_strong seems to hang under GCC 13 for C++11
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114865 --- Comment #24 from Peter Dimov --- I already have https://github.com/boostorg/uuid/blob/e7f4cebe81835fd1b5558178f3d4c40ae266d8e2/include/boost/uuid/time_generator_v1.hpp#L32-L43 but this comes with its own issues (-Wmissing-field-initializers.) Do you think that it's worth trying to roll back this in the standard? Probably not because it's only a problem on C++11 and the standard doesn't care about C++11 at this point.