Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<type_traits>: Workaround for common_reference #2592

Merged
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions stl/inc/concepts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ concept derived_from = __is_base_of(_Base, _Derived)
&& __is_convertible_to(const volatile _Derived*, const volatile _Base*);

template <class _From, class _To>
#if !defined(__EDG__) && !defined(__clang__) // TRANSITION, DevCom-1627396
concept convertible_to = is_convertible_v<_From, _To>
#else // ^^^ workaround / no workaround vvv
concept convertible_to = __is_convertible_to(_From, _To)
#endif // ^^^ no workaround ^^^
&& requires {
static_cast<_To>(_STD declval<_From>());
};
Expand Down
58 changes: 54 additions & 4 deletions stl/inc/type_traits
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,32 @@ struct is_convertible : bool_constant<__is_convertible_to(_From, _To)> {
template <class _From, class _To>
_INLINE_VAR constexpr bool is_convertible_v = __is_convertible_to(_From, _To);

#if !defined(__EDG__) && !defined(__clang__) // TRANSITION, DevCom-1627396
template <class _Ty>
struct is_convertible<_Ty&, volatile _Ty&> : true_type {};

template <class _Ty>
struct is_convertible<volatile _Ty&, volatile _Ty&> : true_type {};

template <class _Ty>
struct is_convertible<_Ty&, const volatile _Ty&> : true_type {};

template <class _Ty>
struct is_convertible<volatile _Ty&, const volatile _Ty&> : true_type {};

template <class _Ty>
_INLINE_VAR constexpr bool is_convertible_v<_Ty&, volatile _Ty&> = true;

template <class _Ty>
_INLINE_VAR constexpr bool is_convertible_v<volatile _Ty&, volatile _Ty&> = true;

template <class _Ty>
_INLINE_VAR constexpr bool is_convertible_v<_Ty&, const volatile _Ty&> = true;

template <class _Ty>
_INLINE_VAR constexpr bool is_convertible_v<volatile _Ty&, const volatile _Ty&> = true;
#endif // ^^^ workaround

template <class _Ty>
struct is_enum : bool_constant<__is_enum(_Ty)> {}; // determine whether _Ty is an enumerated type

Expand Down Expand Up @@ -1179,10 +1205,6 @@ struct basic_common_reference {};
template <class _Ty>
_Ty _Returns_exactly() noexcept; // not defined

template <class _Ty1, class _Ty2>
using _Cond_res = // N4810 [meta.trans.other]/2.4
decltype(false ? _Returns_exactly<_Ty1>() : _Returns_exactly<_Ty2>());

template <class _From>
struct _Copy_cv_impl {
template <class _To>
Expand Down Expand Up @@ -1223,6 +1245,34 @@ struct _Add_qualifiers<_Ty1&&> {
using _Apply = add_rvalue_reference_t<_Copy_cv<_Ty1, _Ty2>>;
};

#if !defined(__EDG__) && !defined(__clang__) // TRANSITION, DevCom-876860
template <class _Ty1, class _Ty2>
using _Cond_res_if_right = // N4810 [meta.trans.other]/2.4
decltype(false ? _Returns_exactly<_Ty1>() : _Returns_exactly<_Ty2>());

template <class _Ty>
using _Is_scalar_or_array = disjunction<is_scalar<_Ty>, is_array<_Ty>>;

template <class _Ty1, class _Ty2, class = void>
struct _Cond_res_workaround {};

template <class _Ty1, class _Ty2>
struct _Cond_res_workaround<_Ty1, _Ty2, void_t<_Cond_res_if_right<_Ty1, _Ty2>>> {
using _Uty = remove_cvref_t<_Ty1>;
using type = conditional_t<conjunction_v<is_same<_Uty, remove_cvref_t<_Ty2>>, _Is_scalar_or_array<_Uty>,
disjunction<conjunction<is_lvalue_reference<_Ty1>, is_rvalue_reference<_Ty2>>,
conjunction<is_rvalue_reference<_Ty1>, is_lvalue_reference<_Ty2>>>>,
decay_t<_Copy_cv<remove_reference_t<_Ty1>, remove_reference_t<_Ty2>>>, _Cond_res_if_right<_Ty1, _Ty2>>;
};

template <class _Ty1, class _Ty2>
using _Cond_res = typename _Cond_res_workaround<_Ty1, _Ty2>::type;
#else // ^^^ workaround / no workaround vvv
template <class _Ty1, class _Ty2>
using _Cond_res = // N4810 [meta.trans.other]/2.4
decltype(false ? _Returns_exactly<_Ty1>() : _Returns_exactly<_Ty2>());
#endif // ^^^ no workaround ^^^

template <class...>
struct common_reference;

Expand Down
14 changes: 0 additions & 14 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -256,17 +256,6 @@ std/atomics/atomics.types.generic/copy_semantics_traits.pass.cpp FAIL
# DevCom-409222 "Constructing rvalue reference from non-reference-related lvalue reference"
std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp:0 FAIL

# DevCom-876860 "conditional operator errors" blocks readable<volatile int*>.
std/concepts/concepts.lang/concept.common/common_with.compile.pass.cpp:0 FAIL
std/concepts/concepts.lang/concept.commonref/common_reference.compile.pass.cpp:0 FAIL
std/containers/views/span.cons/iterator_sentinel.pass.cpp:0 FAIL
std/iterators/iterator.requirements/iterator.concepts/iterator.concept.bidir/bidirectional_iterator.compile.pass.cpp:0 FAIL
std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp:0 FAIL
std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp:0 FAIL
std/iterators/iterator.requirements/iterator.concepts/iterator.concept.forward/forward_iterator.compile.pass.cpp:0 FAIL
std/iterators/iterator.requirements/iterator.concepts/iterator.concept.input/input_iterator.compile.pass.cpp:0 FAIL
std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/random_access_iterator.compile.pass.cpp:0 FAIL

# VSO-1271673 "static analyzer doesn't know about short-circuiting"
std/algorithms/alg.sorting/alg.sort/partial.sort/partial_sort.pass.cpp:0 FAIL
std/algorithms/alg.sorting/alg.sort/partial.sort/partial_sort_comp.pass.cpp:0 FAIL
Expand All @@ -284,9 +273,6 @@ std/utilities/utility/pairs/pairs.spec/three_way_comparison.pass.cpp:0 FAIL
# DevCom-1626727: bogus "failure was caused by a conversion from void* to a pointer-to-object type" for conversion to void
std/algorithms/robust_re_difference_type.compile.pass.cpp:0 FAIL

# DevCom-1627396: C1XX's __is_convertible_to intrinsic mis-handles volatile array lvalues
std/concepts/concepts.lang/concept.swappable/swappable_with.compile.pass.cpp:0 FAIL

# DevCom-1628714: C1XX refuses nullptr_t == reference-to-function in a requires expression
std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp:0 FAIL

Expand Down
14 changes: 0 additions & 14 deletions tests/libcxx/skipped_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -256,17 +256,6 @@ atomics\atomics.types.generic\copy_semantics_traits.pass.cpp
# DevCom-409222 "Constructing rvalue reference from non-reference-related lvalue reference"
utilities\meta\meta.unary\meta.unary.prop\is_constructible.pass.cpp

# DevCom-876860 "conditional operator errors" blocks readable<volatile int*>.
concepts\concepts.lang\concept.common\common_with.compile.pass.cpp
concepts\concepts.lang\concept.commonref\common_reference.compile.pass.cpp
containers\views\span.cons\iterator_sentinel.pass.cpp
iterators\iterator.requirements\iterator.concepts\iterator.concept.bidir\bidirectional_iterator.compile.pass.cpp
iterators\iterator.requirements\iterator.concepts\iterator.concept.random.access\contiguous_iterator.compile.pass.cpp
iterators\iterator.requirements\iterator.concepts\iterator.concept.readable\indirectly_readable.compile.pass.cpp
iterators\iterator.requirements\iterator.concepts\iterator.concept.forward\forward_iterator.compile.pass.cpp
iterators\iterator.requirements\iterator.concepts\iterator.concept.input\input_iterator.compile.pass.cpp
iterators\iterator.requirements\iterator.concepts\iterator.concept.random.access\random_access_iterator.compile.pass.cpp

# VSO-1271673 "static analyzer doesn't know about short-circuiting"
algorithms\alg.sorting\alg.sort\partial.sort\partial_sort.pass.cpp
algorithms\alg.sorting\alg.sort\partial.sort\partial_sort_comp.pass.cpp
Expand All @@ -284,9 +273,6 @@ utilities\utility\pairs\pairs.spec\three_way_comparison.pass.cpp
# DevCom-1626727: bogus "failure was caused by a conversion from void* to a pointer-to-object type" for conversion to void
algorithms\robust_re_difference_type.compile.pass.cpp

# DevCom-1627396: C1XX's __is_convertible_to intrinsic mis-handles volatile array lvalues
concepts\concepts.lang\concept.swappable\swappable_with.compile.pass.cpp

# DevCom-1628714: C1XX refuses nullptr_t == reference-to-function in a requires expression
concepts\concepts.compare\concept.equalitycomparable\equality_comparable_with.compile.pass.cpp

Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ tests\GH_002030_asan_annotate_vector
tests\GH_002039_byte_is_not_trivially_swappable
tests\GH_002058_debug_iterator_race
tests\GH_002120_streambuf_seekpos_and_seekoff
tests\GH_002581_common_reference_workaround
tests\LWG2597_complex_branch_cut
tests\LWG3018_shared_ptr_function
tests\LWG3146_excessive_unwrapping_ref_cref
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\strict_concepts_20_matrix.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <cstddef>
#include <iterator>

using namespace std;

struct Test {};
enum Unscoped {};
enum class Scoped {};

// Tests for raw pointers
static_assert(contiguous_iterator<volatile int*>);
static_assert(contiguous_iterator<const volatile int*>);
static_assert(contiguous_iterator<volatile double*>);
static_assert(contiguous_iterator<const volatile double*>);
static_assert(contiguous_iterator<volatile nullptr_t*>);
static_assert(contiguous_iterator<const volatile nullptr_t*>);
static_assert(contiguous_iterator<volatile Unscoped*>);
static_assert(contiguous_iterator<const volatile Unscoped*>);
static_assert(contiguous_iterator<volatile Scoped*>);
static_assert(contiguous_iterator<const volatile Scoped*>);
static_assert(contiguous_iterator<Test* volatile*>);
static_assert(contiguous_iterator<Test* const volatile*>);
static_assert(contiguous_iterator<int Test::*volatile*>);
static_assert(contiguous_iterator<int Test::*const volatile*>);

// Tests for move_iterator specializations
static_assert(input_iterator<move_iterator<volatile int*>>);
static_assert(input_iterator<move_iterator<const volatile int*>>);
static_assert(input_iterator<move_iterator<volatile double*>>);
static_assert(input_iterator<move_iterator<const volatile double*>>);
static_assert(input_iterator<move_iterator<volatile nullptr_t*>>);
static_assert(input_iterator<move_iterator<const volatile nullptr_t*>>);
static_assert(input_iterator<move_iterator<volatile Unscoped*>>);
static_assert(input_iterator<move_iterator<const volatile Unscoped*>>);
static_assert(input_iterator<move_iterator<volatile Scoped*>>);
static_assert(input_iterator<move_iterator<const volatile Scoped*>>);
static_assert(input_iterator<move_iterator<Test* volatile*>>);
static_assert(input_iterator<move_iterator<Test* const volatile*>>);
static_assert(input_iterator<move_iterator<int Test::*volatile*>>);
static_assert(input_iterator<move_iterator<int Test::*const volatile*>>);

int main() {} // COMPILE-ONLY