Author: ericwf Date: Fri Dec 30 08:05:52 2016 New Revision: 290754 URL: http://llvm.org/viewvc/llvm-project?rev=290754&view=rev Log: Recommit r290750: Fix PR19460 - std::ios is convertible to int.
There were two problems with the initial fix. 1. The added tests flushed out that we misconfigured _LIBCPP_EXPLICIT with GCC. 2. Because the boolean type was a member function template it caused weird link errors. I'm assuming due to the vague linkage rules. This time the bool type is a non-template member function pointer. That seems to have fixed the failing tests. Plus it will end up generating less symbols overall, since the bool type is no longer per instantiation. original commit message below ----------------------------- std::basic_ios has an operator bool(). In C++11 and later it is explicit, and only allows contextual implicit conversions. However explicit isn't available in C++03 which causes std::istream (et al) to have an implicit conversion to int. This can easily cause ambiguities when calling operator<< and operator>>. This patch uses a "bool-like" type in C++03 to work around this. The "bool-like" type is an arbitrary pointer to member function type. It will not convert to either int or void*, but will convert to bool. Modified: libcxx/trunk/include/__config libcxx/trunk/include/ios libcxx/trunk/test/std/input.output/iostreams.base/ios/iostate.flags/bool.pass.cpp Modified: libcxx/trunk/include/__config URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=290754&r1=290753&r2=290754&view=diff ============================================================================== --- libcxx/trunk/include/__config (original) +++ libcxx/trunk/include/__config Fri Dec 30 08:05:52 2016 @@ -727,7 +727,8 @@ template <unsigned> struct __static_asse #define _NOALIAS #endif -#if __has_feature(cxx_explicit_conversions) || defined(__IBMCPP__) +#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 Modified: libcxx/trunk/include/ios URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/ios?rev=290754&r1=290753&r2=290754&view=diff ============================================================================== --- libcxx/trunk/include/ios (original) +++ libcxx/trunk/include/ios Fri Dec 30 08:05:52 2016 @@ -572,6 +572,13 @@ ios_base::exceptions(iostate __iostate) clear(__rdstate_); } +#if defined(_LIBCPP_CXX03_LANG) +struct _LIBCPP_TYPE_VIS_ONLY __cxx03_bool { + typedef void (__cxx03_bool::*__bool_type)(); + void __true_value() {} +}; +#endif + template <class _CharT, class _Traits> class _LIBCPP_TYPE_VIS_ONLY basic_ios : public ios_base @@ -585,9 +592,19 @@ public: typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; + // __true_value will generate undefined references when linking unless + // we give it internal linkage. + +#if defined(_LIBCPP_CXX03_LANG) _LIBCPP_ALWAYS_INLINE - _LIBCPP_EXPLICIT - operator bool() const {return !fail();} + operator __cxx03_bool::__bool_type() const { + return !fail() ? &__cxx03_bool::__true_value : nullptr; + } +#else + _LIBCPP_ALWAYS_INLINE + _LIBCPP_EXPLICIT operator bool() const {return !fail();} +#endif + _LIBCPP_ALWAYS_INLINE bool operator!() const {return fail();} _LIBCPP_ALWAYS_INLINE iostate rdstate() const {return ios_base::rdstate();} _LIBCPP_ALWAYS_INLINE void clear(iostate __state = goodbit) {ios_base::clear(__state);} Modified: libcxx/trunk/test/std/input.output/iostreams.base/ios/iostate.flags/bool.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/input.output/iostreams.base/ios/iostate.flags/bool.pass.cpp?rev=290754&r1=290753&r2=290754&view=diff ============================================================================== --- libcxx/trunk/test/std/input.output/iostreams.base/ios/iostate.flags/bool.pass.cpp (original) +++ libcxx/trunk/test/std/input.output/iostreams.base/ios/iostate.flags/bool.pass.cpp Fri Dec 30 08:05:52 2016 @@ -14,12 +14,21 @@ // operator unspecified-bool-type() const; #include <ios> +#include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { std::ios ios(0); assert(static_cast<bool>(ios) == !ios.fail()); ios.setstate(std::ios::failbit); assert(static_cast<bool>(ios) == !ios.fail()); + 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 } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits