From a5dde6ddac80b3a6e4cb3d988c5c449108411704 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 14 Nov 2014 12:17:57 +0000 Subject: [PATCH] Define C++11 version of std::ios_base::failure. * config/abi/pre/gnu.ver: Add new exports. * include/bits/ios_base.h (ios_base::failure): New definition using abi_tag. (io_errc, make_error_code, make_error_category, iostream_category): Define. * include/std/system_error (system_error): Add char* constructors. * src/c++11/Makefile.am: Add new file. * src/c++11/Makefile.in: Regenerate. * src/c++11/cxx11-ios_failure.cc: New file. * src/c++98/ios_failure.cc: Compile old definition without abi_tag. * testsuite/27_io/ios_base/failure/cxx11.cc: New. * testsuite/27_io/ios_base/failure/what-1.cc: Allow string returned by ios_base::failure::what() to contain additional data. * testsuite/27_io/ios_base/failure/what-2.cc: Likewise.. * testsuite/27_io/ios_base/failure/what-3.cc: Likewise.. * testsuite/27_io/ios_base/failure/what-big.cc: Likewise.. From-SVN: r217559 --- libstdc++-v3/ChangeLog | 19 ++++ libstdc++-v3/config/abi/pre/gnu.ver | 12 +++ libstdc++-v3/include/bits/ios_base.h | 62 +++++++++++++ libstdc++-v3/include/std/system_error | 15 ++-- libstdc++-v3/src/c++11/Makefile.am | 8 ++ libstdc++-v3/src/c++11/Makefile.in | 16 ++-- libstdc++-v3/src/c++11/cxx11-ios_failure.cc | 89 +++++++++++++++++++ libstdc++-v3/src/c++98/ios_failure.cc | 3 +- .../testsuite/27_io/ios_base/failure/cxx11.cc | 52 +++++++++++ .../27_io/ios_base/failure/what-1.cc | 9 ++ .../27_io/ios_base/failure/what-2.cc | 8 +- .../27_io/ios_base/failure/what-3.cc | 8 ++ .../27_io/ios_base/failure/what-big.cc | 4 + 13 files changed, 288 insertions(+), 17 deletions(-) create mode 100644 libstdc++-v3/src/c++11/cxx11-ios_failure.cc create mode 100644 libstdc++-v3/testsuite/27_io/ios_base/failure/cxx11.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 65408784c89..18e214fc94b 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,22 @@ +2014-11-14 Jonathan Wakely + + * config/abi/pre/gnu.ver: Add new exports. + * include/bits/ios_base.h (ios_base::failure): New definition using + abi_tag. + (io_errc, make_error_code, make_error_category, iostream_category): + Define. + * include/std/system_error (system_error): Add char* constructors. + * src/c++11/Makefile.am: Add new file. + * src/c++11/Makefile.in: Regenerate. + * src/c++11/cxx11-ios_failure.cc: New file. + * src/c++98/ios_failure.cc: Compile old definition without abi_tag. + * testsuite/27_io/ios_base/failure/cxx11.cc: New. + * testsuite/27_io/ios_base/failure/what-1.cc: Allow string returned by + ios_base::failure::what() to contain additional data. + * testsuite/27_io/ios_base/failure/what-2.cc: Likewise.. + * testsuite/27_io/ios_base/failure/what-3.cc: Likewise.. + * testsuite/27_io/ios_base/failure/what-big.cc: Likewise.. + 2014-11-13 Daniel Kruegler * include/bits/regex.h: Support embedded zeros in sub_match diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index bd44bcc3ba6..78f3e77a1de 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -1473,6 +1473,18 @@ GLIBCXX_3.4.21 { # std::basic_ios::operator bool() const _ZNKSt9basic_iosI[cw]St11char_traitsI[cw]EEcvbEv; + # C++11 version of std::ios_base::failure + _ZNKSt8ios_base7failureB5cxx114whatEv; + _ZNSt8ios_base7failureB5cxx11C[12]ERKSs; + _ZNSt8ios_base7failureB5cxx11C[12]EPKcRKSt10error_code; + _ZNSt8ios_base7failureB5cxx11C[12]ERKSsB5cxx11; + _ZNSt8ios_base7failureB5cxx11C[12]ERKSsB5cxx11RKSt10error_code; + _ZNSt8ios_base7failureB5cxx11D[012]Ev; + _ZTINSt8ios_base7failureB5cxx11E; + _ZTSNSt8ios_base7failureB5cxx11E; + _ZTVNSt8ios_base7failureB5cxx11E; + _ZSt17iostream_categoryv; + # std::ctype_base::blank _ZNSt10ctype_base5blankE; diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h index 5e33b812fe3..8e600598fe2 100644 --- a/libstdc++-v3/include/bits/ios_base.h +++ b/libstdc++-v3/include/bits/ios_base.h @@ -40,6 +40,12 @@ #include #include +#if __cplusplus < 201103L +# include +#else +# include +#endif + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -186,6 +192,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _S_ios_seekdir_end = 1L << 16 }; +#if __cplusplus >= 201103L + /// I/O error code + enum class io_errc { stream = 1 }; + + template <> struct is_error_code_enum : public true_type { }; + + const error_category& iostream_category() noexcept; + + inline error_code + make_error_code(io_errc e) noexcept + { return error_code(static_cast(e), iostream_category()); } + + inline error_condition + make_error_condition(io_errc e) noexcept + { return error_condition(static_cast(e), iostream_category()); } +#endif + // 27.4.2 Class ios_base /** * @brief The base of the I/O class hierarchy. @@ -198,6 +221,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ class ios_base { +#if _GLIBCXX_USE_CXX11_ABI +#if __cplusplus < 201103L + // Type that is layout-compatible with std::system_error + struct system_error : std::runtime_error + { + // Type that is layout-compatible with std::error_code + struct error_code + { + error_code() { } + private: + int _M_value; + const void* _M_cat; + } _M_code; + }; +#endif +#endif public: /** @@ -206,6 +245,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * 27.4.2.1.1 Class ios_base::failure */ +#if _GLIBCXX_USE_CXX11_ABI + class _GLIBCXX_ABI_TAG_CXX11 failure : public system_error + { + public: + explicit + failure(const string& __str); + +#if __cplusplus >= 201103L + explicit + failure(const string&, const error_code&); + + explicit + failure(const char*, const error_code& = io_errc::stream); +#endif + + virtual + ~failure() throw(); + + virtual const char* + what() const throw(); + }; +#else class failure : public exception { public: @@ -225,6 +286,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: string _M_msg; }; +#endif // 27.4.2.1.2 Type ios_base::fmtflags /** diff --git a/libstdc++-v3/include/std/system_error b/libstdc++-v3/include/std/system_error index 4ec83d77c4e..ed17f554bca 100644 --- a/libstdc++-v3/include/std/system_error +++ b/libstdc++-v3/include/std/system_error @@ -321,16 +321,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION system_error(error_code __ec, const string& __what) : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { } - /* - * TODO: Add const char* ctors to all exceptions. - * - * system_error(error_code __ec, const char* __what) - * : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { } - * - * system_error(int __v, const error_category& __ecat, const char* __what) - * : runtime_error(__what + (": " + __ec.message())), - * _M_code(error_code(__v, __ecat)) { } - */ + system_error(error_code __ec, const char* __what) + : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { } + + system_error(int __v, const error_category& __ecat, const char* __what) + : system_error(error_code(__v, __ecat), __what) { } system_error(int __v, const error_category& __ecat) : runtime_error(error_code(__v, __ecat).message()), diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am index c8507cec8df..71306db4b00 100644 --- a/libstdc++-v3/src/c++11/Makefile.am +++ b/libstdc++-v3/src/c++11/Makefile.am @@ -39,6 +39,13 @@ ctype_configure_char.cc: ${glibcxx_srcdir}/$(OS_INC_SRCDIR)/ctype_configure_char ctype_members.cc: ${glibcxx_srcdir}/$(CCTYPE_CC) $(LN_S) ${glibcxx_srcdir}/$(CCTYPE_CC) . || true +if ENABLE_CXX11_ABI +cxx11_abi_sources = \ + cxx11-ios_failure.cc +else +cxx11_abi_sources = +endif + sources = \ chrono.cc \ condition_variable.cc \ @@ -59,6 +66,7 @@ sources = \ snprintf_lite.cc \ system_error.cc \ thread.cc \ + ${cxx11_abi_sources} \ ${host_sources} if ENABLE_EXTERN_TEMPLATE diff --git a/libstdc++-v3/src/c++11/Makefile.in b/libstdc++-v3/src/c++11/Makefile.in index fd3e7801d85..dd9e110f768 100644 --- a/libstdc++-v3/src/c++11/Makefile.in +++ b/libstdc++-v3/src/c++11/Makefile.in @@ -67,19 +67,20 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libc__11convenience_la_LIBADD = -am__objects_1 = ctype_configure_char.lo ctype_members.lo -am__objects_2 = chrono.lo condition_variable.lo ctype.lo debug.lo \ +@ENABLE_CXX11_ABI_TRUE@am__objects_1 = cxx11-ios_failure.lo +am__objects_2 = ctype_configure_char.lo ctype_members.lo +am__objects_3 = chrono.lo condition_variable.lo ctype.lo debug.lo \ functexcept.lo functional.lo future.lo hash_c++0x.lo \ hashtable_c++0x.lo ios.lo limits.lo mutex.lo placeholders.lo \ random.lo regex.lo shared_ptr.lo snprintf_lite.lo \ - system_error.lo thread.lo $(am__objects_1) -@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_3 = ext11-inst.lo \ + system_error.lo thread.lo $(am__objects_1) $(am__objects_2) +@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_4 = ext11-inst.lo \ @ENABLE_EXTERN_TEMPLATE_TRUE@ fstream-inst.lo ios-inst.lo \ @ENABLE_EXTERN_TEMPLATE_TRUE@ iostream-inst.lo istream-inst.lo \ @ENABLE_EXTERN_TEMPLATE_TRUE@ ostream-inst.lo sstream-inst.lo \ @ENABLE_EXTERN_TEMPLATE_TRUE@ streambuf-inst.lo string-inst.lo \ @ENABLE_EXTERN_TEMPLATE_TRUE@ wstring-inst.lo -am_libc__11convenience_la_OBJECTS = $(am__objects_2) $(am__objects_3) +am_libc__11convenience_la_OBJECTS = $(am__objects_3) $(am__objects_4) libc__11convenience_la_OBJECTS = $(am_libc__11convenience_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = @@ -322,6 +323,10 @@ host_sources = \ ctype_configure_char.cc \ ctype_members.cc +@ENABLE_CXX11_ABI_FALSE@cxx11_abi_sources = +@ENABLE_CXX11_ABI_TRUE@cxx11_abi_sources = \ +@ENABLE_CXX11_ABI_TRUE@ cxx11-ios_failure.cc + sources = \ chrono.cc \ condition_variable.cc \ @@ -342,6 +347,7 @@ sources = \ snprintf_lite.cc \ system_error.cc \ thread.cc \ + ${cxx11_abi_sources} \ ${host_sources} # XTEMPLATE_FLAGS = diff --git a/libstdc++-v3/src/c++11/cxx11-ios_failure.cc b/libstdc++-v3/src/c++11/cxx11-ios_failure.cc new file mode 100644 index 00000000000..143d70e5e93 --- /dev/null +++ b/libstdc++-v3/src/c++11/cxx11-ios_failure.cc @@ -0,0 +1,89 @@ +// Iostreams base classes -*- C++ -*- + +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// +// ISO C++ 14882:2011: 27.5.3.1.1 Class ios_base::failure +// + +#include + +namespace +{ + struct io_error_category : std::error_category + { + virtual const char* + name() const noexcept + { return "iostream"; } + + virtual std::string message(int __ec) const + { + std::string __msg; + switch (std::io_errc(__ec)) + { + case std::io_errc::stream: + __msg = "iostream error"; + break; + default: + __msg = "Unknown error"; + break; + } + return __msg; + } + }; + + const io_error_category& + __io_category_instance() noexcept + { + static const io_error_category __ec{}; + return __ec; + } + +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + const error_category& + iostream_category() noexcept + { return __io_category_instance(); } + + ios_base::failure::failure(const string& __str) + : system_error(io_errc::stream, __str) { } + + ios_base::failure::failure(const string& __str, const error_code& __ec) + : system_error(__ec, __str) { } + + ios_base::failure::failure(const char* __str, const error_code& __ec) + : system_error(__ec, __str) { } + + ios_base::failure::~failure() + { } + + const char* + ios_base::failure::what() const throw() + { return runtime_error::what(); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace diff --git a/libstdc++-v3/src/c++98/ios_failure.cc b/libstdc++-v3/src/c++98/ios_failure.cc index 9d32e51c957..0f4517800ce 100644 --- a/libstdc++-v3/src/c++98/ios_failure.cc +++ b/libstdc++-v3/src/c++98/ios_failure.cc @@ -23,9 +23,10 @@ // . // -// ISO C++ 14882: 27.4.2.1.1 Class ios_base::failure +// ISO C++ 14882:1998: 27.4.2.1.1 Class ios_base::failure // +#define _GLIBCXX_USE_CXX11_ABI 0 #include namespace std _GLIBCXX_VISIBILITY(default) diff --git a/libstdc++-v3/testsuite/27_io/ios_base/failure/cxx11.cc b/libstdc++-v3/testsuite/27_io/ios_base/failure/cxx11.cc new file mode 100644 index 00000000000..a3276e1c5bd --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/ios_base/failure/cxx11.cc @@ -0,0 +1,52 @@ +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++11" } + +#include +#include + +using test_type = std::ios_base::failure; + +static_assert( std::is_base_of::value, "base" ); + +void +test01() +{ + test_type e("io error"); + VERIFY(std::string(e.what()).find("io error") != std::string::npos); + e = test_type("", make_error_code(std::io_errc::stream)); +} + +struct E : test_type +{ + E(const char* s) : test_type(s, make_error_code(std::io_errc::stream)) { } +}; + +void +test02() +{ + E e("io error"); + VERIFY(std::string(e.what()).find("io error") != std::string::npos); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/27_io/ios_base/failure/what-1.cc b/libstdc++-v3/testsuite/27_io/ios_base/failure/what-1.cc index 07be43bfddb..a50c798b14c 100644 --- a/libstdc++-v3/testsuite/27_io/ios_base/failure/what-1.cc +++ b/libstdc++-v3/testsuite/27_io/ios_base/failure/what-1.cc @@ -37,8 +37,13 @@ void test01() // 2 std::ios_base::failure obj2(s); +#if _GLIBCXX_USE_CXX11_ABI + VERIFY( std::strstr(obj1.what(), s.data()) != NULL ); + VERIFY( std::strstr(obj2.what(), s.data()) != NULL ); +#else VERIFY( std::strcmp(obj1.what(), s.data()) == 0 ); VERIFY( std::strcmp(obj2.what(), s.data()) == 0 ); +#endif } void test02() @@ -47,7 +52,11 @@ void test02() std::string s("lack of sunlight error"); std::range_error x(s); +#if _GLIBCXX_USE_CXX11_ABI + VERIFY( std::strstr(x.what(), s.data()) != NULL ); +#else VERIFY( std::strcmp(x.what(), s.data()) == 0 ); +#endif } int main(void) diff --git a/libstdc++-v3/testsuite/27_io/ios_base/failure/what-2.cc b/libstdc++-v3/testsuite/27_io/ios_base/failure/what-2.cc index 334c8e1fcad..e16ef7c64d9 100644 --- a/libstdc++-v3/testsuite/27_io/ios_base/failure/what-2.cc +++ b/libstdc++-v3/testsuite/27_io/ios_base/failure/what-2.cc @@ -37,7 +37,13 @@ void test03() try { throw fuzzy_logic(); } catch(const fuzzy_logic& obj) - { VERIFY( std::strcmp("whoa", obj.what()) == 0 ); } + { +#if _GLIBCXX_USE_CXX11_ABI + VERIFY( std::strstr(obj.what(), "whoa") != NULL ); +#else + VERIFY( std::strcmp("whoa", obj.what()) == 0 ); +#endif + } catch(...) { VERIFY( false ); } } diff --git a/libstdc++-v3/testsuite/27_io/ios_base/failure/what-3.cc b/libstdc++-v3/testsuite/27_io/ios_base/failure/what-3.cc index b9af939df82..abbbcca7826 100644 --- a/libstdc++-v3/testsuite/27_io/ios_base/failure/what-3.cc +++ b/libstdc++-v3/testsuite/27_io/ios_base/failure/what-3.cc @@ -52,7 +52,11 @@ void test04() obj1 = obj2; } allocate_on_stack(); +#if _GLIBCXX_USE_CXX11_ABI + VERIFY( std::strstr(obj1.what(), strlit1) != NULL ); +#else VERIFY( std::strcmp(strlit1, obj1.what()) == 0 ); +#endif // block 02 { @@ -61,7 +65,11 @@ void test04() obj1 = obj3; } allocate_on_stack(); +#if _GLIBCXX_USE_CXX11_ABI + VERIFY( std::strstr(obj1.what(), strlit2) != NULL ); +#else VERIFY( std::strcmp(strlit2, obj1.what()) == 0 ); +#endif } int main(void) diff --git a/libstdc++-v3/testsuite/27_io/ios_base/failure/what-big.cc b/libstdc++-v3/testsuite/27_io/ios_base/failure/what-big.cc index a2bd37c972c..99ee17d6839 100644 --- a/libstdc++-v3/testsuite/27_io/ios_base/failure/what-big.cc +++ b/libstdc++-v3/testsuite/27_io/ios_base/failure/what-big.cc @@ -30,7 +30,11 @@ void test01() bool test __attribute__((unused)) = true; const std::string xxx(10000, 'x'); test_type t(xxx); +#if _GLIBCXX_USE_CXX11_ABI + VERIFY( std::strstr(t.what(), xxx.c_str()) != NULL ); +#else VERIFY( std::strcmp(t.what(), xxx.c_str()) == 0 ); +#endif } int main(void) -- 2.30.2