[libc++] Fix ambiguous constructors for std::complex and std::optional (#103409)
Fixes #101960 (cherry picked from commit 4d08bb11eea5907fa9cdfe4c7bc9d5c91e79c6a7)
This commit is contained in:
parent
67b06b4297
commit
4d4a4100f6
@ -421,7 +421,8 @@ public:
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(float __re = 0.0f, float __im = 0.0f) : __re_(__re), __im_(__im) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(__from_builtin_tag, _Complex float __v)
|
||||
template <class _Tag, __enable_if_t<_IsSame<_Tag, __from_builtin_tag>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit complex(_Tag, _Complex float __v)
|
||||
: __re_(__real__ __v), __im_(__imag__ __v) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI explicit _LIBCPP_CONSTEXPR complex(const complex<double>& __c);
|
||||
@ -517,7 +518,8 @@ public:
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(double __re = 0.0, double __im = 0.0) : __re_(__re), __im_(__im) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(__from_builtin_tag, _Complex double __v)
|
||||
template <class _Tag, __enable_if_t<_IsSame<_Tag, __from_builtin_tag>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit complex(_Tag, _Complex double __v)
|
||||
: __re_(__real__ __v), __im_(__imag__ __v) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(const complex<float>& __c);
|
||||
@ -617,7 +619,8 @@ public:
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(long double __re = 0.0L, long double __im = 0.0L)
|
||||
: __re_(__re), __im_(__im) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(__from_builtin_tag, _Complex long double __v)
|
||||
template <class _Tag, __enable_if_t<_IsSame<_Tag, __from_builtin_tag>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit complex(_Tag, _Complex long double __v)
|
||||
: __re_(__real__ __v), __im_(__imag__ __v) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(const complex<float>& __c);
|
||||
|
@ -301,7 +301,7 @@ struct __optional_destruct_base<_Tp, false> {
|
||||
|
||||
# if _LIBCPP_STD_VER >= 23
|
||||
template <class _Fp, class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base(
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(
|
||||
__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
|
||||
: __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {}
|
||||
# endif
|
||||
@ -707,8 +707,11 @@ public:
|
||||
}
|
||||
|
||||
# if _LIBCPP_STD_VER >= 23
|
||||
template <class _Fp, class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
|
||||
template <class _Tag,
|
||||
class _Fp,
|
||||
class... _Args,
|
||||
__enable_if_t<_IsSame<_Tag, __optional_construct_from_invoke_tag>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Tag, _Fp&& __f, _Args&&... __args)
|
||||
: __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {}
|
||||
# endif
|
||||
|
||||
|
@ -0,0 +1,38 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <complex>
|
||||
|
||||
// Regression test for https://github.com/llvm/llvm-project/issues/101960 where we used to
|
||||
// trigger an ambiguous constructor.
|
||||
|
||||
#include <complex>
|
||||
#include <cassert>
|
||||
|
||||
struct NastyConvertible {
|
||||
template <class T>
|
||||
operator T() const {
|
||||
return T(0);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void test() {
|
||||
NastyConvertible nasty;
|
||||
std::complex<T> x(nasty, nasty);
|
||||
assert(x.real() == T(0));
|
||||
assert(x.imag() == T(0));
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<float>();
|
||||
test<double>();
|
||||
test<long double>();
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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, c++11, c++14
|
||||
|
||||
// <optional>
|
||||
|
||||
// Regression test for https://github.com/llvm/llvm-project/issues/101960 where a constructor
|
||||
// of std::optional that should have been private was instead publicly available.
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
struct NastyConvertible {
|
||||
template <class T>
|
||||
operator T() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
using F = int(int);
|
||||
|
||||
static_assert(!std::is_constructible<std::optional<int>, NastyConvertible, int(int), int>::value);
|
Loading…
x
Reference in New Issue
Block a user