forked from OSchip/llvm-project
[libc++] Enable `explicit` conversion operators, even in C++03 mode.
C++03 didn't support `explicit` conversion operators; but Clang's C++03 mode does, as an extension, so we can use it. This lets us make the conversion explicit in `std::function` (even in '03), and remove some silly metaprogramming in `std::basic_ios`. Drive-by improvements to the tests for these operators, in addition to making sure all these tests also run in `c++03` mode. Differential Revision: https://reviews.llvm.org/D104682
This commit is contained in:
parent
2e120920ac
commit
317e92a3e8
|
@ -874,13 +874,6 @@ typedef unsigned int char32_t;
|
|||
# define _LIBCPP_NOALIAS
|
||||
#endif
|
||||
|
||||
#if __has_feature(cxx_explicit_conversions) || defined(__IBMCPP__) || \
|
||||
(!defined(_LIBCPP_CXX03_LANG) && defined(__GNUC__)) // All supported GCC versions
|
||||
# define _LIBCPP_EXPLICIT explicit
|
||||
#else
|
||||
# define _LIBCPP_EXPLICIT
|
||||
#endif
|
||||
|
||||
#if __has_attribute(using_if_exists)
|
||||
# define _LIBCPP_USING_IF_EXISTS __attribute__((using_if_exists))
|
||||
#else
|
||||
|
|
|
@ -493,7 +493,7 @@ public:
|
|||
{function(allocator_arg, __a, __f).swap(*this);}
|
||||
|
||||
// 20.7.16.2.3, function capacity:
|
||||
_LIBCPP_INLINE_VISIBILITY operator bool() const {return __f_;}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit operator bool() const {return __f_;}
|
||||
|
||||
private:
|
||||
// deleted overloads close possible hole in the type system
|
||||
|
@ -773,7 +773,7 @@ public:
|
|||
{function(allocator_arg, __a, __f).swap(*this);}
|
||||
|
||||
// 20.7.16.2.3, function capacity:
|
||||
_LIBCPP_INLINE_VISIBILITY operator bool() const {return __f_;}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit operator bool() const {return __f_;}
|
||||
|
||||
private:
|
||||
// deleted overloads close possible hole in the type system
|
||||
|
@ -1053,7 +1053,7 @@ public:
|
|||
{function(allocator_arg, __a, __f).swap(*this);}
|
||||
|
||||
// 20.7.16.2.3, function capacity:
|
||||
operator bool() const {return __f_;}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit operator bool() const {return __f_;}
|
||||
|
||||
private:
|
||||
// deleted overloads close possible hole in the type system
|
||||
|
@ -1332,7 +1332,7 @@ public:
|
|||
{function(allocator_arg, __a, __f).swap(*this);}
|
||||
|
||||
// 20.7.16.2.3, function capacity:
|
||||
_LIBCPP_INLINE_VISIBILITY operator bool() const {return __f_;}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit operator bool() const {return __f_;}
|
||||
|
||||
private:
|
||||
// deleted overloads close possible hole in the type system
|
||||
|
|
|
@ -588,7 +588,7 @@ public:
|
|||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool unique() const _NOEXCEPT {return use_count() == 1;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return get() != nullptr;}
|
||||
explicit operator bool() const _NOEXCEPT {return get() != nullptr;}
|
||||
template <class _Up>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool owner_before(shared_ptr<_Up> const& __p) const _NOEXCEPT
|
||||
|
|
|
@ -296,7 +296,7 @@ public:
|
|||
return __ptr_.second();
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {
|
||||
explicit operator bool() const _NOEXCEPT {
|
||||
return __ptr_.first() != nullptr;
|
||||
}
|
||||
|
||||
|
@ -517,7 +517,7 @@ public:
|
|||
return __ptr_.second();
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {
|
||||
explicit operator bool() const _NOEXCEPT {
|
||||
return __ptr_.first() != nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -189,8 +189,7 @@ public:
|
|||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool owns_lock() const _NOEXCEPT {return __owns_;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_EXPLICIT
|
||||
operator bool () const _NOEXCEPT {return __owns_;}
|
||||
explicit operator bool() const _NOEXCEPT {return __owns_;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
mutex_type* mutex() const _NOEXCEPT {return __m_;}
|
||||
};
|
||||
|
|
|
@ -151,7 +151,7 @@ public:
|
|||
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
|
||||
~exception_ptr() _NOEXCEPT;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT
|
||||
_LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT
|
||||
{return __ptr_ != nullptr;}
|
||||
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
|
@ -205,7 +205,7 @@ public:
|
|||
exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT;
|
||||
exception_ptr& operator=(nullptr_t) _NOEXCEPT;
|
||||
~exception_ptr() _NOEXCEPT;
|
||||
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT;
|
||||
explicit operator bool() const _NOEXCEPT;
|
||||
};
|
||||
|
||||
_LIBCPP_FUNC_VIS
|
||||
|
|
|
@ -2111,7 +2111,7 @@ template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)>
|
|||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT { return __f_ != nullptr; }
|
||||
explicit operator bool() const _NOEXCEPT { return __f_ != nullptr; }
|
||||
|
||||
#ifndef _LIBCPP_NO_RTTI
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
|
@ -2597,7 +2597,7 @@ public:
|
|||
|
||||
// function capacity:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {
|
||||
explicit operator bool() const _NOEXCEPT {
|
||||
return static_cast<bool>(__f_);
|
||||
}
|
||||
|
||||
|
|
|
@ -591,13 +591,6 @@ ios_base::exceptions(iostate __iostate)
|
|||
clear(__rdstate_);
|
||||
}
|
||||
|
||||
#if defined(_LIBCPP_CXX03_LANG)
|
||||
struct _LIBCPP_TYPE_VIS __cxx03_bool {
|
||||
typedef void (__cxx03_bool::*__bool_type)();
|
||||
void __true_value() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
class _LIBCPP_TEMPLATE_VIS basic_ios
|
||||
: public ios_base
|
||||
|
@ -614,18 +607,8 @@ public:
|
|||
static_assert((is_same<_CharT, typename traits_type::char_type>::value),
|
||||
"traits_type::char_type must be the same type as CharT");
|
||||
|
||||
// __true_value will generate undefined references when linking unless
|
||||
// we give it internal linkage.
|
||||
|
||||
#if defined(_LIBCPP_CXX03_LANG)
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
operator __cxx03_bool::__bool_type() const {
|
||||
return !fail() ? &__cxx03_bool::__true_value : nullptr;
|
||||
}
|
||||
#else
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_EXPLICIT operator bool() const {return !fail();}
|
||||
#endif
|
||||
explicit operator bool() const {return !fail();}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY bool operator!() const {return fail();}
|
||||
_LIBCPP_INLINE_VISIBILITY iostate rdstate() const {return ios_base::rdstate();}
|
||||
|
|
|
@ -302,8 +302,7 @@ public:
|
|||
// ~sentry() = default;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_EXPLICIT
|
||||
operator bool() const {return __ok_;}
|
||||
explicit operator bool() const {return __ok_;}
|
||||
};
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
|
|
|
@ -254,8 +254,7 @@ public:
|
|||
~sentry();
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_EXPLICIT
|
||||
operator bool() const {return __ok_;}
|
||||
explicit operator bool() const {return __ok_;}
|
||||
};
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
|
|
|
@ -291,8 +291,7 @@ public:
|
|||
string message() const;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_EXPLICIT
|
||||
operator bool() const _NOEXCEPT {return __val_ != 0;}
|
||||
explicit operator bool() const _NOEXCEPT {return __val_ != 0;}
|
||||
};
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
|
@ -368,8 +367,7 @@ public:
|
|||
string message() const;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_EXPLICIT
|
||||
operator bool() const _NOEXCEPT {return __val_ != 0;}
|
||||
explicit operator bool() const _NOEXCEPT {return __val_ != 0;}
|
||||
};
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// XFAIL: c++03
|
||||
|
||||
// <system_error>
|
||||
|
||||
// class error_code
|
||||
|
||||
// explicit operator bool() const;
|
||||
|
||||
#include <system_error>
|
||||
|
||||
bool test_func(void)
|
||||
{
|
||||
const std::error_code ec(0, std::generic_category());
|
||||
return ec; // conversion to bool is explicit; should fail.
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -13,13 +13,17 @@
|
|||
// explicit operator bool() const;
|
||||
|
||||
#include <system_error>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
static_assert(std::is_constructible<bool, std::error_code>::value, "");
|
||||
static_assert(!std::is_convertible<std::error_code, bool>::value, "");
|
||||
|
||||
{
|
||||
const std::error_code ec(6, std::generic_category());
|
||||
assert(static_cast<bool>(ec));
|
||||
|
|
|
@ -27,9 +27,7 @@ int main(int, char**)
|
|||
static_assert((!std::is_convertible<std::ios, void*>::value), "");
|
||||
static_assert((!std::is_convertible<std::ios, int>::value), "");
|
||||
static_assert((!std::is_convertible<std::ios const&, int>::value), "");
|
||||
#if TEST_STD_VER >= 11
|
||||
static_assert((!std::is_convertible<std::ios, bool>::value), "");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <exception>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
|
@ -33,5 +34,5 @@ int main(int, char**)
|
|||
p3 = nullptr;
|
||||
assert(p3 == nullptr);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -9,11 +9,6 @@
|
|||
// UNSUPPORTED: libcpp-has-no-threads
|
||||
// UNSUPPORTED: c++03, c++11
|
||||
|
||||
// dylib support for shared_mutex was added in macosx10.12
|
||||
// XFAIL: use_system_cxx_lib && x86_64-apple-macosx10.11
|
||||
// XFAIL: use_system_cxx_lib && x86_64-apple-macosx10.10
|
||||
// XFAIL: use_system_cxx_lib && x86_64-apple-macosx10.9
|
||||
|
||||
// <shared_mutex>
|
||||
|
||||
// template <class Mutex> class shared_lock;
|
||||
|
@ -25,17 +20,24 @@
|
|||
|
||||
#include "test_macros.h"
|
||||
|
||||
std::shared_timed_mutex m;
|
||||
struct M {
|
||||
void lock_shared() {}
|
||||
void unlock_shared() {}
|
||||
};
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
std::shared_lock<std::shared_timed_mutex> lk0;
|
||||
static_assert(std::is_constructible<bool, std::shared_lock<M>>::value, "");
|
||||
static_assert(!std::is_convertible<std::shared_lock<M>, bool>::value, "");
|
||||
|
||||
M m;
|
||||
std::shared_lock<M> lk0;
|
||||
assert(static_cast<bool>(lk0) == false);
|
||||
std::shared_lock<std::shared_timed_mutex> lk1(m);
|
||||
std::shared_lock<M> lk1(m);
|
||||
assert(static_cast<bool>(lk1) == true);
|
||||
lk1.unlock();
|
||||
assert(static_cast<bool>(lk1) == false);
|
||||
static_assert(noexcept(static_cast<bool>(lk0)), "explicit operator bool() must be noexcept");
|
||||
ASSERT_NOEXCEPT(static_cast<bool>(lk0));
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -12,10 +12,11 @@
|
|||
|
||||
// template <class Mutex> class unique_lock;
|
||||
|
||||
// explicit operator bool() const;
|
||||
// explicit operator bool() const noexcept;
|
||||
|
||||
#include <mutex>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
|
@ -23,12 +24,16 @@ std::mutex m;
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
static_assert(std::is_constructible<bool, std::unique_lock<std::mutex> >::value, "");
|
||||
static_assert(!std::is_convertible<std::unique_lock<std::mutex>, bool>::value, "");
|
||||
|
||||
std::unique_lock<std::mutex> lk0;
|
||||
assert(static_cast<bool>(lk0) == false);
|
||||
std::unique_lock<std::mutex> lk1(m);
|
||||
assert(static_cast<bool>(lk1) == true);
|
||||
lk1.unlock();
|
||||
assert(static_cast<bool>(lk1) == false);
|
||||
ASSERT_NOEXCEPT(static_cast<bool>(lk0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <functional>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
|
@ -24,6 +25,9 @@ int g(int) {return 0;}
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
static_assert(std::is_constructible<bool, std::function<void()> >::value, "");
|
||||
static_assert(!std::is_convertible<std::function<void()>, bool>::value, "");
|
||||
|
||||
{
|
||||
std::function<int(int)> f;
|
||||
assert(!f);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
|
@ -25,6 +26,9 @@ struct B : A {};
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
static_assert(std::is_constructible<bool, std::shared_ptr<A> >::value, "");
|
||||
static_assert(!std::is_convertible<std::shared_ptr<A>, bool>::value, "");
|
||||
|
||||
{
|
||||
const std::shared_ptr<int> p(new int(32));
|
||||
assert(p);
|
||||
|
|
Loading…
Reference in New Issue