summaryrefslogtreecommitdiff
path: root/libstdc++-v3/src/c++11/cxx11-ios_failure.cc
blob: 2010b6617413f4ca50284c0bc5f17662534f29f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Iostreams base classes -*- C++ -*-

// Copyright (C) 2014-2019 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
// <http://www.gnu.org/licenses/>.

//
// ISO C++ 14882:2011: 27.5.3.1.1  Class ios_base::failure
//

#define _GLIBCXX_USE_CXX11_ABI 1
#include <ios>
#include <bits/functexcept.h>
#include <cxxabi.h>

#ifdef _GLIBCXX_USE_NLS
# include <libintl.h>
# define _(msgid)   gettext (msgid)
#else
# define _(msgid)   (msgid)
#endif

#if ! _GLIBCXX_USE_DUAL_ABI
# error This file should not be compiled for this configuration.
#endif

namespace
{
  struct io_error_category : std::error_category
  {
    virtual const char*
    name() const noexcept
    { return "iostream"; }

    _GLIBCXX_DEFAULT_ABI_TAG
    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(); }

#if __cpp_rtti
  // These functions are defined in src/c++98/ios_failure.cc
  extern void __construct_ios_failure(void*, const char*);
  extern void __destroy_ios_failure(void*);
  extern bool __is_ios_failure_handler(const __cxxabiv1::__class_type_info*);

  // The type thrown to report errors during stream buffer operations.
  // In addition to the ios::failure[abi:cxx11] base class it also has a
  // member of the gcc4-compatible ios::failure type (in an opaque buffer).
  struct __ios_failure : std::ios::failure
  {
    __ios_failure(const char* s) : failure(s)
    { __construct_ios_failure(buf, runtime_error::what()); }

    __ios_failure(const char* s, int e) : failure(s, to_error_code(e))
    { __construct_ios_failure(buf, runtime_error::what()); }

    ~__ios_failure()
    { __destroy_ios_failure(buf); }

    // Use std::runtime_error as a proxy for the gcc4-compatible ios::failure
    // (which can't be declared here because _GLIBCXX_USE_CXX11_ABI == 1).
    // There are assertions in src/c++98/ios_failure.cc to ensure the size
    // and alignment assumptions are valid.
    alignas(runtime_error) unsigned char buf[sizeof(runtime_error)];

    static error_code
    to_error_code(int e)
    { return e ? error_code(e, system_category()) : io_errc::stream; }
  };

  // Custom type info for __ios_failure.
  class __iosfail_type_info : __cxxabiv1::__si_class_type_info
  {
    ~__iosfail_type_info();

    bool
    __do_upcast (const __class_type_info *dst_type,
		 void **obj_ptr) const override;
  };

  __iosfail_type_info::~__iosfail_type_info() = default;

  // This function gets called to see if an exception of type
  // __ios_failure can be upcast to the type in a catch handler.
  bool
  __iosfail_type_info::__do_upcast(const __class_type_info *dst_type,
				   void **obj_ptr) const
  {
    // If the handler is for the gcc4-compatible ios::failure type then
    // catch the object stored in __ios_failure::buf instead of
    // the __ios_failure exception object itself.
    if (__is_ios_failure_handler(dst_type))
      {
	*obj_ptr = static_cast<__ios_failure*>(*obj_ptr)->buf;
	return true;
      }
    // Otherwise proceed as normal to see if the handler matches.
    return __class_type_info::__do_upcast(dst_type, obj_ptr);
  }
#else // ! __cpp_rtti
  using __ios_failure = ios::failure;
#endif

  void
  __throw_ios_failure(const char* __s __attribute__((unused)))
  { _GLIBCXX_THROW_OR_ABORT(__ios_failure(_(__s))); }

  void
  __throw_ios_failure(const char* str __attribute__((unused)),
		      int err __attribute__((unused)))
  { _GLIBCXX_THROW_OR_ABORT(__ios_failure(_(str), err)); }

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace