[libc] Add implementation of errno and define the other macros of errno.h.
Reviewers: stanshebs, alexbrachet
Subscribers: mgorny, MaskRay, tschuett, libc-commits
Tags: #libc-project
Differential Revision: https://reviews.llvm.org/D71094
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 00df588..f9a86af 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -1,4 +1,5 @@
-add_subdirectory(string)
+add_subdirectory(errno)
add_subdirectory(math)
+add_subdirectory(string)
add_subdirectory(__support)
diff --git a/libc/src/errno/CMakeLists.txt b/libc/src/errno/CMakeLists.txt
new file mode 100644
index 0000000..32d7262
--- /dev/null
+++ b/libc/src/errno/CMakeLists.txt
@@ -0,0 +1,19 @@
+add_entrypoint_object(
+ __errno_location
+ SRCS
+ errno_location.cpp
+ HDRS
+ llvmlibc_errno.h
+)
+
+add_custom_target(libc_errno_unittests)
+
+add_libc_unittest(
+ errno_test
+ SUITE
+ libc_errno_unittests
+ SRCS
+ errno_test.cpp
+ DEPENDS
+ __errno_location
+)
diff --git a/libc/src/errno/errno_location.cpp b/libc/src/errno/errno_location.cpp
new file mode 100644
index 0000000..1a1b288
--- /dev/null
+++ b/libc/src/errno/errno_location.cpp
@@ -0,0 +1,22 @@
+//===----------------- Implementation of __errno_location -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/errno/llvmlibc_errno.h"
+
+#include "src/__support/common.h"
+
+namespace __llvm_libc {
+
+static thread_local int __errno = 0;
+
+// __errno_location is not really an entry point but we still want it to behave
+// like an entry point because the errno macro resolves to the C symbol
+// "__errno_location".
+int *LLVM_LIBC_ENTRYPOINT(__errno_location)() { return &__errno; }
+
+} // namespace __llvm_libc
diff --git a/libc/src/errno/errno_test.cpp b/libc/src/errno/errno_test.cpp
new file mode 100644
index 0000000..1ca61d5
--- /dev/null
+++ b/libc/src/errno/errno_test.cpp
@@ -0,0 +1,17 @@
+//===---------------------- Unittests for errno --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/errno/llvmlibc_errno.h"
+
+#include "gtest/gtest.h"
+
+TEST(ErrnoTest, Basic) {
+ int test_val = 123;
+ llvmlibc_errno = test_val;
+ ASSERT_EQ(test_val, llvmlibc_errno);
+}
diff --git a/libc/src/errno/llvmlibc_errno.h b/libc/src/errno/llvmlibc_errno.h
new file mode 100644
index 0000000..b5a8fdd
--- /dev/null
+++ b/libc/src/errno/llvmlibc_errno.h
@@ -0,0 +1,22 @@
+//===------------------ Implementation header for errno -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_ERRNO_LLVMLIBC_ERRNO_H
+#define LLVM_LIBC_SRC_ERRNO_LLVMLIBC_ERRNO_H
+
+// Internal code should use this and not use the errno macro from the
+// public header.
+#define llvmlibc_errno (*__llvm_libc::__errno_location())
+
+namespace __llvm_libc {
+
+int *__errno_location();
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_ERRNO_LLVMLIBC_ERRNO_H