Per https://github.com/itanium-cxx-abi/cxx-abi/issues/24 and
https://github.com/itanium-cxx-abi/cxx-abi/pull/166
We need to mangle constraints to be able to distinguish between function
templates that only differ in constraints. From the latter link, we want to
use the template parameter mangling previously specified for lambdas to also
make explicit the form of a template parameter where the argument is not a
"natural" fit for it, such as when the parameter is constrained or deduced.
I'm concerned about how the latter link changes the mangling for some C++98
and C++11 patterns, so I've limited template_parm_natural_p to avoid two
cases found by running the testsuite with -Wabi forced on:
template <class T, T V> T f() { return V; }
int main() { return f<int,42>(); }
template <int i> int max() { return i; }
template <int i, int j, int... rest> int max()
{
int sub = max<j, rest...>();
return i > sub ? i : sub;
}
int main() { return max<1,2,3>(); }
A third C++11 pattern is changed by this patch:
template <template <typename...> class TT, typename... Ts> TT<Ts...> f();
template <typename> struct A { };
int main() { f<A,int>(); }
I aim to resolve these with the ABI committee before GCC 14.1.
We also need to resolve https://github.com/itanium-cxx-abi/cxx-abi/issues/38
(mangling references to dependent template-ids where the name is fully
resolved) as references to concepts in std:: will consistently run into this
area. This is why mangle-concepts1.C only refers to concepts in the global
namespace so far.
The library changes are to avoid trying to mangle builtins, which fails.
Demangler support and test coverage is not complete yet.
gcc/cp/ChangeLog:
* cp-tree.h (TEMPLATE_ARGS_TYPE_CONSTRAINT_P): New.
(get_concept_check_template): Declare.
* constraint.cc (combine_constraint_expressions)
(finish_shorthand_constraint): Use UNKNOWN_LOCATION.
* pt.cc (convert_generic_types_to_packs): Likewise.
* mangle.cc (write_constraint_expression)
(write_tparms_constraints, write_type_constraint)
(template_parm_natural_p, write_requirement)
(write_requires_expr): New.
(write_encoding): Mangle trailing requires-clause.
(write_name): Pass parms to write_template_args.
(write_template_param_decl): Factor out from...
(write_closure_template_head): ...here.
(write_template_args): Mangle non-natural parms
and requires-clause.
(write_expression): Handle REQUIRES_EXPR.
include/ChangeLog:
* demangle.h (enum demangle_component_type): Add
DEMANGLE_COMPONENT_CONSTRAINTS.
libiberty/ChangeLog:
* cp-demangle.c (d_make_comp): Handle
DEMANGLE_COMPONENT_CONSTRAINTS.
(d_count_templates_scopes): Likewise.
(d_print_comp_inner): Likewise.
(d_maybe_constraints): New.
(d_encoding, d_template_args_1): Call it.
(d_parmlist): Handle 'Q'.
* testsuite/demangle-expected: Add some constraint tests.
libstdc++-v3/ChangeLog:
* include/std/bit: Avoid builtins in requires-clauses.
* include/std/variant: Likewise.
gcc/testsuite/ChangeLog:
* g++.dg/abi/mangle10.C: Disable compat aliases.
* g++.dg/abi/mangle52.C: Specify ABI 18.
* g++.dg/cpp2a/class-deduction-alias3.C
* g++.dg/cpp2a/class-deduction-alias8.C:
Avoid builtins in requires-clauses.
* g++.dg/abi/mangle-concepts1.C: New test.
* g++.dg/abi/mangle-ttp1.C: New test.
This C++26 change makes several classes "partially freestanding", but we
already fully supported them in freestanding mode. All we need to do is
define the new feature test macros and add tests for them.
libstdc++-v3/ChangeLog:
* include/bits/version.def (freestanding_algorithm)
(freestanding_array, freestanding_optional)
(freestanding_string_view, freestanding_variant): Add.
* include/bits/version.h: Regenerate.
* include/std/algorithm (__glibcxx_want_freestanding_algorithm):
Define.
* include/std/array (__glibcxx_want_freestanding_array):
Define.
* include/std/optional (__glibcxx_want_freestanding_optional):
Define.
* include/std/string_view
(__glibcxx_want_freestanding_string_view): Define.
* include/std/variant (__glibcxx_want_freestanding_variant):
Define.
* testsuite/20_util/optional/version.cc: Add checks for
__cpp_lib_freestanding_optional.
* testsuite/20_util/variant/version.cc: Add checks for
__cpp_lib_freestanding_variant.
* testsuite/23_containers/array/tuple_interface/get_neg.cc:
Adjust dg-error line numbers.
* testsuite/21_strings/basic_string_view/requirements/version.cc:
New test.
* testsuite/23_containers/array/requirements/version.cc: New
test.
* testsuite/25_algorithms/fill_n/requirements/version.cc: New
test.
* testsuite/25_algorithms/swap_ranges/requirements/version.cc:
New test.
This patch ensures that the union members for std::string and
std::variant are always properly set when a change occurs.
libstdc++-v3/ChangeLog:
* include/bits/basic_string.h: (basic_string(basic_string&&)):
Activate _M_local_buf when needed.
(basic_string(basic_string&&, const _Alloc&)): Likewise.
* include/bits/basic_string.tcc: (basic_string::swap): Likewise.
* include/std/variant: (__detail::__variant::__construct_n): New.
(__detail::__variant::__emplace): Use __construct_n.
Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
The standard says the default ctor should be constrained, not deleted.
Our use of a defaulted default ctor and _Enable_default_constructor base
class results in it being deleted.
libstdc++-v3/ChangeLog:
* include/std/variant (variant): Remove derivation from
_Enable_default_constructor base class.
(variant::variant()): Constrain.
* testsuite/20_util/variant/default_ctor.cc: New test.
A void template argument would cause a substitution failure when trying
to form a reference for the return type, so the function body would
never be instantiated.
libstdc++-v3/ChangeLog:
PR libstdc++/111172
* include/std/variant (get<T>): Remove !is_void static
assertions.
This was approved at the October 2021 plenary.
libstdc++-v3/ChangeLog:
* include/std/variant (variant::operator=): Implement resolution
of LWG 3585.
* testsuite/20_util/variant/lwg3585.cc: New test.
The warning is wrong here, the qualifier serves a purpose and is not
ignored (c.f. PR c++/107492).
libstdc++-v3/ChangeLog:
* include/std/variant (__variant::_Multi_array::__untag_result):
Use pragma to suppress warning.
The optimization for the common case of std::visit forgot to handle the
edge case of passing zero variants to a non-void visitor and converting
the result to void.
libstdc++-v3/ChangeLog:
PR libstdc++/106589
* include/std/variant (__do_visit): Handle is_void<R> for zero
argument case.
* testsuite/20_util/variant/visit_r.cc: Check std::visit<void>(v).
For any typedef-name or template parameter, T, add_const_t<T> is
equivalent to T const, so we can avoid instantiating the std::add_const
class template and just say T const (or const T).
This isn't true for a non-typedef like int&, where int& const would be
ill-formed, but we shouldn't be using add_const_t<int&> anyway, because
we know what that type is.
The only place we need to continue using std::add_const is in the
std::bind implementation where it's used as a template template
parameter to be applied as a metafunction elsewhere.
libstdc++-v3/ChangeLog:
* include/bits/stl_iterator.h (__iter_to_alloc_t): Replace
add_const_t with const-qualifier.
* include/bits/utility.h (tuple_element<N, cv T>): Likewise for
all cv-qualifiers.
* include/std/type_traits (add_const, add_volatile): Replace
typedef-declaration with using-declaration.
(add_cv): Replace add_const and add_volatile with cv-qualifiers.
* include/std/variant (variant_alternative<N, cv T>): Replace
add_const_t, add_volatile_t and add_cv_t etc. with cv-qualifiers.
libstdc++-v3/ChangeLog:
* include/std/variant (_Build_FUN::_S_fun): Define fallback case
as deleted.
(__accepted_index, _Extra_visit_slot_needed): Replace class
templates with variable templates.
These headers do not use anything in <bits/stl_iterator_base_types.h>
directly, and it's included by <bits/stl_iterator_base_funcs.h> and
<bits/stl_iterator.h> anyway, because they do need it.
libstdc++-v3/ChangeLog:
* include/bits/ranges_algobase.h: Do not include
<bits/stl_iterator_base_types.h>.
* include/std/string: Likewise.
* include/std/variant: Likewise.
With the new value of __cpp_concepts required by P2493, we can test
whether the compiler supports conditionally trivial special members.
This allows us to remove the workaround that disables fully-constexpr
std::variant for Clang. Now it should work for non-GCC compilers (such
as future releases of Clang) that support conditionally trivial
destructors and define the new value of __cpp_concepts.
libstdc++-v3/ChangeLog:
PR libstdc++/103891
* include/bits/c++config (_GLIBCXX_HAVE_COND_TRIVIAL_SPECIAL_MEMBERS):
Remove.
* include/std/variant: Check feature test macros instead.
* include/std/version: Likewise.
Clang has some bugs with destructors that use constraints to be
conditionally trivial, so disable the P2231R1 constexpr changes to
std::variant unless the compiler is GCC 12 or later.
If/when P2493R0 gets accepted and implemented by G++ we can remove the
__GNUC__ check and use __cpp_concepts >= 202002 instead.
libstdc++-v3/ChangeLog:
PR libstdc++/103891
* include/bits/c++config (_GLIBCXX_HAVE_COND_TRIVIAL_SPECIAL_MEMBERS):
Define.
* include/std/variant (__cpp_lib_variant): Only define C++20
value when the compiler is known to support conditionally
trivial destructors.
* include/std/version (__cpp_lib_variant): Likewise.
Currently std::variant uses __index_of<T, Types...> to find the first
occurence of a type in a pack, and __exactly_once<T, Types...> to check
that there is no other occurrence.
We can reuse the __find_uniq_type_in_pack<T, Types...>() function for
both tasks, and remove the recursive templates used to implement
__index_of and __exactly_once.
libstdc++-v3/ChangeLog:
* include/bits/utility.h (__find_uniq_type_in_pack): Move
definition to here, ...
* include/std/tuple (__find_uniq_type_in_pack): ... from here.
* include/std/variant (__detail__variant::__index_of): Remove.
(__detail::__variant::__exactly_once): Define using
__find_uniq_type_in_pack instead of __index_of.
(get<T>, get_if<T>, variant::__index_of): Likewise.
This reduces the number of class template instantiations needed for code
using tuples, by reusing _Nth_type in tuple_element and specializing
tuple_size_v for tuple, pair and array (and const-qualified versions of
them).
Also define the _Nth_type primary template as a complete type (but with
no nested 'type' member). This avoids "invalid use of incomplete type"
errors for out-of-range specializations of tuple_element. Those errors
would probably be confusing and unhelpful for users. We already have
a user-friendly static assert in tuple_element itself.
Also ensure that tuple_size_v is available whenever tuple_size is (as
proposed by LWG 3387). We already do that for tuple_element_t.
libstdc++-v3/ChangeLog:
* include/bits/stl_pair.h (tuple_size_v): Define partial
specializations for std::pair.
* include/bits/utility.h (_Nth_type): Move definition here
and define primary template.
(tuple_size_v): Move definition here.
* include/std/array (tuple_size_v): Define partial
specializations for std::array.
* include/std/tuple (tuple_size_v): Move primary template to
<bits/utility.h>. Define partial specializations for
std::tuple.
(tuple_element): Change definition to use _Nth_type.
* include/std/variant (_Nth_type): Move to <bits/utility.h>.
(variant_alternative, variant): Adjust qualification of
_Nth_type.
* testsuite/20_util/tuple/element_access/get_neg.cc: Prune
additional errors from _Nth_type.
libstdc++-v3/ChangeLog:
* include/std/variant (__detail::__variant::__emplace): New
function template.
(_Copy_assign_base::operator=): Reorder conditions to match
bulleted list of effects in the standard. Use __emplace instead
of _M_reset followed by _Construct.
(_Move_assign_base::operator=): Likewise.
(__construct_by_index): Remove.
(variant::emplace): Use __emplace instead of _M_reset followed
by __construct_by_index.
(variant::swap): Hoist valueless cases out of visitor. Use
__emplace to replace _M_reset followed by _Construct.
By defining additional partial specializations of _Nth_type we can
reduce the number of recursive instantiations needed to get from N to 0.
We can also use _Nth_type in variant_alternative, to take advantage of
that new optimization.
By adding a static_assert to variant_alternative we get a nicer error
than 'invalid use of incomplete type'.
By defining partial specializations of std::variant_size_v for the
common case we can avoid instantiating the std::variant_size class
template.
The __tuple_count class template and __tuple_count_v variable template
can be simplified to a single variable template, __count.
By adding a deleted constructor to the _Variant_union primary template
we can (very slightly) improve diagnostics for invalid attempts to
construct a std::variant with an out-of-range index. Instead of a
confusing error about "too many initializers for ..." we get a call to a
deleted function.
By using _Nth_type instead of variant_alternative (for cv-unqualified
variant types) we avoid instantiating variant_alternative.
By adding deleted overloads of variant::emplace we get better
diagnostics for emplace<invalid-index> or emplace<invalid-type>. Instead
of getting errors explaining why each of the four overloads wasn't
valid, we just get one error about calling a deleted function.
libstdc++-v3/ChangeLog:
* include/std/variant (_Nth_type): Define partial
specializations to reduce number of instantiations.
(variant_size_v): Define partial specializations to avoid
instantiations.
(variant_alternative): Use _Nth_type. Add static assert.
(__tuple_count, __tuple_count_v): Replace with ...
(__count): New variable template.
(_Variant_union): Add deleted constructor.
(variant::__to_type): Use _Nth_type.
(variant::emplace): Use _Nth_type. Add deleted overloads for
invalid types and indices.
Prior to r12-4447 (implementing P2231R1 constexpr changes) we didn't
construct the correct member of the union in __variant_construct_single,
we just plopped an object in the memory occupied by the union:
void* __storage = std::addressof(__lhs._M_u);
using _Type = remove_reference_t<decltype(__rhs_mem)>;
::new (__storage) _Type(std::forward<decltype(__rhs_mem)>(__rhs_mem));
We didn't care whether we had variant<int, const int>, we would just
place an int (or const int) into the storage, and then set the _M_index
to say which one it was.
In the new constexpr-friendly code we use std::construct_at to construct
the union object, which constructs the active member of the right type.
But now we need to know exactly the right type. We have to distinguish
between alternatives of type int and const int, and we have to be able
to find a const int (or const std::string, as in the OP) among the
alternatives. So my change from remove_reference_t<decltype(__rhs_mem)>
to remove_cvref_t<_Up> was wrong. It strips the const from const int,
and then we can't find the index of the const int alternative.
But just using remove_reference_t doesn't work either. When the copy
assignment operator of std::variant<int> uses __variant_construct_single
it passes a const int& as __rhs_mem, but if we don't strip the const
then we try to find const int among the alternatives, and *that* fails.
Similarly for the copy constructor, which also uses a const int& as the
initializer for a non-const int alternative.
The root cause of the problem is that __variant_construct_single doesn't
know the index of the type it's supposed to construct, and the new
_Variant_storage::__index_of<_Type> helper doesn't work if __rhs_mem and
the alternative being constructed have different const-qualification. We
need to replace __variant_construct_single with something that knows the
index of the alternative being constructed. All uses of that function do
actually know the index, but that context is lost by the time we call
__variant_construct_single. This patch replaces that function and
__variant_construct, inlining their effects directly into the callers.
libstdc++-v3/ChangeLog:
PR libstdc++/102912
* include/std/variant (_Variant_storage::__index_of): Remove.
(__variant_construct_single): Remove.
(__variant_construct): Remove.
(_Copy_ctor_base::_Copy_ctor_base(const _Copy_ctor_base&)): Do
construction directly instead of using __variant_construct.
(_Move_ctor_base::_Move_ctor_base(_Move_ctor_base&&)): Likewise.
(_Move_ctor_base::_M_destructive_move()): Remove.
(_Move_ctor_base::_M_destructive_copy()): Remove.
(_Copy_assign_base::operator=(const _Copy_assign_base&)): Do
construction directly instead of using _M_destructive_copy.
(variant::swap): Do construction directly instead of using
_M_destructive_move.
* testsuite/20_util/variant/102912.cc: New test.
This more clearly expresses the intent (a completely unused, trivial
type) than using char. It's also consistent with the unions in
std::optional.
libstdc++-v3/ChangeLog:
* include/std/variant (_Uninitialized): Use an empty struct
for the unused union member, instead of char.
This implements the changes in P2231R1 which make std::variant fully
constexpr in C++20.
We need to replace placement new with std::construct_at, but that isn't
defined for C++17. Use std::_Construct instead, which forwards to
std::construct_at in C++20 mode (since the related changes to make
std::optional fully constexpr, in r12-4389).
We also need to replace the untyped char buffer in _Uninitialized with a
union, which can be accessed in constexpr functions. But the union needs
to have a non-trivial destructor if its variant type is non-trivial,
which means that the _Variadic_union also needs a non-trivial
destructor. This adds a constrained partial specialization of
_Variadic_union for the C++20-only case where a non-trivial destructor
is needed.
We can't use concepts to constrain the specialization (or the primary
template's destructor) in C++17, so retain the untyped char buffer
solution for C++17 mode.
libstdc++-v3/ChangeLog:
* include/std/variant (__cpp_lib_variant): Update value for
C++20.
(__variant_cast, __variant_construct): Add constexpr for C++20.
(__variant_construct_single, __construct_by_index) Likewise. Use
std::_Construct instead of placement new.
(_Uninitialized<T, false>) [__cplusplus >= 202002]: Replace
buffer with a union and define a destructor.
(_Variadic_union) [__cplusplus >= 202002]: Add a specialization
for non-trivial destruction.
(_Variant_storage::__index_of): New helper variable template.
(_Variant_storage::~_Variant_storage()): Add constexpr.
(_Variant_storage::_M_reset()): Likewise.
(_Copy_ctor_base, _Move_ctor_base): Likewise.
(_Copy_assign_base, _Move_assign_base): Likewise.
(variant, swap): Likewise.
* include/std/version (__cpp_lib_variant): Update value for
C++20.
* testsuite/20_util/optional/version.cc: Check for exact value
in C++17.
* testsuite/20_util/variant/87619.cc: Increase timeout for
C++20 mode.
* testsuite/20_util/variant/constexpr.cc: New test.
* testsuite/20_util/variant/version.cc: New test.
The __variant_construct_by_index helper function sets the new index
before constructing the new object. This means that if the construction
throws then the exception needs to be caught, so the index can be reset
to variant_npos, and then the exception rethrown. This means callers are
responsible for restoring the variant's invariants and they need the
overhead of a catch handler and a rethrow.
If we don't set the index until after construction completes then the
invariant is never broken, and callers can ignore the exception and let
it propagate. The callers all call _M_reset() first, which sets index to
variant_npos as required while the variant is valueless.
We need to be slightly careful here, because changing the order of
operations in __variant_construct_by_index and removing the try-block
from variant::emplace<I> changes an implicit ABI contract between those
two functions. If the linker were to create an executable containing an
instantiation of the old __variant_construct_by_index and an
instantiation of the new variant::emplace<I> code then we would have a
combination that breaks the invariant and doesn't have the exception
handling to restore it. To avoid this problem, we can rename the
__variant_construct_by_index function so that the new emplace<I> code
calls a new symbol, and is unaffected by the behaviour of the old
symbol.
libstdc++-v3/ChangeLog:
* include/std/variant (__detail::__variant::__get_storage):
Remove unused function.
(__variant_construct_by_index): Set index after construction is
complete. Rename to ...
(__detail::__variant::__construct_by_index): ... this.
(variant): Use new name for __variant_construct_by_index friend
declaration. Remove __get_storage friend declaration.
(variant::emplace): Use new name and remove try-blocks.
These functions aren't used, and accessing the storage as a void* isn't
compatible with C++20 constexpr requirements anyway, so we're unlikely
to ever start using them in future.
libstdc++-v3/ChangeLog:
* include/std/variant (_Variant_storage::_M_storage()): Remove.
(__detail::__variant::__get_storage): Remove.
(variant): Remove friend declaration of __get_storage.
libstdc++-v3/ChangeLog:
* include/std/variant (__variant::__get(in_place_index_t<N>, U&&)):
Rename to __get_n and remove first argument. Replace pair of
overloads with a single function using 'if constexpr'.
(__variant::__get(Variant&&)): Adjust to use __get_n.
Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/ChangeLog:
* include/std/variant (__do_visit): Use variant_npos instead of
literal -1 that requires a narrowing conversion.
This change is inspired by the suggestion in
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1715r0.html
The new std::__conditional_t alias template is functionally equivalent
to std::conditional_t but should be more efficient to compile, due to
only ever instantiating two specializations (std::__conditional<true>
and std::__conditional<false>) rather than a new specialization for
every use of std::conditional.
The new alias template is also available in C++11, unlike the C++14
std::conditional_t alias.
Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/ChangeLog:
* include/std/type_traits (__conditional): New class template
for internal uses of std::conditional.
(__conditional_t): New alias template to replace conditional_t.
(__and_, __or_, __result_of_memfun, __result_of_memobj): Use
__conditional_t instead of conditional::type.
* include/bits/atomic_base.h (__atomic_impl::_Diff): Likewise.
* include/bits/hashtable.h (_Hashtable): Likewise.
* include/bits/hashtable_policy.h (_Node_iterator, _Insert_base)
(_Local_iterator): Likewise. Replace typedefs with
using-declarations.
* include/bits/move.h (move_if_noexcept): Use __conditional_t.
* include/bits/parse_numbers.h (_Select_int_base): Likewise.
* include/bits/ptr_traits.h (__make_not_void): Likewise.
* include/bits/ranges_algobase.h (__copy_or_move_backward)
(__copy_or_move): Likewise.
* include/bits/ranges_base.h (borrowed_iterator_t): Likewise.
* include/bits/ranges_util.h (borrowed_subrange_t): Likewise.
* include/bits/regex_compiler.h (_BracketMatcher): Use
__conditional_t. Replace typedefs with using-declarations.
* include/bits/shared_ptr_base.h (__shared_count): Use
__conditional_t.
* include/bits/stl_algobase.h (__copy_move, __copy_move_backward):
Likewise.
* include/bits/stl_iterator.h (__detail::__clamp_iter_cat)
(reverse_iterator::iterator_concept)
(__make_move_if_noexcept_iterator)
(iterator_traits<common_iterator<_It, _Sent>>)
(iterator_traits<counted_iterator<_It>>): Likewise.
* include/bits/stl_pair.h (_PCC, pair::operator=): Likewise.
* include/bits/stl_tree.h (_Rb_tree::insert_return_type)
(_Rb_tree::_M_clone_node): Likewise.
* include/bits/unique_ptr.h (unique_ptr(unique_ptr<U,E>&&)):
Likewise.
* include/bits/uses_allocator.h (__uses_alloc): Likewise.
(__is_uses_allocator_predicate): Likewise.
* include/debug/functions.h (__foreign_iterator_aux2): Likewise.
* include/experimental/any (any::_Manager, __any_caster):
Likewise.
* include/experimental/executor (async_completion): Likewise.
* include/experimental/functional (__boyer_moore_base_t):
Likewise.
* include/std/any (any::_Manager): Likewise.
* include/std/functional (__boyer_moore_base_t): Likewise.
* include/std/ranges (borrowed_iterator_t)
(borrowed_subrange_t, __detail::__maybe_present_t)
(__detail::__maybe_const_t, split_view): Likewise.
* include/std/tuple (__empty_not_final, tuple::operator=):
Likewise.
* include/std/variant (__detail::__variant::__get_t): Likewise.
GCC does not do a good job of optimizing the table of function pointers
used for variant visitation. This avoids using the table for the common
case of visiting a single variant with a small number of alternative
types. Instead we use:
switch(v.index())
{
case 0: return visitor(get<0>(v));
case 1: return visitor(get<1>(v));
...
}
It's not quite that simple, because get<1>(v) is ill-formed if the
variant only has one alternative, and similarly for each get<N>. We
need to ensure each case only applies the visitor if the index is in
range for the actual type we're dealing with, and tell the compiler that
the case is unreachable otherwise. We also need to invoke the visitor
via the __gen_vtable_impl::__visit_invoke function, to handle the raw
visitation cases used to implement std::variant assignments and
comparisons.
Because that gets quite verbose and repetitive, a macro is used to stamp
out the cases.
We also need to handle the valueless_by_exception case, but only for raw
visitation, because std::visit already checks for it before calling
__do_visit.
Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/ChangeLog:
PR libstdc++/78113
* include/std/variant (__do_visit): Use a switch when we have a
single variant with a small number of alternatives.
Implement the changes from P2162R2 (as a DR for C++17).
Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/ChangeLog:
PR libstdc++/90943
* include/std/variant (__cpp_lib_variant): Update value.
(__detail::__variant::__as): New helpers implementing the
as-variant exposition-only function templates.
(visit, visit<R>): Use __as to upcast the variant parameters.
* include/std/version (__cpp_lib_variant): Update value.
* testsuite/20_util/variant/visit_inherited.cc: New test.
This refactoring reduces the memory usage and compilation time to parse
a number of headers that depend on std::pair, std::tuple or std::array.
Previously the headers for these class templates were all intertwined,
due to the common dependency on std::tuple_size, std::tuple_element and
their std::get overloads. This decouples the headers by moving some
parts of <utility> into a new <bits/utility.h> header. This means that
<array> and <tuple> no longer need to include the whole of <utility>,
and <tuple> no longer needs to include <array>.
This decoupling benefits headers such as <thread> and <scoped_allocator>
which only need std::tuple, and so no longer have to parse std::array.
Some other headers such as <any>, <optional> and <variant> no longer
need to include <utility> just for the std::in_place tag types, so
do not have to parse the std::pair definitions.
Removing direct uses of <utility> also means that the std::rel_ops
namespace is not transitively declared by other headers.
Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/ChangeLog:
* include/Makefile.am: Add bits/utility.h header.
* include/Makefile.in: Regenerate.
* include/bits/utility.h: New file.
* include/std/utility (tuple_size, tuple_element): Move
to new header.
* include/std/type_traits (__is_tuple_like_impl<tuple<T...>>):
Move to <tuple>.
(_Index_tuple, _Build_index_tuple, integer_sequence): Likewise.
(in_place_t, in_place_index_t, in_place_type_t): Likewise.
* include/bits/ranges_util.h: Include new header instead of
<utility>.
* include/bits/stl_pair.h (tuple_size, tuple_element): Move
partial specializations for std::pair here.
(get): Move overloads for std::pair here.
* include/std/any: Include new header instead of <utility>.
* include/std/array: Likewise.
* include/std/memory_resource: Likewise.
* include/std/optional: Likewise.
* include/std/variant: Likewise.
* include/std/tuple: Likewise.
(__is_tuple_like_impl<tuple<T...>>): Move here.
(get) Declare overloads for std::array.
* include/std/version (__cpp_lib_tuples_by_type): Change type
to long.
* testsuite/20_util/optional/84601.cc: Include <utility>.
* testsuite/20_util/specialized_algorithms/uninitialized_fill/constrained.cc:
Likewise.
* testsuite/23_containers/array/tuple_interface/get_neg.cc:
Adjust dg-error line numbers.
* testsuite/std/ranges/access/cbegin.cc: Include <utility>.
* testsuite/std/ranges/access/cend.cc: Likewise.
* testsuite/std/ranges/access/end.cc: Likewise.
* testsuite/std/ranges/single_view.cc: Likewise.
This defines some new Doxygen groups for C++17 variable templates and
for the contents of <experimental/type_traits>. By documenting the group
as a whole and adding each template to a group we don't need to document
them individually.
Also mark more internals with "@cond undocumented" so that Doxygen
ignores them by default. Also make Doxygen process <experimental/simd>.
For some reason, many of the class templates in <type_traits> do not
appear in the "Metaprogramming" group. For example, add_cv,
remove_extent, and all the is_xxx_constructible and is_xxx_assignable
traits. For some reason, Doxygen doesn't include them in the group,
despite doing it correctly for other traits in the same header.
Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/ChangeLog:
PR libstdc++/101258
* doc/doxygen/user.cfg.in (INPUT): Add <experimental/simd>.
(COLS_IN_ALPHA_INDEX): Remove obsolete tag.
(PREDEFINED): Add/fix some more macros that need to be expanded.
* include/bits/random.h: Stop Doxygen from documenting internal
implementation details.
* include/bits/random.tcc: Likewise.
* include/bits/this_thread_sleep.h: Fix @file name.
* include/experimental/bits/simd.h: Add to Doxygen group. Do not
document internal implementation details.
* include/experimental/bits/simd_detail.h: Do not document
internal implementation details.
* include/experimental/simd: Define Doxygen groups.
* include/experimental/type_traits: Improve documentation for
the header file. Define groups. Use @since commands.
* include/std/scoped_allocator (scoped_allocator_adaptor): Move
declaration before undocumented region.
* include/std/type_traits (true_type, false_type): Use using
declaration instead of typedef.
(is_invocable_v, is_nothrow_invocable_v, is_invocable_r_v)
(is_nothrow_invocable_r_v): Move definitions next to other C++17
variable templates.
Do not document internal implementation details. Move misplaced
group-end command. Define group for variable templates.
* include/std/variant: Do not document internal implementation
details.
* testsuite/26_numerics/random/pr60037-neg.cc: Adjust dg-error
line number.
This avoids errors outside the immediate context when std::visit is an
overload candidate because of ADL, but not actually viable.
The solution is to give std::visit a non-deduced return type. New
helpers are introduced for that, and existing ones refactored slightly.
libstdc++-v3/ChangeLog:
PR libstdc++/100384
* include/std/variant (__get_t): New alias template yielding the
return type of std::get<N> on a variant.
(__visit_result_t): New alias template yielding the result of
std::visit.
(__same_types): Move into namespace __detail::__variant.
(__check_visitor_results): Likewise. Use __invoke_result_t and
__get_t.
(__check_visitor_result): Remove.
(visit): Use __visit_result_t for return type.
* testsuite/20_util/variant/100384.cc: New test.
These are usually suppressed in system headers, but should be fixed
anyway.
libstdc++-v3/ChangeLog:
* include/bits/parse_numbers.h (_Select_int_base): Avoid
narrowing conversion in constant expression.
* include/experimental/buffer (buffer_copy): Avoid narrowing
conversion.
* include/experimental/internet (hash<>::operator()): Do not
use deprecated 'argument_type' member.
* include/std/variant (variant::emplace): Use cast instead
of implicit conversion from size_t to narrower unsigned type.
PR libstdc++/91807
* include/std/variant
(_Copy_assign_base::operator=(const _Copy_assign_base&):
Do the move-assignment from a temporary so that the temporary
is constructed with an explicit index.
* testsuite/20_util/variant/91807.cc: New.
G++ implements P1972R2 since r11-1597-0ca22d027ecc and so we no longer
need the P0608R3 special case to prevent narrowing conversions to bool.
Since non-GNU compilers don't necessarily implment P1972R2 yet, this
may cause a regression for those compilers. There is no feature-test
macro we can use to detect it though, so we'll have to live with it.
libstdc++-v3/ChangeLog:
PR libstdc++/95832
* include/std/variant (__detail::__variant::_Build_FUN): Remove
partial specialization to prevent narrowing conversions to bool.
* testsuite/20_util/variant/compile.cc: Test non-narrowing
conversions to bool.
* testsuite/20_util/variant/run.cc: Likewise.
The __index_type is only ever unsigned char or unsigned short, so not
the same type as size_t.
* include/std/variant (variant::index()): Remove impossible case.
From-SVN: r276100
If __index_type is a smaller type than size_t, then the result of
size_t(__index_type(-1)) is not equal to size_t(-1), but to an incorrect
value such as size_t(255) or size_t(65535). The old implementation of
variant<T...>::index() uses (size_t(__index_type(_M_index + 1)) - 1)
which is always correct, but generates suboptimal code for many common
cases.
When the __index_type is size_t or valueless variants are not possible
we can just return the value directly.
When the number of alternatives is sufficiently small the result of
converting the _M_index value to the corresponding signed type will be
either non-negative or -1. In those cases converting to the signed type
and then to size_t will either produce the correct positive value or
will sign extend -1 to (size_t)-1 as desired.
For the remaining case we keep the existing arithmetic operations to
ensure the correct result.
PR libstdc++/91788 (partial)
* include/std/variant (variant::index()): Improve codegen for cases
where conversion to size_t already works correctly.
From-SVN: r276056
Also fix a warning with -Wunused-parameter -Wsystem-headers.
* include/std/variant (get<T>, get<N>, get_if<N>, get_if<T>)
(variant::emplace): Change static_assert messages from "should be"
to "must be".
(hash<monostate>::operator()): Remove name of unused parameter.
From-SVN: r272188