Author: ericwf Date: Fri Dec 30 06:44:58 2016 New Revision: 290750 URL: http://llvm.org/viewvc/llvm-project?rev=290750&view=rev Log: Fix PR19460 - std::ios is convertible to int.
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/ios libcxx/trunk/test/std/input.output/iostreams.base/ios/iostate.flags/bool.pass.cpp Modified: libcxx/trunk/include/ios URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/ios?rev=290750&r1=290749&r2=290750&view=diff ============================================================================== --- libcxx/trunk/include/ios (original) +++ libcxx/trunk/include/ios Fri Dec 30 06:44:58 2016 @@ -585,9 +585,22 @@ public: typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; +#if defined(_LIBCPP_CXX03_LANG) +private: + struct __bool_tag {}; + typedef void (basic_ios::*_BoolType)(__bool_tag) const; + void __true_value(__bool_tag) const {} + +public: + _LIBCPP_ALWAYS_INLINE + operator _BoolType() const { + return !fail() ? &basic_ios::__true_value : nullptr; + } +#else _LIBCPP_ALWAYS_INLINE - _LIBCPP_EXPLICIT - operator bool() const {return !fail();} + _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=290750&r1=290749&r2=290750&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 06:44:58 2016 @@ -14,6 +14,7 @@ // operator unspecified-bool-type() const; #include <ios> +#include <type_traits> #include <cassert> int main() @@ -22,4 +23,10 @@ int main() 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