[llvm-branch-commits] [libcxx] 3c8e31e - [libc++] ADL-proof <functional> by adding _VSTD:: qualification on calls.
Arthur O'Dwyer via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Dec 14 09:14:23 PST 2020
Author: Arthur O'Dwyer
Date: 2020-12-14T12:08:34-05:00
New Revision: 3c8e31e17b85c3d24ade9053d56c1998b4dd28cd
URL: https://github.com/llvm/llvm-project/commit/3c8e31e17b85c3d24ade9053d56c1998b4dd28cd
DIFF: https://github.com/llvm/llvm-project/commit/3c8e31e17b85c3d24ade9053d56c1998b4dd28cd.diff
LOG: [libc++] ADL-proof <functional> by adding _VSTD:: qualification on calls.
- std::reference_wrapper
- std::function
- std::mem_fn
While I'm here, remove _VSTD:: qualification from calls to `declval`
because it takes no arguments and thus isn't susceptible to ADL.
Differential Revision: https://reviews.llvm.org/D92884
Added:
libcxx/test/std/utilities/function.objects/func.memfn/robust_against_adl.pass.cpp
libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/robust_against_adl.pass.cpp
libcxx/test/std/utilities/function.objects/refwrap/refwrap.invoke/robust_against_adl.pass.cpp
Modified:
libcxx/include/__functional_base
libcxx/include/__functional_base_03
libcxx/include/functional
Removed:
################################################################################
diff --git a/libcxx/include/__functional_base b/libcxx/include/__functional_base
index f591bf5a9dce..c84e7eb11567 100644
--- a/libcxx/include/__functional_base
+++ b/libcxx/include/__functional_base
@@ -298,7 +298,7 @@ struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile>
template <class _Tp, class ..._Args>
struct __invoke_return
{
- typedef decltype(__invoke(_VSTD::declval<_Tp>(), _VSTD::declval<_Args>()...)) type;
+ typedef decltype(_VSTD::__invoke(declval<_Tp>(), declval<_Args>()...)) type;
};
#else // defined(_LIBCPP_CXX03_LANG)
@@ -314,27 +314,27 @@ struct __invoke_void_return_wrapper
#ifndef _LIBCPP_CXX03_LANG
template <class ..._Args>
static _Ret __call(_Args&&... __args) {
- return __invoke(_VSTD::forward<_Args>(__args)...);
+ return _VSTD::__invoke(_VSTD::forward<_Args>(__args)...);
}
#else
template <class _Fn>
static _Ret __call(_Fn __f) {
- return __invoke(__f);
+ return _VSTD::__invoke(__f);
}
template <class _Fn, class _A0>
static _Ret __call(_Fn __f, _A0& __a0) {
- return __invoke(__f, __a0);
+ return _VSTD::__invoke(__f, __a0);
}
template <class _Fn, class _A0, class _A1>
static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1) {
- return __invoke(__f, __a0, __a1);
+ return _VSTD::__invoke(__f, __a0, __a1);
}
template <class _Fn, class _A0, class _A1, class _A2>
static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2){
- return __invoke(__f, __a0, __a1, __a2);
+ return _VSTD::__invoke(__f, __a0, __a1, __a2);
}
#endif
};
@@ -345,27 +345,27 @@ struct __invoke_void_return_wrapper<void>
#ifndef _LIBCPP_CXX03_LANG
template <class ..._Args>
static void __call(_Args&&... __args) {
- __invoke(_VSTD::forward<_Args>(__args)...);
+ _VSTD::__invoke(_VSTD::forward<_Args>(__args)...);
}
#else
template <class _Fn>
static void __call(_Fn __f) {
- __invoke(__f);
+ _VSTD::__invoke(__f);
}
template <class _Fn, class _A0>
static void __call(_Fn __f, _A0& __a0) {
- __invoke(__f, __a0);
+ _VSTD::__invoke(__f, __a0);
}
template <class _Fn, class _A0, class _A1>
static void __call(_Fn __f, _A0& __a0, _A1& __a1) {
- __invoke(__f, __a0, __a1);
+ _VSTD::__invoke(__f, __a0, __a1);
}
template <class _Fn, class _A0, class _A1, class _A2>
static void __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2) {
- __invoke(__f, __a0, __a1, __a2);
+ _VSTD::__invoke(__f, __a0, __a1, __a2);
}
#endif
};
@@ -398,112 +398,112 @@ public:
_LIBCPP_INLINE_VISIBILITY
typename __invoke_of<type&, _ArgTypes...>::type
operator() (_ArgTypes&&... __args) const {
- return __invoke(get(), _VSTD::forward<_ArgTypes>(__args)...);
+ return _VSTD::__invoke(get(), _VSTD::forward<_ArgTypes>(__args)...);
}
#else
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return<type>::type
operator() () const {
- return __invoke(get());
+ return _VSTD::__invoke(get());
}
template <class _A0>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return0<type, _A0>::type
operator() (_A0& __a0) const {
- return __invoke(get(), __a0);
+ return _VSTD::__invoke(get(), __a0);
}
template <class _A0>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return0<type, _A0 const>::type
operator() (_A0 const& __a0) const {
- return __invoke(get(), __a0);
+ return _VSTD::__invoke(get(), __a0);
}
template <class _A0, class _A1>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return1<type, _A0, _A1>::type
operator() (_A0& __a0, _A1& __a1) const {
- return __invoke(get(), __a0, __a1);
+ return _VSTD::__invoke(get(), __a0, __a1);
}
template <class _A0, class _A1>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return1<type, _A0 const, _A1>::type
operator() (_A0 const& __a0, _A1& __a1) const {
- return __invoke(get(), __a0, __a1);
+ return _VSTD::__invoke(get(), __a0, __a1);
}
template <class _A0, class _A1>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return1<type, _A0, _A1 const>::type
operator() (_A0& __a0, _A1 const& __a1) const {
- return __invoke(get(), __a0, __a1);
+ return _VSTD::__invoke(get(), __a0, __a1);
}
template <class _A0, class _A1>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return1<type, _A0 const, _A1 const>::type
operator() (_A0 const& __a0, _A1 const& __a1) const {
- return __invoke(get(), __a0, __a1);
+ return _VSTD::__invoke(get(), __a0, __a1);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0, _A1, _A2>::type
operator() (_A0& __a0, _A1& __a1, _A2& __a2) const {
- return __invoke(get(), __a0, __a1, __a2);
+ return _VSTD::__invoke(get(), __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0 const, _A1, _A2>::type
operator() (_A0 const& __a0, _A1& __a1, _A2& __a2) const {
- return __invoke(get(), __a0, __a1, __a2);
+ return _VSTD::__invoke(get(), __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0, _A1 const, _A2>::type
operator() (_A0& __a0, _A1 const& __a1, _A2& __a2) const {
- return __invoke(get(), __a0, __a1, __a2);
+ return _VSTD::__invoke(get(), __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0, _A1, _A2 const>::type
operator() (_A0& __a0, _A1& __a1, _A2 const& __a2) const {
- return __invoke(get(), __a0, __a1, __a2);
+ return _VSTD::__invoke(get(), __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0 const, _A1 const, _A2>::type
operator() (_A0 const& __a0, _A1 const& __a1, _A2& __a2) const {
- return __invoke(get(), __a0, __a1, __a2);
+ return _VSTD::__invoke(get(), __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0 const, _A1, _A2 const>::type
operator() (_A0 const& __a0, _A1& __a1, _A2 const& __a2) const {
- return __invoke(get(), __a0, __a1, __a2);
+ return _VSTD::__invoke(get(), __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0, _A1 const, _A2 const>::type
operator() (_A0& __a0, _A1 const& __a1, _A2 const& __a2) const {
- return __invoke(get(), __a0, __a1, __a2);
+ return _VSTD::__invoke(get(), __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0 const, _A1 const, _A2 const>::type
operator() (_A0 const& __a0, _A1 const& __a1, _A2 const& __a2) const {
- return __invoke(get(), __a0, __a1, __a2);
+ return _VSTD::__invoke(get(), __a0, __a1, __a2);
}
#endif // _LIBCPP_CXX03_LANG
};
diff --git a/libcxx/include/__functional_base_03 b/libcxx/include/__functional_base_03
index e6dac90c84f7..9b08bd26a8fd 100644
--- a/libcxx/include/__functional_base_03
+++ b/libcxx/include/__functional_base_03
@@ -40,7 +40,7 @@ struct __enable_invoke_imp<_Ret, _T1, false, true> {
template <class _Ret, class _T1>
struct __enable_invoke_imp<_Ret, _T1, false, false> {
typedef typename add_lvalue_reference<
- typename __apply_cv<decltype(*_VSTD::declval<_T1>()), _Ret>::type
+ typename __apply_cv<decltype(*declval<_T1>()), _Ret>::type
>::type _Bullet4;
typedef _Bullet4 type;
};
@@ -142,7 +142,7 @@ __invoke(_Fn __f, _T1& __t1) {
template <class _Fp>
inline _LIBCPP_INLINE_VISIBILITY
-decltype(_VSTD::declval<_Fp&>()())
+decltype(declval<_Fp&>()())
__invoke(_Fp& __f)
{
return __f();
@@ -150,7 +150,7 @@ __invoke(_Fp& __f)
template <class _Fp, class _A0>
inline _LIBCPP_INLINE_VISIBILITY
-decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>()))
+decltype(declval<_Fp&>()(declval<_A0&>()))
__invoke(_Fp& __f, _A0& __a0)
{
return __f(__a0);
@@ -158,7 +158,7 @@ __invoke(_Fp& __f, _A0& __a0)
template <class _Fp, class _A0, class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>()))
+decltype(declval<_Fp&>()(declval<_A0&>(), declval<_A1&>()))
__invoke(_Fp& __f, _A0& __a0, _A1& __a1)
{
return __f(__a0, __a1);
@@ -166,7 +166,7 @@ __invoke(_Fp& __f, _A0& __a0, _A1& __a1)
template <class _Fp, class _A0, class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>(), _VSTD::declval<_A2&>()))
+decltype(declval<_Fp&>()(declval<_A0&>(), declval<_A1&>(), declval<_A2&>()))
__invoke(_Fp& __f, _A0& __a0, _A1& __a1, _A2& __a2)
{
return __f(__a0, __a1, __a2);
@@ -181,13 +181,13 @@ struct __invoke_return
template <class _Fp>
struct __invoke_return<_Fp, false>
{
- typedef decltype(__invoke(_VSTD::declval<_Fp&>())) type;
+ typedef decltype(_VSTD::__invoke(declval<_Fp&>())) type;
};
template <class _Tp, class _A0>
struct __invoke_return0
{
- typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>())) type;
+ typedef decltype(_VSTD::__invoke(declval<_Tp&>(), declval<_A0&>())) type;
};
template <class _Rp, class _Tp, class _A0>
@@ -199,8 +199,8 @@ struct __invoke_return0<_Rp _Tp::*, _A0>
template <class _Tp, class _A0, class _A1>
struct __invoke_return1
{
- typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(),
- _VSTD::declval<_A1&>())) type;
+ typedef decltype(_VSTD::__invoke(declval<_Tp&>(), declval<_A0&>(),
+ declval<_A1&>())) type;
};
template <class _Rp, class _Class, class _A0, class _A1>
@@ -211,9 +211,9 @@ struct __invoke_return1<_Rp _Class::*, _A0, _A1> {
template <class _Tp, class _A0, class _A1, class _A2>
struct __invoke_return2
{
- typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(),
- _VSTD::declval<_A1&>(),
- _VSTD::declval<_A2&>())) type;
+ typedef decltype(_VSTD::__invoke(declval<_Tp&>(), declval<_A0&>(),
+ declval<_A1&>(),
+ declval<_A2&>())) type;
};
template <class _Ret, class _Class, class _A0, class _A1, class _A2>
diff --git a/libcxx/include/functional b/libcxx/include/functional
index 6d3d905e6754..a54868e82220 100644
--- a/libcxx/include/functional
+++ b/libcxx/include/functional
@@ -1296,7 +1296,7 @@ public:
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return<type, _ArgTypes...>::type
operator() (_ArgTypes&&... __args) const {
- return __invoke(__f_, _VSTD::forward<_ArgTypes>(__args)...);
+ return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__args)...);
}
#else
@@ -1304,98 +1304,98 @@ public:
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return0<type, _A0>::type
operator() (_A0& __a0) const {
- return __invoke(__f_, __a0);
+ return _VSTD::__invoke(__f_, __a0);
}
template <class _A0>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return0<type, _A0 const>::type
operator() (_A0 const& __a0) const {
- return __invoke(__f_, __a0);
+ return _VSTD::__invoke(__f_, __a0);
}
template <class _A0, class _A1>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return1<type, _A0, _A1>::type
operator() (_A0& __a0, _A1& __a1) const {
- return __invoke(__f_, __a0, __a1);
+ return _VSTD::__invoke(__f_, __a0, __a1);
}
template <class _A0, class _A1>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return1<type, _A0 const, _A1>::type
operator() (_A0 const& __a0, _A1& __a1) const {
- return __invoke(__f_, __a0, __a1);
+ return _VSTD::__invoke(__f_, __a0, __a1);
}
template <class _A0, class _A1>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return1<type, _A0, _A1 const>::type
operator() (_A0& __a0, _A1 const& __a1) const {
- return __invoke(__f_, __a0, __a1);
+ return _VSTD::__invoke(__f_, __a0, __a1);
}
template <class _A0, class _A1>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return1<type, _A0 const, _A1 const>::type
operator() (_A0 const& __a0, _A1 const& __a1) const {
- return __invoke(__f_, __a0, __a1);
+ return _VSTD::__invoke(__f_, __a0, __a1);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0, _A1, _A2>::type
operator() (_A0& __a0, _A1& __a1, _A2& __a2) const {
- return __invoke(__f_, __a0, __a1, __a2);
+ return _VSTD::__invoke(__f_, __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0 const, _A1, _A2>::type
operator() (_A0 const& __a0, _A1& __a1, _A2& __a2) const {
- return __invoke(__f_, __a0, __a1, __a2);
+ return _VSTD::__invoke(__f_, __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0, _A1 const, _A2>::type
operator() (_A0& __a0, _A1 const& __a1, _A2& __a2) const {
- return __invoke(__f_, __a0, __a1, __a2);
+ return _VSTD::__invoke(__f_, __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0, _A1, _A2 const>::type
operator() (_A0& __a0, _A1& __a1, _A2 const& __a2) const {
- return __invoke(__f_, __a0, __a1, __a2);
+ return _VSTD::__invoke(__f_, __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0 const, _A1 const, _A2>::type
operator() (_A0 const& __a0, _A1 const& __a1, _A2& __a2) const {
- return __invoke(__f_, __a0, __a1, __a2);
+ return _VSTD::__invoke(__f_, __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0 const, _A1, _A2 const>::type
operator() (_A0 const& __a0, _A1& __a1, _A2 const& __a2) const {
- return __invoke(__f_, __a0, __a1, __a2);
+ return _VSTD::__invoke(__f_, __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0, _A1 const, _A2 const>::type
operator() (_A0& __a0, _A1 const& __a1, _A2 const& __a2) const {
- return __invoke(__f_, __a0, __a1, __a2);
+ return _VSTD::__invoke(__f_, __a0, __a1, __a2);
}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
typename __invoke_return2<type, _A0 const, _A1 const, _A2 const>::type
operator() (_A0 const& __a0, _A1 const& __a1, _A2 const& __a2) const {
- return __invoke(__f_, __a0, __a1, __a2);
+ return _VSTD::__invoke(__f_, __a0, __a1, __a2);
}
#endif
};
@@ -2303,7 +2303,7 @@ public:
}
virtual _Rp operator()(_ArgTypes&& ... __arg) {
- return __invoke(__f_, _VSTD::forward<_ArgTypes>(__arg)...);
+ return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__arg)...);
}
#ifndef _LIBCPP_NO_RTTI
diff --git a/libcxx/test/std/utilities/function.objects/func.memfn/robust_against_adl.pass.cpp b/libcxx/test/std/utilities/function.objects/func.memfn/robust_against_adl.pass.cpp
new file mode 100644
index 000000000000..2bb8e9f49209
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/func.memfn/robust_against_adl.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <functional>
+
+#include <functional>
+
+#include "test_macros.h"
+
+struct Incomplete;
+template<class T> struct Holder { T t; };
+typedef Holder<Incomplete> *Ptr;
+
+struct A {
+ Ptr no_args() const { return nullptr; }
+ Ptr one_arg(Ptr p) const { return p; }
+ void one_arg_void(Ptr) const { }
+};
+
+int main(int, char**)
+{
+ A a;
+ A *pa = &a;
+ const A *cpa = &a;
+ Ptr x = nullptr;
+ const Ptr cx = nullptr;
+ std::mem_fn(&A::no_args)(a);
+ std::mem_fn(&A::no_args)(pa);
+ std::mem_fn(&A::no_args)(*cpa);
+ std::mem_fn(&A::no_args)(cpa);
+ std::mem_fn(&A::one_arg)(a, x);
+ std::mem_fn(&A::one_arg)(pa, x);
+ std::mem_fn(&A::one_arg)(a, cx);
+ std::mem_fn(&A::one_arg)(pa, cx);
+ std::mem_fn(&A::one_arg)(*cpa, x);
+ std::mem_fn(&A::one_arg)(cpa, x);
+ std::mem_fn(&A::one_arg)(*cpa, cx);
+ std::mem_fn(&A::one_arg)(cpa, cx);
+ std::mem_fn(&A::one_arg_void)(a, x);
+ std::mem_fn(&A::one_arg_void)(pa, x);
+ std::mem_fn(&A::one_arg_void)(a, cx);
+ std::mem_fn(&A::one_arg_void)(pa, cx);
+ std::mem_fn(&A::one_arg_void)(*cpa, x);
+ std::mem_fn(&A::one_arg_void)(cpa, x);
+ std::mem_fn(&A::one_arg_void)(*cpa, cx);
+ std::mem_fn(&A::one_arg_void)(cpa, cx);
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/robust_against_adl.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/robust_against_adl.pass.cpp
new file mode 100644
index 000000000000..f831ec7986c5
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/robust_against_adl.pass.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// <functional>
+
+#include <functional>
+
+#include "test_macros.h"
+
+struct Incomplete;
+template<class T> struct Holder { T t; };
+typedef Holder<Incomplete> *Ptr;
+
+Ptr no_args() { return nullptr; }
+Ptr one_arg(Ptr p) { return p; }
+Ptr two_args(Ptr p, Ptr) { return p; }
+Ptr three_args(Ptr p, Ptr, Ptr) { return p; }
+Ptr four_args(Ptr p, Ptr, Ptr, Ptr) { return p; }
+
+void one_arg_void(Ptr) { }
+
+int main(int, char**)
+{
+ Ptr x = nullptr;
+ std::function<Ptr()> f(no_args); f();
+ std::function<Ptr(Ptr)> g(one_arg); g(x);
+ std::function<void(Ptr)> h(one_arg_void); h(x);
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/function.objects/refwrap/refwrap.invoke/robust_against_adl.pass.cpp b/libcxx/test/std/utilities/function.objects/refwrap/refwrap.invoke/robust_against_adl.pass.cpp
new file mode 100644
index 000000000000..2774401b052b
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/refwrap/refwrap.invoke/robust_against_adl.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <functional>
+
+#include <functional>
+
+#include "test_macros.h"
+
+struct Incomplete;
+template<class T> struct Holder { T t; };
+typedef Holder<Incomplete> *Ptr;
+
+Ptr no_args() { return nullptr; }
+Ptr one_arg(Ptr p) { return p; }
+Ptr two_args(Ptr p, Ptr) { return p; }
+Ptr three_args(Ptr p, Ptr, Ptr) { return p; }
+
+void one_arg_void(Ptr) { }
+
+int main(int, char**)
+{
+ Ptr x = nullptr;
+ const Ptr cx = nullptr;
+ std::ref(no_args)();
+ std::ref(one_arg)(x);
+ std::ref(one_arg)(cx);
+ std::ref(two_args)(x, x);
+ std::ref(two_args)(x, cx);
+ std::ref(two_args)(cx, x);
+ std::ref(two_args)(cx, cx);
+ std::ref(three_args)(x, x, x);
+ std::ref(three_args)(x, x, cx);
+ std::ref(three_args)(x, cx, x);
+ std::ref(three_args)(cx, x, x);
+ std::ref(three_args)(x, cx, cx);
+ std::ref(three_args)(cx, x, cx);
+ std::ref(three_args)(cx, cx, x);
+ std::ref(three_args)(cx, cx, cx);
+ std::ref(one_arg_void)(x);
+ std::ref(one_arg_void)(cx);
+
+ return 0;
+}
More information about the llvm-branch-commits
mailing list