Age | Commit message (Collapse) | Author | Files | Lines |
|
The methods layout_{left,right}::mapping::stride are defined
as
\prod_{i = 0}^r E[i]
\prod_{i = r+1}^n E[i]
This is computed as the product of a precomputed static product and the
product of the required dynamic extents.
Disassembly shows that even for low-rank extents, i.e. rank == 1 and
rank == 2, with at least one dynamic extent, the generated code loads
two values; and then runs the loop over at most one element, e.g. for
stride_left_d5 defined below the generated code is:
220: 48 8b 04 f5 00 00 00 mov rax,QWORD PTR [rsi*8+0x0]
227: 00
228: 31 d2 xor edx,edx
22a: 48 85 c0 test rax,rax
22d: 74 23 je 252 <stride_left_d5+0x32>
22f: 48 8b 0c f5 00 00 00 mov rcx,QWORD PTR [rsi*8+0x0]
236: 00
237: 48 c1 e1 02 shl rcx,0x2
23b: 74 13 je 250 <stride_left_d5+0x30>
23d: 48 01 f9 add rcx,rdi
240: 48 63 17 movsxd rdx,DWORD PTR [rdi]
243: 48 83 c7 04 add rdi,0x4
247: 48 0f af c2 imul rax,rdx
24b: 48 39 f9 cmp rcx,rdi
24e: 75 f0 jne 240 <stride_left_d5+0x20>
250: 89 c2 mov edx,eax
252: 89 d0 mov eax,edx
254: c3 ret
If there's no dynamic extents, it simply loads the precomputed product
of static extents.
For rank == 1 the answer is the constant `1`; for rank == 2 it's either 1 or
extents.extent(k), with k == 0 for layout_left and k == 1 for
layout_right.
Consider,
using Ed = std::extents<int, dyn>;
int stride_left_d(const std::layout_left::mapping<Ed>& m, size_t r)
{ return m.stride(r); }
using E3d = std::extents<int, 3, dyn>;
int stride_left_3d(const std::layout_left::mapping<E3d>& m, size_t r)
{ return m.stride(r); }
using Ed5 = std::extents<int, dyn, 5>;
int stride_left_d5(const std::layout_left::mapping<Ed5>& m, size_t r)
{ return m.stride(r); }
The optimized code for these three cases is:
0000000000000060 <stride_left_d>:
60: b8 01 00 00 00 mov eax,0x1
65: c3 ret
0000000000000090 <stride_left_3d>:
90: 48 83 fe 01 cmp rsi,0x1
94: 19 c0 sbb eax,eax
96: 83 e0 fe and eax,0xfffffffe
99: 83 c0 03 add eax,0x3
9c: c3 ret
00000000000000a0 <stride_left_d5>:
a0: b8 01 00 00 00 mov eax,0x1
a5: 48 85 f6 test rsi,rsi
a8: 74 02 je ac <stride_left_d5+0xc>
aa: 8b 07 mov eax,DWORD PTR [rdi]
ac: c3 ret
For rank == 1 it simply returns 1 (as expected). For rank == 2, it
either implements a branchless formula, or conditionally loads one
value. In all cases involving a dynamic extent this seems like it's
always doing clearly less work, both in terms of computation and loads.
In cases not involving a dynamic extent, it replaces loading one value
with a branchless sequence of four instructions.
This commit also refactors __size to no use any of the precomputed
arrays. This prevents instantiating __{fwd,rev}_partial_prods for
low-rank extents. This results in a further size reduction of a
reference object file (described two commits prior) by 9% from 46.0kB to
41.9kB.
In a prior commit we optimized __size to produce better object code by
precomputing the static products. This refactor enables the optimizer to
generate the same optimized code.
libstdc++-v3/ChangeLog:
* include/std/mdspan (__mdspan::__fwd_prod): Optimize
for rank <= 2.
(__mdspan::__rev_prod): Ditto.
(__mdspan::__size): Refactor to use a pre-computed product, not
a partial product.
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
|
|
Let E denote an multi-dimensional extent; n the rank of E; r = 0, ...,
n; E[i] the i-th extent; and D[k] be the (possibly empty) array of
dynamic extents.
The two partial products for r = 0, ..., n:
\prod_{i = 0}^r E[i] (fwd)
\prod_{i = r+1}^n E[i] (rev)
can be computed as the product of static and dynamic extents. The static
fwd and rev product can be computed at compile time for all values of r.
Three methods are directly affected by this optimization:
layout_left::mapping::stride
layout_right::mapping::stride
mdspan::size
We'll check the generated code (-O2) for all three methods for a generic
(artificially) high-dimensional multi-dimensional extents.
Consider a generic case:
using Extents = std::extents<int, 3, 5, dyn, dyn, dyn, 7, dyn>;
int stride_left(const std::layout_left::mapping<Extents>& m, size_t r)
{ return m.stride(r); }
The code generated prior to this commit:
4f0: 66 0f 6f 05 00 00 00 movdqa xmm0,XMMWORD PTR [rip+0x0] # 4f8
4f7: 00
4f8: 48 83 c6 01 add rsi,0x1
4fc: 48 c7 44 24 e8 ff ff mov QWORD PTR [rsp-0x18],0xffffffffffffffff
503: ff ff
505: 48 8d 04 f5 00 00 00 lea rax,[rsi*8+0x0]
50c: 00
50d: 0f 29 44 24 b8 movaps XMMWORD PTR [rsp-0x48],xmm0
512: 66 0f 76 c0 pcmpeqd xmm0,xmm0
516: 0f 29 44 24 c8 movaps XMMWORD PTR [rsp-0x38],xmm0
51b: 66 0f 6f 05 00 00 00 movdqa xmm0,XMMWORD PTR [rip+0x0] # 523
522: 00
523: 0f 29 44 24 d8 movaps XMMWORD PTR [rsp-0x28],xmm0
528: 48 83 f8 38 cmp rax,0x38
52c: 74 72 je 5a0 <stride_right_E1+0xb0>
52e: 48 8d 54 04 b8 lea rdx,[rsp+rax*1-0x48]
533: 4c 8d 4c 24 f0 lea r9,[rsp-0x10]
538: b8 01 00 00 00 mov eax,0x1
53d: 0f 1f 00 nop DWORD PTR [rax]
540: 48 8b 0a mov rcx,QWORD PTR [rdx]
543: 49 89 c0 mov r8,rax
546: 4c 0f af c1 imul r8,rcx
54a: 48 83 f9 ff cmp rcx,0xffffffffffffffff
54e: 49 0f 45 c0 cmovne rax,r8
552: 48 83 c2 08 add rdx,0x8
556: 49 39 d1 cmp r9,rdx
559: 75 e5 jne 540 <stride_right_E1+0x50>
55b: 48 85 c0 test rax,rax
55e: 74 38 je 598 <stride_right_E1+0xa8>
560: 48 8b 14 f5 00 00 00 mov rdx,QWORD PTR [rsi*8+0x0]
567: 00
568: 48 c1 e2 02 shl rdx,0x2
56c: 48 83 fa 10 cmp rdx,0x10
570: 74 1e je 590 <stride_right_E1+0xa0>
572: 48 8d 4f 10 lea rcx,[rdi+0x10]
576: 48 01 d7 add rdi,rdx
579: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
580: 48 63 17 movsxd rdx,DWORD PTR [rdi]
583: 48 83 c7 04 add rdi,0x4
587: 48 0f af c2 imul rax,rdx
58b: 48 39 f9 cmp rcx,rdi
58e: 75 f0 jne 580 <stride_right_E1+0x90>
590: c3 ret
591: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
598: c3 ret
599: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
5a0: b8 01 00 00 00 mov eax,0x1
5a5: eb b9 jmp 560 <stride_right_E1+0x70>
5a7: 66 0f 1f 84 00 00 00 nop WORD PTR [rax+rax*1+0x0]
5ae: 00 00
which seems to be performing:
preparatory_work();
ret = 1
for(i = 0; i < rank; ++i)
tmp = ret * E[i]
if E[i] != -1
ret = tmp
for(i = 0; i < rank_dynamic; ++i)
ret *= D[i]
This commit reduces it down to:
270: 48 8b 04 f5 00 00 00 mov rax,QWORD PTR [rsi*8+0x0]
277: 00
278: 31 d2 xor edx,edx
27a: 48 85 c0 test rax,rax
27d: 74 33 je 2b2 <stride_right_E1+0x42>
27f: 48 8b 14 f5 00 00 00 mov rdx,QWORD PTR [rsi*8+0x0]
286: 00
287: 48 c1 e2 02 shl rdx,0x2
28b: 48 83 fa 10 cmp rdx,0x10
28f: 74 1f je 2b0 <stride_right_E1+0x40>
291: 48 8d 4f 10 lea rcx,[rdi+0x10]
295: 48 01 d7 add rdi,rdx
298: 0f 1f 84 00 00 00 00 nop DWORD PTR [rax+rax*1+0x0]
29f: 00
2a0: 48 63 17 movsxd rdx,DWORD PTR [rdi]
2a3: 48 83 c7 04 add rdi,0x4
2a7: 48 0f af c2 imul rax,rdx
2ab: 48 39 f9 cmp rcx,rdi
2ae: 75 f0 jne 2a0 <stride_right_E1+0x30>
2b0: 89 c2 mov edx,eax
2b2: 89 d0 mov eax,edx
2b4: c3 ret
Loosely speaking this does the following:
1. Load the starting position k in the array of dynamic extents; and
return if possible.
2. Load the partial product of static extents.
3. Computes the \prod_{i = k}^d D[i] where d is the number of
dynamic extents in a loop.
It shows that the span used for passing in the dynamic extents is
completely eliminated; and the fact that the product always runs to the
end of the array of dynamic extents is used by the compiler to eliminate
one indirection to determine the end position in the array of dynamic
extents.
The analogous code is generated for layout_left.
Next, consider
using E2 = std::extents<int, 3, 5, dyn, dyn, 7, dyn, 11>;
int size2(const std::mdspan<double, E2>& md)
{ return md.size(); }
on immediately preceding commit the generated code is
10: 66 0f 6f 05 00 00 00 movdqa xmm0,XMMWORD PTR [rip+0x0] # 18
17: 00
18: 49 89 f8 mov r8,rdi
1b: 48 8d 44 24 b8 lea rax,[rsp-0x48]
20: 48 c7 44 24 e8 0b 00 mov QWORD PTR [rsp-0x18],0xb
27: 00 00
29: 48 8d 7c 24 f0 lea rdi,[rsp-0x10]
2e: ba 01 00 00 00 mov edx,0x1
33: 0f 29 44 24 b8 movaps XMMWORD PTR [rsp-0x48],xmm0
38: 66 0f 76 c0 pcmpeqd xmm0,xmm0
3c: 0f 29 44 24 c8 movaps XMMWORD PTR [rsp-0x38],xmm0
41: 66 0f 6f 05 00 00 00 movdqa xmm0,XMMWORD PTR [rip+0x0] # 49
48: 00
49: 0f 29 44 24 d8 movaps XMMWORD PTR [rsp-0x28],xmm0
4e: 66 66 2e 0f 1f 84 00 data16 cs nop WORD PTR [rax+rax*1+0x0]
55: 00 00 00 00
59: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
60: 48 8b 08 mov rcx,QWORD PTR [rax]
63: 48 89 d6 mov rsi,rdx
66: 48 0f af f1 imul rsi,rcx
6a: 48 83 f9 ff cmp rcx,0xffffffffffffffff
6e: 48 0f 45 d6 cmovne rdx,rsi
72: 48 83 c0 08 add rax,0x8
76: 48 39 c7 cmp rdi,rax
79: 75 e5 jne 60 <size2+0x50>
7b: 48 85 d2 test rdx,rdx
7e: 74 18 je 98 <size2+0x88>
80: 49 63 00 movsxd rax,DWORD PTR [r8]
83: 49 63 48 04 movsxd rcx,DWORD PTR [r8+0x4]
87: 48 0f af c1 imul rax,rcx
8b: 41 0f af 40 08 imul eax,DWORD PTR [r8+0x8]
90: 0f af c2 imul eax,edx
93: c3 ret
94: 0f 1f 40 00 nop DWORD PTR [rax+0x0]
98: 31 c0 xor eax,eax
9a: c3 ret
which is needlessly long. The current commit reduces it down to:
10: 48 63 07 movsxd rax,DWORD PTR [rdi]
13: 48 63 57 04 movsxd rdx,DWORD PTR [rdi+0x4]
17: 48 0f af c2 imul rax,rdx
1b: 0f af 47 08 imul eax,DWORD PTR [rdi+0x8]
1f: 69 c0 83 04 00 00 imul eax,eax,0x483
25: c3 ret
Which simply computes the product:
D[0] * D[1] * D[2] * const
where const is the product of all static extents. Meaning the loop to
compute the product of dynamic extents has been fully unrolled and
all constants are perfectly precomputed.
The size of the object file described in the previous commit reduces
by 17% from 55.8kB to 46.0kB.
libstdc++-v3/ChangeLog:
* include/std/mdspan (__mdspan::__static_prod): New function.
(__mdspan::__fwd_partial_prods): Constexpr array of partial
forward products.
(__mdspan::__fwd_partial_prods): Same for reverse partial
products.
(__mdspan::__static_extents_prod): Delete function.
(__mdspan::__extents_prod): Renamed from __exts_prod and refactored.
include/std/mdspan (__mdspan::__fwd_prod): Compute as the
product of pre-computed static static and the product of dynamic
extents.
(__mdspan::__rev_prod): Ditto.
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
|
|
In mdspan related code involving static extents, often the IndexType is
part of the template parameters, even though it's not needed.
This commit extracts the parts of _ExtentsStorage not related to
IndexType into a separate class _StaticExtents.
It also prefers passing the array of static extents, instead of the
whole extents object where possible.
The size of an object file compiled with -O2 that instantiates
Layout::mapping<extents<IndexType, Indices...>::stride
Layout::mapping<extents<IndexType, Indices...>::required_span_size
for the product of
- eight IndexTypes
- three Layouts,
- nine choices of Indices...
decreases by 19% from 69.2kB to 55.8kB.
libstdc++-v3/ChangeLog:
* include/std/mdspan (__mdspan::_StaticExtents): Extract non IndexType
related code from _ExtentsStorage.
(__mdspan::_ExtentsStorage): Use _StaticExtents.
(__mdspan::__static_extents): Return reference to NTTP of _StaticExtents.
(__mdspan::__contains_zero): New overload.
(__mdspan::__exts_prod, __mdspan::__static_quotient): Use span to avoid
copying __sta_exts.
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
|
|
|
|
[PR104874]
The test call was accidentally omitted in r16-2484-gdc49c0a46ec96e,
a commit that refactored this test file. This patch adds it back.
PR libstdc++/104874
libstdc++-v3/ChangeLog:
* testsuite/24_iterators/random_access/string_vector_iterators.cc:
Call test6642.
|
|
|
|
This patch adds the [[nodiscard]] attribute to the operator() of ranges
algorithm function objects if their std counterpart has it.
Furthermore, we [[nodiscard]] the operator() of the following ranges
algorithms that lack a std counterpart:
* find_last, find_last_if, find_last_if_not (to match other find
algorithms)
* contains, contains_subrange (to match find/any_of and search)
Finally, [[nodiscard]] is added to std::min and std::max overloads
that accept std::initializer_list. This appears to be an oversight,
as std::minmax is already marked, and other min overloads are as well.
The same applies to corresponding operator() overloads of ranges::min and
ranges::max.
PR libstdc++/121476
libstdc++-v3/ChangeLog:
* include/bits/ranges_algo.h (__all_of_fn::operator()):
(__any_of_fn::operator(), __none_of_fn::operator())
(__find_first_of_fn::operator(), __count_fn::operator())
(__find_end_fn::operator(), __remove_if_fn::operator())
(__remove_fn::operator(), __unique_fn::operator())
(__is_sorted_until_fn::operator(), __is_sorted_fn::operator())
(__lower_bound_fn::operator(), __upper_bound_fn::operator())
(__equal_range_fn::operator(), __binary_search_fn::operator())
(__is_partitioned_fn::operator(), __partition_point_fn::operator())
(__minmax_fn::operator(), __min_element_fn::operator())
(__includes_fn::operator(), __max_fn::operator())
(__lexicographical_compare_fn::operator(), __clamp__fn::operator())
(__find_last_fn::operator(), __find_last_if_fn::operator())
(__find_last_if_not_fn::operator()): Add [[nodiscard]] attribute.
* include/bits/ranges_algobase.h (__equal_fn::operator()):
Add [[nodiscard]] attribute.
* include/bits/ranges_util.h (__find_fn::operator())
(__find_if_fn::operator(), __find_if_not_fn::operator())
(__mismatch_fn::operator(), __search_fn::operator())
(__min_fn::operator(), __adjacent_find_fn::operator()):
Add [[nodiscard]] attribute.
* include/bits/stl_algo.h (std::min(initializer_list<T>))
(std::min(initializer_list<T>, _Compare))
(std::max(initializer_list<T>))
(std::mmax(initializer_list<T>, _Compare)): Add _GLIBCXX_NODISCARD.
* testsuite/25_algorithms/min/constrained.cc: Silence nodiscard
warning.
* testsuite/25_algorithms/max/constrained.cc: Likewise.
* testsuite/25_algorithms/minmax/constrained.cc: Likewise.
* testsuite/25_algorithms/minmax_element/constrained.cc: Likewise.
|
|
[PR121313]
For __n == 0, the elements were self move-assigned by
std::move_backward(__ins, __old_finish - __n, __old_finish).
PR libstdc++/121313
libstdc++-v3/ChangeLog:
* include/bits/vector.tcc (vector::insert_range): Add check for
empty size.
* testsuite/23_containers/vector/modifiers/insert/insert_range.cc:
New tests.
|
|
|
|
Regenerate configure files after
commit 8a3ad190c14789cde0b03142760b14b5675e8b39
Author: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Date: Sun Aug 10 08:33:30 2025 -0600
config: Handle dash in library name for AC_LIB_LINKAGEFLAGS_BODY
gcc/
* configure: Regenerated.
libcpp/
* configure: Regenerated.
libgcobol/
* configure: Regenerated.
libstdc++-v3/
* configure: Regenerated.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
|
|
|
|
libstdc++-v3:
* doc/xml/manual/build_hacking.xml: Switch gcc.gnu.org installation
docs to https.
* doc/html/manual/appendix_porting.html: Regenerate.
|
|
|
|
On Mon, Aug 04, 2025 at 11:33:17AM -0400, Patrick Palka wrote:
> > @@ -1693,6 +1697,8 @@ export namespace std
> > {
> > using std::ranges::advance;
> > using std::ranges::distance;
> > + using std::ranges::iter_move;
> > + using std::ranges::iter_swap;
>
> Actually a few lines above we already do:
>
> // _Cpo is an implementation detail we can't avoid exposing; if we do the
> // using in ranges directly, it conflicts with any friend functions of the
> // same name, which is why the customization points are in an inline
> // namespace in the first place.
> namespace ranges::inline _Cpo
> {
> using _Cpo::iter_move;
> using _Cpo::iter_swap;
> }
>
> So I think we don't want to export iter_move and iter_swap directly... Sorry
> for not catching this sooner :/
Here is a patch which does that.
2025-08-05 Jakub Jelinek <jakub@redhat.com>
PR libstdc++/121373
* src/c++23/std.cc.in (std::ranges::iter_move, std::ranges::iter_swap):
Remove exports.
|
|
|
|
On Sat, Aug 02, 2025 at 09:05:07PM +0200, Jakub Jelinek wrote:
> Wonder how to automatically discover other missing exports (like in PR121373
> std::byteswap), maybe one could dig that stuff somehow from the raw
> dump (look for identifiers in std namespace (and perhaps inlined namespaces
> thereof at least) which don't start with underscore.
To answer that question, I wrote a simple plugin which just dumps the names
(which do not start with underscore) in std namespace (and its inlined
namespaces) and for non-inline namespaces in there which do not start with
underscore also recurses on those namespaces.
Plugin source in
https://gcc.gnu.org/pipermail/libstdc++/2025-August/062859.html
I went through it all now, using cppreference as a quick check for stuff
removed in C++17/C++20 and for everything added verified it is in
corresponding eel.is/c++-draft/*.syn etc. and looked it up in the libstdc++
headers for guarding macros.
After all the additions I've compiled std.cc with -std=c++20, -std=c++23 and
-std=c++26, the first one revealed std::ranges::shift_{left,right} emitted an
error in that case, the patch fixes that too.
2025-08-04 Jakub Jelinek <jakub@redhat.com>
hexne <printfne@gmail.com>
PR libstdc++/121373
* src/c++23/std.cc.in (std::ranges::shift_left,
std::ranges::shift_right): Only export for C++23 and later.
(std::ranges::fold_left_first_with_iter_result,
std::ranges::fold_left_with_iter_result): Export.
(std::byteswap): Export for C++23 and later.
(std::ranges::iter_move, std::ranges::iter_swap): Export.
(std::projected_value_t): Export for C++26 and later.
(std::out_ptr_t, std::inout_ptr_t): Export.
(std::ranges::iota_result): Export.
(std::regex_constants): Export a lot of constants.
(std::is_scoped_enum, std::is_scoped_enum_v): Export.
|
|
Forr rvalues the _Self parameter deduces a non-reference type. Consequently,
((_Self)__self) moved the object to a temporary, which then destroyed on
function exit.
This patch fixes this by using a C-style cast __self to (const indirect&).
This not only resolves the above issue but also correctly handles types that
are derived (publicly and privately) from indirect. Allocator requirements in
[allocator.requirements.general] p22 guarantee that dereferencing const _M_objp
works with equivalent semantics to dereferencing _M_objp.
PR libstdc++/121128
libstdc++-v3/ChangeLog:
* include/bits/indirect.h (indirect::operator*):
Cast __self to approparietly qualified indirect.
* testsuite/std/memory/indirect/access.cc: New test.
* testsuite/std/memory/polymorphic/access.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
|
|
|
|
I've tried compiling
#include <bits/stdc++.h>
with -std=c++26 -fdump-lang-all
and
for i in `grep ^Class.std::[^_] *.C.001l.class | sed 's/^Class //;s/[< ].*$//' | sort -u | grep -v ::.*::`; do grep -q $i /usr/src/gcc/libstdc++-v3/src/c++23/std.cc.in || echo $i;
+done
This printed
std::auto_ptr
std::binary_function
std::owner_equal
std::owner_hash
std::unary_function
where auto_ptr, binary_function and unary_function have been removed in earlier
versions of C++ and owner_equal and owner_hash are missing.
The following patch adds them.
Wonder how to automatically discover other missing exports (like in PR121373
std::byteswap), maybe one could dig that stuff somehow from the raw
dump (look for identifiers in std namespace (and perhaps inlined namespaces
thereof at least) which don't start with underscore.
2025-08-03 Jakub Jelinek <jakub@redhat.com>
* src/c++23/std.cc.in (std::owner_equal, std::owner_hash): Export.
|
|
|
|
When !_GLIBCXX_USE_DUAL_ABI the old COW std::string implementation is being used
which do not generate the expected error diagnostics.
libstdc++-v3/ChangeLog:
* testsuite/std/time/format/data_not_present_neg.cc: Remove _GLIBCXX_USE_DUAL_ABI
check.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
|
|
|
|
This adderess TODO from the test file.
libstdc++-v3/ChangeLog:
* testsuite/std/format/ranges/format_kind.cc: New test.
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
|
|
|
|
When the C++98 std::distance and std::advance functions (and C++11
std::next and std::prev) are used with C++20 iterators there can be
unexpected results, ranging from compilation failure to decreased
performance to undefined behaviour.
An iterator which satisfies std::input_iterator but does not meet the
Cpp17InputIterator requirements might have std::output_iterator_tag for
its std::iterator_traits<I>::iterator_category, which means it currently
cannot be used with std::advance at all. However, the implementation of
std::advance for a Cpp17InputIterator doesn't do anything that isn't
valid for iterator types satsifying C++20 std::input_iterator.
Similarly, a type satisfying C++20 std::bidirectional_iterator might be
usable with std::prev, if it weren't for the fact that its C++17
iterator_category is std::input_iterator_tag.
Finally, a type satisfying C++20 std::random_access_iterator might use a
slower implementation for std::distance or std::advance if its C++17
iterator_category is not std::random_access_iterator_tag.
This commit adds a __promotable_iterator concept to detect C++20
iterators which explicitly define an iterator_concept member, and which
either have no iterator_category, or their iterator_category is weaker
than their iterator_concept. This is used by std::distance and
std::advance to detect iterators which should dispatch based on their
iterator_concept instead of their iterator_category. This means that
those functions just work and do the right thing for C++20 iterators
which would otherwise fail to compile or have suboptimal performance.
This is related to LWG 3197, which considers making it undefined to use
std::prev with types which do not meet the Cpp17BidirectionalIterator
requirements. I think making it work, as in this commit, is a better
solution than banning it (or rejecting it at compile-time as libc++
does).
PR libstdc++/102181
libstdc++-v3/ChangeLog:
* include/bits/stl_iterator_base_funcs.h (distance, advance):
Check C++20 iterator concepts and handle appropriately.
(__detail::__iter_category_converts_to_concept): New concept.
(__detail::__promotable_iterator): New concept.
* testsuite/24_iterators/operations/cxx20_iterators.cc: New
test.
Reviewed-by: Patrick Palka <ppalka@redhat.com>
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
|
|
This adds the new bitset constructor from string_view
defined in P2697 to the debug version of the type.
libstdc++-v3/Changelog:
PR libstdc++/119742
* include/debug/bitset: Add new ctor.
|
|
libstdc++-v3/ChangeLog:
* include/std/mdspan: Small stylistic adjustments.
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
|
|
Versions 1, 2 and 3 of the patch for adding aligned_accessor had a
bug in the constraints that allowed conversion of
aligned_accessor<T, N> a = aligned_accessor<const T, N>{};
and prevented the reverse.
The file mdspan/accessors/generic.cc already contains code that checks
all variation of the constraint. This commit allows passing in two
different accessors. Enabling it to be reused more widely.
libstdc++-v3/ChangeLog:
* testsuite/23_containers/mdspan/accessors/generic.cc: Refactor
test_ctor.
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
|
|
[PR121196]
PR libstdc++/121196
libstdc++-v3/ChangeLog:
* include/std/inplace_vector (std::erase): Provide default argument
for _Up parameter.
* testsuite/23_containers/inplace_vector/erasure.cc: Add test for
using braces-init-list as arguments to erase_if and use function
to verify content of inplace_vector
Reviewed-by: Patrick Palka <ppalka@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
|
|
|
|
The unordered_map header incorrectly refers to a non-existent template parameter
_Value in default template argument descriptions. They should refer to _Key instead.
This patch fixes these descriptions to match the actual template parameters.
libstdc++-v3/ChangeLog:
* include/bits/unordered_map.h: Rectify referencing of
non-existent type.
|
|
|
|
[PR117294]
Currently, concept failures of standard type traits just report
'expression X<T> evaluates to false'. However, many type traits are
actually defined in terms of compiler builtins; we can do better here.
For instance, 'is_constructible_v' could go on to explain why the type
is not constructible, or 'is_invocable_v' could list potential
candidates.
Apart from concept diagnostics, this is also useful when using such
traits in a 'static_assert' directly, so this patch also adjusts the
diagnostics in that context.
As a first step to supporting that we need to be able to map the
standard type traits to the builtins that they use. Rather than adding
another list that would need to be kept up-to-date whenever a builtin is
added, this patch instead tries to detect any variable template defined
directly in terms of a TRAIT_EXPR.
This patch also adjusts 'diagnose_trait_expr' to provide more helpful
diagnostics for these cases. Not all type traits have yet been updated,
this patch just updates those that seem particularly valuable or
straight-forward. The function also gets moved to cp/semantics.cc to be
closer to 'trait_expr_value'.
Various other parts of the compiler are also adjusted here to assist in
making clear diagnostics, such as making more use of 'is_stub_object' to
refer to a type directly rather than in terms of 'std::declval<T>()'.
Additionally, since there are now more cases of nesting within a
'static_assert'ion I felt it was helpful for the experimental-nesting
mode to nest here as well.
PR c++/117294
PR c++/113854
gcc/cp/ChangeLog:
* call.cc (implicit_conversion_error): Hide label when printing
a stub object.
(convert_like_internal): Likewise, and nest candidate
diagnostics.
* constexpr.cc (diagnose_failing_condition): Nest diagnostics,
attempt to provide more helpful diagnostics for traits.
* constraint.cc (satisfy_atom): Pass result before constant
evaluation to diagnose_atomic_constraint.
(diagnose_trait_expr): Adjust diagnostics for clarity and
detail.
(maybe_diagnose_standard_trait): New function.
(diagnose_atomic_constraint): Attempt to provide more helpful
diagnostics for more traits.
* cp-tree.h (explain_not_noexcept): Declare new function.
(is_trivially_xible): Add parameter.
(is_nothrow_xible): Likewise.
(is_xible): Likewise.
(is_convertible): Likewise.
(is_nothrow_convertible): Likewise.
(diagnose_trait_expr): Declare new function.
(maybe_diagnose_standard_trait): Declare new function.
* error.cc (dump_type) <case TREE_VEC>: Handle trait types.
* except.cc (explain_not_noexcept): New function.
* method.cc (build_trait_object): Add complain parameter.
(build_invoke): Propagate complain parameter.
(assignable_expr): Add explain parameter to show diagnostics.
(constructible_expr): Likewise.
(destructible_expr): Likewise.
(is_xible_helper): Replace trivial flag with explain flag,
add diagnostics.
(is_trivially_xible): New explain flag.
(is_nothrow_xible): Likewise.
(is_xible): Likewise.
(is_convertible_helper): Add complain flag.
(is_convertible): New explain flag.
(is_nothrow_convertible): Likewise.
* typeck.cc (cp_build_function_call_vec): Add handling for stub
objects.
(convert_arguments): Always return -1 on error.
* typeck2.cc (cxx_readonly_error): Add handling for stub
objects.
libstdc++-v3/ChangeLog:
* testsuite/20_util/any/misc/any_cast_neg.cc: Adjust
diagnostics.
* testsuite/20_util/expected/illformed_neg.cc: Likewise.
* testsuite/20_util/optional/monadic/or_else_neg.cc: Likewise.
* testsuite/23_containers/array/creation/3_neg.cc: Likewise.
* testsuite/24_iterators/range_generators/lwg3900.cc: Likewise.
* testsuite/29_atomics/atomic/requirements/types_neg.cc:
Likewise.
* testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc:
Likewise.
* testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc:
Likewise.
* testsuite/std/format/arguments/args_neg.cc: Likewise.
* testsuite/std/format/string_neg.cc: Likewise.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-traits3.C: Adjust diagnostics.
* g++.dg/cpp2a/concepts-traits4.C: New test.
* g++.dg/diagnostic/static_assert5.C: New test.
* g++.dg/ext/has_virtual_destructor2.C: New test.
* g++.dg/ext/is_assignable2.C: New test.
* g++.dg/ext/is_constructible9.C: New test.
* g++.dg/ext/is_convertible7.C: New test.
* g++.dg/ext/is_destructible3.C: New test.
* g++.dg/ext/is_invocable6.C: New test.
* g++.dg/ext/is_virtual_base_of_diagnostic2.C: New test.
Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
Reviewed-by: Patrick Palka <ppalka@redhat.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
|
|
Removed the wrong_stuff() function, which was effectively empty for
actual test runs. Replaced the manual failure counter with the VERIFY
macro to simplify identifying failures.
PR libstdc++/104874
libstdc++-v3/ChangeLog:
* testsuite/24_iterators/random_access/string_vector_iterators.cc:
Reworked.
Reviewed-by: Patrick Palka <ppalka@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
|
|
This replaces most test_constexpr invocations with direct calls to
test_ranges(), which is also used for runtime tests.
SimpleAllocator was made constexpr to simplify this refactoring. Other
test allocators, like uneq_allocator (used in from_range constructor
tests), were not updated.
libstdc++-v3/ChangeLog:
* testsuite/21_strings/basic_string/cons/from_range.cc: Replace
test_constexpr with test_ranges inside static_assert.
* testsuite/21_strings/basic_string/modifiers/append/append_range.cc:
Likewise.
* testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc:
Likewise.
* testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc:
Likewise.
* testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc:
Likewise.
* testsuite/23_containers/vector/bool/cons/from_range.cc: Likewise.
* testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc:
Likewise.
* testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc:
Likewise.
* testsuite/23_containers/vector/cons/from_range.cc: Likewise.
* testsuite/23_containers/vector/modifiers/assign/assign_range.cc:
Likewise.
* testsuite/23_containers/vector/modifiers/insert/insert_range.cc:
Likewise.
* testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc:
Run full test_ranges instead of span-only in test_constexpr.
* testsuite/23_containers/vector/modifiers/append_range.cc:
Replace test_constexpr with calls to test_ranges and test_overlapping.
* testsuite/util/testsuite_allocator.h (__gnu_test::SimpleAllocator):
Declared member functions as constexpr.
|
|
|
|
All test code of default_accessor can be reused. This commit moves
the reuseable code into a file generic.cc and prepares the tests for
reuse with aligned_accessor.
libstdc++-v3/ChangeLog:
* testsuite/23_containers/mdspan/accessors/default.cc: Delete.
* testsuite/23_containers/mdspan/accessors/generic.cc: Slightly
generalize the test code previously in default.cc.
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
|
|
A recent commit improved the macro VERIFY to eliminate the need for
certain parens. This commit updates the test code in
23_containers/mdspan
libstdc++-v3/ChangeLog:
* testsuite/23_containers/mdspan/extents/ctor_ints.cc: Remove
superfluous parens.
* testsuite/23_containers/mdspan/extents/ctor_shape.cc: Ditto.
* testsuite/23_containers/mdspan/mdspan.cc: Ditto.
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
|
|
Adds negative tests for preconditions on inserting into a full
inplace_vector and erasing non-existent elementsi at compile-time.
This ensures coverage for the inplace_vector<T, 0> specialization.
Also extends element access tests to cover front() and back()
methods, and const and mutable overloads for all accesses.
PR libstdc++/119137
libstdc++-v3/ChangeLog:
* testsuite/23_containers/inplace_vector/access/elem.cc: Cover
front and back methods and const calls.
* testsuite/23_containers/inplace_vector/access/elem_neg.cc:
Likewise.
* testsuite/23_containers/inplace_vector/modifiers/erase_neg.cc:
New test.
* testsuite/23_containers/inplace_vector/modifiers/single_insert_neg.cc:
New test.
|
|
|
|
tests [PR119137]
All functions in testsuite_iterators.h are now marked constexpr,
targeting the earliest possible standard. Most functions use C++14 due
to multi-statement bodies, with exceptions:
* BoundsContainer and some constructors are C++11 compatible.
* OutputContainer is C++20 due to operator new/delete usage.
Before C++23, each constexpr templated function requires a constexpr
-suitable instantiation. Functions delegating to _GLIBCXX14_CONSTEXPR
must also be _GLIBCXX14_CONSTEXPR; e.g., forward_iterator_wrapper's
constructor calling input_iterator_wrapper's constructor, or
operator-> calling operator*.
For classes defined C++20 or later (e.g., test_range), constexpr is
applied unconditionally.
PR libstdc++/119137
libstdc++-v3/ChangeLog:
* testsuite/23_containers/inplace_vector/cons/from_range.cc: Run
iterators and range test at compile-time.
* testsuite/23_containers/inplace_vector/modifiers/assign.cc:
Likewise.
* testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc:
Likewise.
* testsuite/util/testsuite_iterators.h (__gnu_test::BoundsContainer)
(__gnu_test::OutputContainer, __gnu_test::WritableObject)
(__gnu_test::output_iterator_wrapper, __gnu_test::input_iterator_wrapper)
(__gnu_test::forward_iterator_wrapper)
(__gnu_test::bidirectional_iterator_wrapper)
(__gnu_test::random_access_iterator_wrapper)
(__gnu_test::test_container): Add appropriate _GLIBCXXNN_CONSTEXPR
macros to member functions.
(__gnu_test::contiguous_iterator_wrapper)
(__gnu_test::input_iterator_wrapper_rval)
(__gnu_test::test_range, __gnu_test::test_range_nocopy)
(__gnu_test::test_sized_range_sized_sent)
(__gnu_test::test_sized_range): Add constexpr specifier to member
functions.
|
|
In case of input iterators, the loop that assigns to existing elements
should run up to number of elements in vector (_M_size) not capacity (_Nm).
PR libstdc++/119137
libstdc++-v3/ChangeLog:
* include/std/inplace_vector (inplace_vector::assign_range):
Replace _Nm with _M_size in the assigment loop.
|
|
|
|
Previously, the default ctor of mdspan was never noexcept, even if all
members of mdspan were nothrow default constructible.
This commit makes mdspan conditionally nothrow default constructible.
A similar strengthening happens in libc++.
libstdc++-v3/ChangeLog:
* include/std/mdspan (mdspan::mdspan): Make default ctor
conditionally noexcept.
* testsuite/23_containers/mdspan/mdspan.cc: Add tests.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
|
|
The mdspan::is_{,always}_{unique,strided,exhaustive} methods only call
their counterparts in mdspan::mapping_type. The standard specifies that
the methods of mdspan::mapping_type are noexcept, but doesn't specify if
the methods of mdspan are noexcept.
Libc++ strengthened the exception guarantee for these mdspan methods.
This commit conditionally strengthens these methods for libstdc++.
libstdc++-v3/ChangeLog:
* include/std/mdspan (mdspan::is_always_unique): Make
conditionally noexcept.
(mdspan::is_always_exhaustive): Ditto.
(mdspan::is_always_strided): Ditto.
(mdspan::is_unique): Ditto.
(mdspan::is_exhaustive): Ditto.
(mdspan::is_strided): Ditto.
* testsuite/23_containers/mdspan/layout_like.h: Make noexcept
configurable. Add ThrowingLayout.
* testsuite/23_containers/mdspan/mdspan.cc: Add tests for
noexcept.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
|
|
|
|
r16-442 implemented both std::extents and std::dextents (and perhaps other
stuff), but exported only std::extents.
I went through https://eel.is/c++draft/mdspan.syn and I think std::dextents
is the only one implemented but not exported.
The following patch exports it, and additionally appends some further
entities to the FIXME list, those all seems to be unimplemented yet.
2025-07-20 Jakub Jelinek <jakub@redhat.com>
PR libstdc++/121174
* src/c++23/std.cc.in (std::dextents): Export. Add to FIXME comments
other not yet implemented nor exported <mdspan> entities.
|
|
|
|
Currently this new concept will get defined for -std=c++17 -fconcepts
but as it uses std::input_iterator, which is new in C++20, that won't
work. Guard it with __cpp_lib_concepts as well as __cpp_concepts.
libstdc++-v3/ChangeLog:
* include/bits/stl_iterator_base_types.h (__any_input_iterator):
Only define when __cpp_lib_concepts is defined.
|
|
Paolo has not been active for some time.
libstdc++-v3/ChangeLog:
* doc/xml/manual/appendix_contributing.xml: Remove Paolo from
list of maintainers to contact about contributing.
* doc/html/manual/appendix_contributing.html: Regenerate.
|