[libc++][Android] Allow testing libc++ with clang-r536225 (#116149)
[llvm-project.git] / libc / src / errno / libc_errno.cpp
blobd1600d1b050e3334d066057b3344ce63e7c51791
1 //===-- Implementation of libc_errno --------------------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include "libc_errno.h"
10 #include "src/__support/macros/config.h"
12 // libc uses a fallback default value, either system or thread local.
13 #define LIBC_ERRNO_MODE_DEFAULT 0
14 // libc never stores a value; `errno` macro uses get link-time failure.
15 #define LIBC_ERRNO_MODE_UNDEFINED 1
16 // libc maintains per-thread state (requires C++ `thread_local` support).
17 #define LIBC_ERRNO_MODE_THREAD_LOCAL 2
18 // libc maintains shared state used by all threads, contrary to standard C
19 // semantics unless always single-threaded; nothing prevents data races.
20 #define LIBC_ERRNO_MODE_SHARED 3
21 // libc doesn't maintain any internal state, instead the embedder must define
22 // `int *__llvm_libc_errno(void);` C function.
23 #define LIBC_ERRNO_MODE_EXTERNAL 4
24 // libc uses system `<errno.h>` `errno` macro directly in the overlay mode; in
25 // fullbuild mode, effectively the same as `LIBC_ERRNO_MODE_EXTERNAL`.
26 #define LIBC_ERRNO_MODE_SYSTEM 5
28 #if !defined(LIBC_ERRNO_MODE) || LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_DEFAULT
29 #undef LIBC_ERRNO_MODE
30 #if defined(LIBC_FULL_BUILD) || !defined(LIBC_COPT_PUBLIC_PACKAGING)
31 #define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_THREAD_LOCAL
32 #else
33 #define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM
34 #endif
35 #endif // LIBC_ERRNO_MODE
37 #if LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_DEFAULT && \
38 LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_UNDEFINED && \
39 LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_THREAD_LOCAL && \
40 LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SHARED && \
41 LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_EXTERNAL && \
42 LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SYSTEM
43 #error LIBC_ERRNO_MODE must be one of the following values: \
44 LIBC_ERRNO_MODE_DEFAULT, \
45 LIBC_ERRNO_MODE_UNDEFINED, \
46 LIBC_ERRNO_MODE_THREAD_LOCAL, \
47 LIBC_ERRNO_MODE_SHARED, \
48 LIBC_ERRNO_MODE_EXTERNAL, \
49 LIBC_ERRNO_MODE_SYSTEM
50 #endif
52 namespace LIBC_NAMESPACE_DECL {
54 #if LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_UNDEFINED
56 void Errno::operator=(int) {}
57 Errno::operator int() { return 0; }
59 #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_THREAD_LOCAL
61 namespace {
62 LIBC_THREAD_LOCAL int thread_errno;
65 extern "C" int *__llvm_libc_errno() noexcept { return &thread_errno; }
67 void Errno::operator=(int a) { thread_errno = a; }
68 Errno::operator int() { return thread_errno; }
70 #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_SHARED
72 namespace {
73 int shared_errno;
76 extern "C" int *__llvm_libc_errno() noexcept { return &shared_errno; }
78 void Errno::operator=(int a) { shared_errno = a; }
79 Errno::operator int() { return shared_errno; }
81 #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_EXTERNAL
83 void Errno::operator=(int a) { *__llvm_libc_errno() = a; }
84 Errno::operator int() { return *__llvm_libc_errno(); }
86 #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_SYSTEM
88 void Errno::operator=(int a) { errno = a; }
89 Errno::operator int() { return errno; }
91 #endif
93 // Define the global `libc_errno` instance.
94 Errno libc_errno;
96 } // namespace LIBC_NAMESPACE_DECL