Index: docs/UsingLibcxx.rst =================================================================== --- docs/UsingLibcxx.rst +++ docs/UsingLibcxx.rst @@ -180,3 +180,6 @@ * Giving `set`, `map`, `multiset`, `multimap` a comparator which is not const callable. +**_LIBCPP_DISABLE_EXTENSION_DIAGNOSTICS**: + This macro disables diagnostics generated by libc++ when a libc++ extension + is used. Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -1041,6 +1041,12 @@ # define _LIBCPP_DIAGNOSE_ERROR(...) #endif +#if defined(_LIBCPP_BUILDING_LIBRARY) || defined(_LIBCPP_DISABLE_EXTENSION_DIAGNOSTICS) +# define _LIBCPP_DIAGNOSE_EXTENSIONS 0 +#else +# define _LIBCPP_DIAGNOSE_EXTENSIONS 1 +#endif + #if defined(_LIBCPP_ABI_MICROSOFT) && \ (defined(_LIBCPP_COMPILER_MSVC) || __has_declspec_attribute(empty_bases)) # define _LIBCPP_DECLSPEC_EMPTY_BASES __declspec(empty_bases) Index: include/future =================================================================== --- include/future +++ include/future @@ -504,7 +504,9 @@ { error_code __ec_; public: - future_error(error_code __ec); + explicit future_error(error_code __ec) + _LIBCPP_DIAGNOSE_WARNING(_LIBCPP_DIAGNOSE_EXTENSIONS, + "this constructor is a libc++ extension"); #if _LIBCPP_STD_VERS > 14 explicit future_error(future_errc _Ev) : logic_error(), __ec_(make_error_code(_Ev)) {} #endif @@ -514,6 +516,11 @@ virtual ~future_error() _NOEXCEPT; }; +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wuser-defined-warnings" +#endif + _LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_future_error(future_errc _Ev) { @@ -525,6 +532,16 @@ #endif } +inline _LIBCPP_ALWAYS_INLINE +future_error __make_future_error(future_errc _Ev) +{ + return future_error(make_error_code(_Ev)); +} + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + class _LIBCPP_TYPE_VIS __assoc_sub_state : public __shared_count { @@ -1444,7 +1461,7 @@ { if (!__state_->__has_value() && __state_->use_count() > 1) __state_->set_exception(make_exception_ptr( - future_error(make_error_code(future_errc::broken_promise)) + __make_future_error(future_errc::broken_promise) )); __state_->__release_shared(); } @@ -1606,7 +1623,7 @@ { if (!__state_->__has_value() && __state_->use_count() > 1) __state_->set_exception(make_exception_ptr( - future_error(make_error_code(future_errc::broken_promise)) + __make_future_error(future_errc::broken_promise) )); __state_->__release_shared(); } Index: test/libcxx/thread/futures/futures.future_error/diagnose_extended_constructor.fail.cpp =================================================================== --- /dev/null +++ test/libcxx/thread/futures/futures.future_error/diagnose_extended_constructor.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: libcpp-has-no-threads +// REQUIRES: diagnose-if-support + +// + +// class future_error + +// future_error(error_code) // libc++ extension + +#include + +int main() { + std::future_error f(std::make_error_code(std::future_errc::broken_promise)); + // expected-warning@-1 {{this constructor is a libc++ extension}} + ((void)f); +} Index: test/libcxx/thread/futures/futures.future_error/extended_constructor.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/thread/futures/futures.future_error/extended_constructor.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: libcpp-has-no-threads + +// + +// class future_error + +// future_error(error_code) // libc++ extension + +#include +#include + +int main() { + static_assert(std::is_constructible::value, ""); + static_assert(!std::is_convertible::value, ""); +} Index: test/std/thread/futures/futures.future_error/code.pass.cpp =================================================================== --- test/std/thread/futures/futures.future_error/code.pass.cpp +++ test/std/thread/futures/futures.future_error/code.pass.cpp @@ -22,8 +22,13 @@ #include "test_macros.h" +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wuser-defined-warnings" +#endif + int main() { +#if defined(_LIBCPP_VERSION) { std::error_code ec = std::make_error_code(std::future_errc::broken_promise); std::future_error f(ec); @@ -44,6 +49,7 @@ std::future_error f(ec); assert(f.code() == ec); } +#endif // _LIBCPP_VERSION #if TEST_STD_VER > 14 { std::future_error f(std::future_errc::broken_promise); Index: test/std/thread/futures/futures.future_error/what.pass.cpp =================================================================== --- test/std/thread/futures/futures.future_error/what.pass.cpp +++ test/std/thread/futures/futures.future_error/what.pass.cpp @@ -28,24 +28,38 @@ #include "test_macros.h" + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wuser-defined-warnings" +#endif + +template // make dependent to prevent compile errors +std::future_error make_error(ErrC ec) { +#if TEST_STD_VER > 14 + return std::future_error(ec); +#else + return std::future_error(std::make_error_code(ec)); // libc++ extension +#endif +} + int main() { { - std::future_error f(std::make_error_code(std::future_errc::broken_promise)); + std::future_error f = make_error(std::future_errc::broken_promise); LIBCPP_ASSERT(std::strcmp(f.what(), "The associated promise has been destructed prior " "to the associated state becoming ready.") == 0); } { - std::future_error f(std::make_error_code(std::future_errc::future_already_retrieved)); + std::future_error f = make_error(std::future_errc::future_already_retrieved); LIBCPP_ASSERT(std::strcmp(f.what(), "The future has already been retrieved from " "the promise or packaged_task.") == 0); } { - std::future_error f(std::make_error_code(std::future_errc::promise_already_satisfied)); + std::future_error f = make_error(std::future_errc::promise_already_satisfied); LIBCPP_ASSERT(std::strcmp(f.what(), "The state of the promise has already been set.") == 0); } { - std::future_error f(std::make_error_code(std::future_errc::no_state)); + std::future_error f = make_error(std::future_errc::no_state); LIBCPP_ASSERT(std::strcmp(f.what(), "Operation not permitted on an object without " "an associated state.") == 0); }