Restrict ADL for `reference_wrapper` and `thread` (#3101)

Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
This commit is contained in:
A. Jiang 2022-10-12 21:13:50 +08:00 коммит произвёл GitHub
Родитель fe9f8587e0
Коммит 6128830457
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 51 добавлений и 46 удалений

Просмотреть файл

@ -51,7 +51,7 @@ private:
static unsigned int __stdcall _Invoke(void* _RawVals) noexcept /* terminates */ {
// adapt invoke of user's callable object to _beginthreadex's thread procedure
const unique_ptr<_Tuple> _FnVals(static_cast<_Tuple*>(_RawVals));
_Tuple& _Tup = *_FnVals;
_Tuple& _Tup = *_FnVals.get(); // avoid ADL, handle incomplete types
_STD invoke(_STD move(_STD get<_Indices>(_Tup))...);
_Cnd_do_broadcast_at_thread_exit(); // TRANSITION, ABI
return 0;
@ -311,7 +311,7 @@ public:
jthread& operator=(jthread&& _Other) noexcept {
// note: the standard specifically disallows making self-move-assignment a no-op here
// N4861 [thread.jthread.cons]/13
// N4917 33.4.4.2 [thread.jthread.cons]/12
// Effects: If joinable() is true, calls request_stop() and then join(). Assigns the state
// of x to *this and sets x to a default constructed state.
_Try_cancel_and_join();

Просмотреть файл

@ -140,7 +140,7 @@ using add_rvalue_reference_t = typename _Add_reference<_Ty>::_Rvalue;
_EXPORT_STD template <class _Ty>
add_rvalue_reference_t<_Ty> declval() noexcept {
static_assert(_Always_false<_Ty>, "Calling declval is ill-formed, see N4892 [declval]/2.");
static_assert(_Always_false<_Ty>, "Calling declval is ill-formed, see N4917 22.2.6 [declval]/2.");
}
_EXPORT_STD template <class _Ty>
@ -1189,8 +1189,8 @@ using _Conditional_type = decltype(false ? _STD declval<_Ty1>() : _STD declval<_
template <class _Ty1, class _Ty2, class = void>
struct _Const_lvalue_cond_oper {};
// N4810 [meta.trans.other]/3.3.4 (per the proposed resolution of LWG-3205): "Otherwise, if remove_cvref_t</**/> denotes
// a type..."
// N4917 21.3.8.7 [meta.trans.other]/3.3.4 (per the proposed resolution of LWG-3205): "Otherwise, if
// remove_cvref_t</**/> denotes a type..."
template <class _Ty1, class _Ty2>
struct _Const_lvalue_cond_oper<_Ty1, _Ty2, void_t<_Conditional_type<const _Ty1&, const _Ty2&>>> {
using type = remove_cvref_t<_Conditional_type<const _Ty1&, const _Ty2&>>;
@ -1267,11 +1267,11 @@ struct _Copy_cv_impl<const volatile _From> {
using _Apply = const volatile _To;
};
template <class _From, class _To>
using _Copy_cv = // N4810 [meta.trans.other]/2.3
using _Copy_cv = // N4917 21.3.8.7 [meta.trans.other]/2.3
typename _Copy_cv_impl<_From>::template _Apply<_To>;
template <class _Ty1>
struct _Add_qualifiers { // _Add_qualifiers<A>::template _Apply is XREF(A) from N4810 [meta.trans.other]/2.1
struct _Add_qualifiers { // _Add_qualifiers<A>::template _Apply is XREF(A) from N4917 21.3.8.7 [meta.trans.other]/2.2
template <class _Ty2>
using _Apply = _Copy_cv<_Ty1, _Ty2>;
};
@ -1288,7 +1288,7 @@ struct _Add_qualifiers<_Ty1&&> {
#if !defined(__EDG__) && !defined(__clang__) // TRANSITION, DevCom-10095944
template <class _Ty1, class _Ty2>
using _Cond_res_if_right = // N4810 [meta.trans.other]/2.4
using _Cond_res_if_right = // N4917 21.3.8.7 [meta.trans.other]/2.4
decltype(false ? _Returns_exactly<_Ty1>() : _Returns_exactly<_Ty2>());
template <class _Ty>
@ -1310,7 +1310,7 @@ 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
using _Cond_res = // N4917 21.3.8.7 [meta.trans.other]/2.4
decltype(false ? _Returns_exactly<_Ty1>() : _Returns_exactly<_Ty2>());
#endif // ^^^ no workaround ^^^
@ -1320,30 +1320,30 @@ struct common_reference;
_EXPORT_STD template <class... _Types>
using common_reference_t = typename common_reference<_Types...>::type;
// N4810 [meta.trans.other]/5.1: "If sizeof...(T) is zero ..."
// N4917 21.3.8.7 [meta.trans.other]/5.1: "If sizeof...(T) is zero ..."
template <>
struct common_reference<> {};
// N4810 [meta.trans.other]/5.2: "...if sizeof...(T) is one ..."
// N4917 21.3.8.7 [meta.trans.other]/5.2: "...if sizeof...(T) is one ..."
template <class _Ty>
struct common_reference<_Ty> {
using type = _Ty;
};
// N4810 [meta.trans.other]/5.3: "...if sizeof...(T) is two..."
// N4917 21.3.8.7 [meta.trans.other]/5.3: "...if sizeof...(T) is two..."
// N4810 [meta.trans.other]/5.3.4: "if common_type_t<T1, T2> is well-formed..."
// N4810 [meta.trans.other]/5.3.5: "Otherwise, there shall be no member type."
// N4917 21.3.8.7 [meta.trans.other]/5.3.4: "if common_type_t<T1, T2> is well-formed..."
// N4917 21.3.8.7 [meta.trans.other]/5.3.5: "Otherwise, there shall be no member type."
template <class _Ty1, class _Ty2, class = void>
struct _Common_reference2C : common_type<_Ty1, _Ty2> {};
// N4810 [meta.trans.other]/5.3.3: "if COND_RES(T1, T2) is well-formed..."
// N4917 21.3.8.7 [meta.trans.other]/5.3.3: "if COND_RES(T1, T2) is well-formed..."
template <class _Ty1, class _Ty2>
struct _Common_reference2C<_Ty1, _Ty2, void_t<_Cond_res<_Ty1, _Ty2>>> {
using type = _Cond_res<_Ty1, _Ty2>;
};
// N4810 [meta.trans.other]/5.3.2: "if basic_common_reference<[...]>::type is well-formed..."
// N4917 21.3.8.7 [meta.trans.other]/5.3.2: "if basic_common_reference<[...]>::type is well-formed..."
template <class _Ty1, class _Ty2>
using _Basic_specialization = typename basic_common_reference<remove_cvref_t<_Ty1>, remove_cvref_t<_Ty2>,
_Add_qualifiers<_Ty1>::template _Apply, _Add_qualifiers<_Ty2>::template _Apply>::type;
@ -1356,7 +1356,7 @@ struct _Common_reference2B<_Ty1, _Ty2, void_t<_Basic_specialization<_Ty1, _Ty2>>
using type = _Basic_specialization<_Ty1, _Ty2>;
};
// N4810 [meta.trans.other]/5.3.1: "If T1 and T2 are reference types and COMMON_REF(T1, T2) is well-formed..."
// N4917 21.3.8.7 [meta.trans.other]/5.3.1: "If T1 and T2 are reference types and COMMON_REF(T1, T2) is well-formed..."
template <class _Ty1, class _Ty2, class = void>
struct _Common_reference2A : _Common_reference2B<_Ty1, _Ty2> {};
@ -1366,17 +1366,19 @@ using _LL_common_ref = _Result;
template <class _Ty1, class _Ty2>
struct _Common_reference2A<_Ty1&, _Ty2&, void_t<_LL_common_ref<_Ty1, _Ty2>>> {
using type = _LL_common_ref<_Ty1, _Ty2>; // "both lvalues" case from N4810 [meta.trans.other]/2.5
using type = _LL_common_ref<_Ty1, _Ty2>; // "both lvalues" case from N4917 21.3.8.7 [meta.trans.other]/2.5
};
template <class _Ty1, class _Ty2>
struct _Common_reference2A<_Ty1&&, _Ty2&, enable_if_t<is_convertible_v<_Ty1&&, _LL_common_ref<const _Ty1, _Ty2>>>> {
using type = _LL_common_ref<const _Ty1, _Ty2>; // "rvalue and lvalue" case from N4810 [meta.trans.other]/2.7
using type =
_LL_common_ref<const _Ty1, _Ty2>; // "rvalue and lvalue" case from N4917 21.3.8.7 [meta.trans.other]/2.7
};
template <class _Ty1, class _Ty2>
struct _Common_reference2A<_Ty1&, _Ty2&&, enable_if_t<is_convertible_v<_Ty2&&, _LL_common_ref<const _Ty2, _Ty1>>>> {
using type = _LL_common_ref<const _Ty2, _Ty1>; // "lvalue and rvalue" case from N4810 [meta.trans.other]/2.8
using type =
_LL_common_ref<const _Ty2, _Ty1>; // "lvalue and rvalue" case from N4917 21.3.8.7 [meta.trans.other]/2.8
};
template <class _Ty1, class _Ty2>
@ -1386,13 +1388,13 @@ template <class _Ty1, class _Ty2>
struct _Common_reference2A<_Ty1&&, _Ty2&&,
enable_if_t<
is_convertible_v<_Ty1&&, _RR_common_ref<_Ty1, _Ty2>> && is_convertible_v<_Ty2&&, _RR_common_ref<_Ty1, _Ty2>>>> {
using type = _RR_common_ref<_Ty1, _Ty2>; // "both rvalues" case from N4810 [meta.trans.other]/2.6
using type = _RR_common_ref<_Ty1, _Ty2>; // "both rvalues" case from N4917 21.3.8.7 [meta.trans.other]/2.6
};
template <class _Ty1, class _Ty2>
struct common_reference<_Ty1, _Ty2> : _Common_reference2A<_Ty1, _Ty2> {};
// N4810 [meta.trans.other]/5.4: "if sizeof...(T) is greater than two..."
// N4917 21.3.8.7 [meta.trans.other]/5.4: "if sizeof...(T) is greater than two..."
template <class _Void, class _Ty1, class _Ty2, class... _Types>
struct _Fold_common_reference {};
template <class _Ty1, class _Ty2, class... _Types>
@ -1448,8 +1450,9 @@ _EXPORT_STD template <class _Ty>
class reference_wrapper;
// std::invoke isn't constexpr in C++17, and normally implementers are forbidden from "strengthening" constexpr
// (WG21-N4842 [constexpr.functions]/1), yet both std::apply and std::visit are required to be constexpr and have
// invoke-like behavior. As a result, we've chosen to apply the part of P1065R2 resolving LWG-2894 as a defect report.
// (WG21-N4917 16.4.6.7 [constexpr.functions]/1), yet both std::apply and std::visit are required to be constexpr and
// have invoke-like behavior. As a result, we've chosen to apply the part of P1065R2 resolving LWG-2894 as a defect
// report.
enum class _Invoker_strategy {
_Functor,
@ -1854,7 +1857,8 @@ template <class _Ty, class _Uty, class = void>
struct _Refwrap_has_ctor_from : false_type {};
template <class _Ty, class _Uty>
struct _Refwrap_has_ctor_from<_Ty, _Uty, void_t<decltype(_Refwrap_ctor_fun<_Ty>(_STD declval<_Uty>()))>> : true_type {};
struct _Refwrap_has_ctor_from<_Ty, _Uty, void_t<decltype(_STD _Refwrap_ctor_fun<_Ty>(_STD declval<_Uty>()))>>
: true_type {}; // _STD _Refwrap_ctor_fun is qualified: avoid ADL, handle incomplete types
_EXPORT_STD template <class _Ty>
class reference_wrapper
@ -1871,7 +1875,8 @@ public:
template <class _Uty, enable_if_t<conjunction_v<negation<is_same<_Remove_cvref_t<_Uty>, reference_wrapper>>,
_Refwrap_has_ctor_from<_Ty, _Uty>>,
int> = 0>
_CONSTEXPR20 reference_wrapper(_Uty&& _Val) noexcept(noexcept(_Refwrap_ctor_fun<_Ty>(_STD declval<_Uty>()))) {
_CONSTEXPR20 reference_wrapper(_Uty&& _Val) noexcept(
noexcept(_STD _Refwrap_ctor_fun<_Ty>(_STD declval<_Uty>()))) { // qualified: avoid ADL, handle incomplete types
_Ty& _Ref = static_cast<_Uty&&>(_Val);
_Ptr = _STD addressof(_Ref);
}

Просмотреть файл

@ -369,15 +369,19 @@ std/utilities/meta/meta.trans/meta.trans.other/aligned_storage.pass.cpp FAIL
std/depr/depr.c.headers/math_h.pass.cpp FAIL
std/numerics/c.math/cmath.pass.cpp FAIL
# GH-2358: <filesystem>: path's comparison operators are IF-NDR
std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp FAIL
# GH-1374: Spaceship CPO wording in [cmp.alg] needs an overhaul
# (Technically an STL bug until the wording in the working draft is fixed to agree.)
std/language.support/cmp/cmp.alg/partial_order.pass.cpp FAIL
std/language.support/cmp/cmp.alg/strong_order.pass.cpp FAIL
std/language.support/cmp/cmp.alg/weak_order.pass.cpp FAIL
# GH-1596: <algorithm>: unqualified calls to _Adl_verify_range incorrectly cause instantiation
std/algorithms/robust_against_adl.compile.pass.cpp FAIL
std/strings/basic.string/string.modifiers/robust_against_adl.pass.cpp FAIL
# GH-3100: <memory> etc.: ADL should be avoided when calling _Construct_in_place and its friends
std/utilities/function.objects/func.wrap/func.wrap.func/robust_against_adl.pass.cpp FAIL
# *** CRT BUGS ***
# We're permanently missing aligned_alloc().
@ -581,6 +585,9 @@ std/utilities/format/format.functions/locale-specific_form.pass.cpp FAIL
# libc++ chose option A for [time.clock.file.members], and we chose option B.
std/time/time.clock/time.clock.file/to_from_sys.pass.cpp FAIL
# libc++'s filesystem::path::iterator model bidirectional_iterator, which is not guaranteed by the Standard
std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp FAIL
# libc++ is missing various Ranges DRs
std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp FAIL
@ -781,13 +788,6 @@ std/re/re.const/re.matchflag/match_prev_avail.pass.cpp FAIL
# Not yet analyzed. Many diagnostics.
std/input.output/filesystems/class.path/path.member/path.charconv.pass.cpp FAIL
# Not yet analyzed. Probably ADL shenanigans.
std/algorithms/robust_against_adl.compile.pass.cpp FAIL
std/strings/basic.string/string.modifiers/robust_against_adl.pass.cpp FAIL
std/thread/thread.threads/thread.thread.class/thread.thread.constr/robust_against_adl.pass.cpp FAIL
std/utilities/function.objects/func.wrap/func.wrap.func/robust_against_adl.pass.cpp FAIL
std/utilities/function.objects/refwrap/refwrap.invoke/robust_against_adl.pass.cpp FAIL
# Not yet analyzed. Possibly C1XX constexpr bug.
std/utilities/function.objects/func.invoke/invoke_constexpr.pass.cpp:0 FAIL

Просмотреть файл

@ -370,15 +370,19 @@ utilities\meta\meta.trans\meta.trans.other\aligned_storage.pass.cpp
depr\depr.c.headers\math_h.pass.cpp
numerics\c.math\cmath.pass.cpp
# GH-2358: <filesystem>: path's comparison operators are IF-NDR
input.output\filesystems\class.path\range_concept_conformance.compile.pass.cpp
# GH-1374: Spaceship CPO wording in [cmp.alg] needs an overhaul
# (Technically an STL bug until the wording in the working draft is fixed to agree.)
language.support\cmp\cmp.alg\partial_order.pass.cpp
language.support\cmp\cmp.alg\strong_order.pass.cpp
language.support\cmp\cmp.alg\weak_order.pass.cpp
# GH-1596: <algorithm>: unqualified calls to _Adl_verify_range incorrectly cause instantiation
algorithms\robust_against_adl.compile.pass.cpp
strings\basic.string\string.modifiers\robust_against_adl.pass.cpp
# GH-3100: <memory> etc.: ADL should be avoided when calling _Construct_in_place and its friends
utilities\function.objects\func.wrap\func.wrap.func\robust_against_adl.pass.cpp
# *** CRT BUGS ***
# We're permanently missing aligned_alloc().
@ -582,6 +586,9 @@ utilities\format\format.functions\locale-specific_form.pass.cpp
# libc++ chose option A for [time.clock.file.members], and we chose option B.
time\time.clock\time.clock.file\to_from_sys.pass.cpp
# libc++'s filesystem::path::iterator model bidirectional_iterator, which is not guaranteed by the Standard
input.output\filesystems\class.path\range_concept_conformance.compile.pass.cpp
# libc++ is missing various Ranges DRs
language.support\support.limits\support.limits.general\ranges.version.compile.pass.cpp
@ -782,13 +789,6 @@ re\re.const\re.matchflag\match_prev_avail.pass.cpp
# Not yet analyzed. Many diagnostics.
input.output\filesystems\class.path\path.member\path.charconv.pass.cpp
# Not yet analyzed. Probably ADL shenanigans.
algorithms\robust_against_adl.compile.pass.cpp
strings\basic.string\string.modifiers\robust_against_adl.pass.cpp
thread\thread.threads\thread.thread.class\thread.thread.constr\robust_against_adl.pass.cpp
utilities\function.objects\func.wrap\func.wrap.func\robust_against_adl.pass.cpp
utilities\function.objects\refwrap\refwrap.invoke\robust_against_adl.pass.cpp
# Not yet analyzed. Possibly C1XX constexpr bug.
utilities\function.objects\func.invoke\invoke_constexpr.pass.cpp