Coverage Report

Created: 2022-05-14 11:35

/Users/buildslave/jenkins/workspace/coverage/llvm-project/libcxx/src/system_error.cpp
Line
Count
Source (jump to first uncovered line)
1
//===----------------------------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include <__config>
10
#ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
11
#   define _LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS
12
#endif
13
14
#include <__assert>
15
#include <cerrno>
16
#include <cstdio>
17
#include <cstdlib>
18
#include <cstring>
19
#include <string>
20
#include <string.h>
21
#include <system_error>
22
23
#include "include/config_elast.h"
24
25
#if defined(__ANDROID__)
26
#include <android/api-level.h>
27
#endif
28
29
_LIBCPP_BEGIN_NAMESPACE_STD
30
31
// class error_category
32
33
#if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS)
34
error_category::error_category() noexcept
35
30.9k
{
36
30.9k
}
37
#endif
38
39
error_category::~error_category() noexcept
40
873
{
41
873
}
42
43
error_condition
44
error_category::default_error_condition(int ev) const noexcept
45
6
{
46
6
    return error_condition(ev, *this);
47
6
}
48
49
bool
50
error_category::equivalent(int code, const error_condition& condition) const noexcept
51
6
{
52
6
    return default_error_condition(code) == condition;
53
6
}
54
55
bool
56
error_category::equivalent(const error_code& code, int condition) const noexcept
57
0
{
58
0
    return *this == code.category() && code.value() == condition;
59
0
}
60
61
#if !defined(_LIBCPP_HAS_NO_THREADS)
62
namespace {
63
64
//  GLIBC also uses 1024 as the maximum buffer size internally.
65
constexpr size_t strerror_buff_size = 1024;
66
67
string do_strerror_r(int ev);
68
69
#if defined(_LIBCPP_MSVCRT_LIKE)
70
string do_strerror_r(int ev) {
71
  char buffer[strerror_buff_size];
72
  if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
73
    return string(buffer);
74
  std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
75
  return string(buffer);
76
}
77
#else
78
79
// Only one of the two following functions will be used, depending on
80
// the return type of strerror_r:
81
82
// For the GNU variant, a char* return value:
83
__attribute__((unused)) const char *
84
0
handle_strerror_r_return(char *strerror_return, char *buffer) {
85
0
  // GNU always returns a string pointer in its return value. The
86
0
  // string might point to either the input buffer, or a static
87
0
  // buffer, but we don't care which.
88
0
  return strerror_return;
89
0
}
90
91
// For the POSIX variant: an int return value.
92
__attribute__((unused)) const char *
93
29
handle_strerror_r_return(int strerror_return, char *buffer) {
94
  // The POSIX variant either:
95
  // - fills in the provided buffer and returns 0
96
  // - returns a positive error value, or
97
  // - returns -1 and fills in errno with an error value.
98
29
  if (strerror_return == 0)
99
29
    return buffer;
100
101
  // Only handle EINVAL. Other errors abort.
102
0
  int new_errno = strerror_return == -1 ? errno : strerror_return;
103
0
  if (new_errno == EINVAL)
104
0
    return "";
105
106
0
  _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
107
  // FIXME maybe? 'strerror_buff_size' is likely to exceed the
108
  // maximum error size so ERANGE shouldn't be returned.
109
0
  std::abort();
110
0
}
111
112
// This function handles both GNU and POSIX variants, dispatching to
113
// one of the two above functions.
114
29
string do_strerror_r(int ev) {
115
29
    char buffer[strerror_buff_size];
116
    // Preserve errno around the call. (The C++ standard requires that
117
    // system_error functions not modify errno).
118
29
    const int old_errno = errno;
119
29
    const char *error_message = handle_strerror_r_return(
120
29
        ::strerror_r(ev, buffer, strerror_buff_size), buffer);
121
    // If we didn't get any message, print one now.
122
29
    if (!error_message[0]) {
123
0
      std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
124
0
      error_message = buffer;
125
0
    }
126
29
    errno = old_errno;
127
29
    return string(error_message);
128
29
}
129
#endif
130
} // end namespace
131
#endif
132
133
string
134
__do_message::message(int ev) const
135
29
{
136
#if defined(_LIBCPP_HAS_NO_THREADS)
137
    return string(::strerror(ev));
138
#else
139
29
    return do_strerror_r(ev);
140
29
#endif
141
29
}
142
143
class _LIBCPP_HIDDEN __generic_error_category
144
    : public __do_message
145
{
146
public:
147
    virtual const char* name() const noexcept;
148
    virtual string message(int ev) const;
149
};
150
151
const char*
152
__generic_error_category::name() const noexcept
153
0
{
154
0
    return "generic";
155
0
}
156
157
string
158
__generic_error_category::message(int ev) const
159
29
{
160
29
#ifdef _LIBCPP_ELAST
161
29
    if (ev > _LIBCPP_ELAST)
162
0
      return string("unspecified generic_category error");
163
29
#endif // _LIBCPP_ELAST
164
29
    return __do_message::message(ev);
165
29
}
166
167
const error_category&
168
generic_category() noexcept
169
3.18M
{
170
3.18M
    static __generic_error_category s;
171
3.18M
    return s;
172
3.18M
}
173
174
class _LIBCPP_HIDDEN __system_error_category
175
    : public __do_message
176
{
177
public:
178
    virtual const char* name() const noexcept;
179
    virtual string message(int ev) const;
180
    virtual error_condition default_error_condition(int ev) const noexcept;
181
};
182
183
const char*
184
__system_error_category::name() const noexcept
185
0
{
186
0
    return "system";
187
0
}
188
189
string
190
__system_error_category::message(int ev) const
191
0
{
192
0
#ifdef _LIBCPP_ELAST
193
0
    if (ev > _LIBCPP_ELAST)
194
0
      return string("unspecified system_category error");
195
0
#endif // _LIBCPP_ELAST
196
0
    return __do_message::message(ev);
197
0
}
198
199
error_condition
200
__system_error_category::default_error_condition(int ev) const noexcept
201
0
{
202
0
#ifdef _LIBCPP_ELAST
203
0
    if (ev > _LIBCPP_ELAST)
204
0
      return error_condition(ev, system_category());
205
0
#endif // _LIBCPP_ELAST
206
0
    return error_condition(ev, generic_category());
207
0
}
208
209
const error_category&
210
system_category() noexcept
211
2.43M
{
212
2.43M
    static __system_error_category s;
213
2.43M
    return s;
214
2.43M
}
215
216
// error_condition
217
218
string
219
error_condition::message() const
220
0
{
221
0
    return __cat_->message(__val_);
222
0
}
223
224
// error_code
225
226
string
227
error_code::message() const
228
29
{
229
29
    return __cat_->message(__val_);
230
29
}
231
232
// system_error
233
234
string
235
system_error::__init(const error_code& ec, string what_arg)
236
0
{
237
0
    if (ec)
238
0
    {
239
0
        if (!what_arg.empty())
240
0
            what_arg += ": ";
241
0
        what_arg += ec.message();
242
0
    }
243
0
    return what_arg;
244
0
}
245
246
system_error::system_error(error_code ec, const string& what_arg)
247
    : runtime_error(__init(ec, what_arg)),
248
      __ec_(ec)
249
0
{
250
0
}
251
252
system_error::system_error(error_code ec, const char* what_arg)
253
    : runtime_error(__init(ec, what_arg)),
254
      __ec_(ec)
255
0
{
256
0
}
257
258
system_error::system_error(error_code ec)
259
    : runtime_error(__init(ec, "")),
260
      __ec_(ec)
261
0
{
262
0
}
263
264
system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
265
    : runtime_error(__init(error_code(ev, ecat), what_arg)),
266
      __ec_(error_code(ev, ecat))
267
0
{
268
0
}
269
270
system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
271
    : runtime_error(__init(error_code(ev, ecat), what_arg)),
272
      __ec_(error_code(ev, ecat))
273
0
{
274
0
}
275
276
system_error::system_error(int ev, const error_category& ecat)
277
    : runtime_error(__init(error_code(ev, ecat), "")),
278
      __ec_(error_code(ev, ecat))
279
0
{
280
0
}
281
282
system_error::~system_error() noexcept
283
0
{
284
0
}
285
286
void
287
__throw_system_error(int ev, const char* what_arg)
288
0
{
289
0
#ifndef _LIBCPP_NO_EXCEPTIONS
290
0
    throw system_error(error_code(ev, system_category()), what_arg);
291
#else
292
    (void)ev;
293
    (void)what_arg;
294
    _VSTD::abort();
295
#endif
296
0
}
297
298
_LIBCPP_END_NAMESPACE_STD