[libc++] Only include_next C library headers when they exist

Some platforms don't provide all C library headers. In practice, libc++
only requires a few C library headers to exist, and only a few functions
on those headers. Missing functions that libc++ doesn't need for its own
implementation are handled properly by the using_if_exists attribute,
however a missing header is currently a hard error when we try to
do #include_next.

This patch should make libc++ more flexible on platforms that do not
provide C headers that libc++ doesn't actually require for its own
implementation. The only downside is that it may move some errors from
the #include_next point to later in the compilation if we actually try
to use something that isn't provided, which could be somewhat confusing.
However, these errors should be caught by folks trying to port libc++
over to a new platform (when running the libc++ test suite), not by end
users.

NOTE: This is a reapplicaton of 226409, which was reverted in 674729813
      because it broke the build. The issue has now been fixed with
      https://reviews.llvm.org/D138062.

Differential Revision: https://reviews.llvm.org/D136683
This commit is contained in:
Louis Dionne
2022-11-15 17:08:01 -05:00
parent f81f0cb75a
commit 5d87f60f89
18 changed files with 60 additions and 32 deletions

View File

@@ -24,13 +24,9 @@
#endif
#ifdef __cplusplus
#include <ccomplex>
#else // __cplusplus
#include_next <complex.h>
#endif // __cplusplus
# include <ccomplex>
#elif __has_include_next(<complex.h>)
# include_next <complex.h>
#endif
#endif // _LIBCPP_COMPLEX_H

View File

@@ -35,7 +35,9 @@ int toupper(int c);
# pragma GCC system_header
#endif
#include_next <ctype.h>
#if __has_include_next(<ctype.h>)
# include_next <ctype.h>
#endif
#ifdef __cplusplus

View File

@@ -28,7 +28,9 @@ Macros:
# pragma GCC system_header
#endif
#include_next <errno.h>
#if __has_include_next(<errno.h>)
# include_next <errno.h>
#endif
#ifdef __cplusplus

View File

@@ -56,7 +56,9 @@ int feupdateenv(const fenv_t* envp);
# pragma GCC system_header
#endif
#include_next <fenv.h>
#if __has_include_next(<fenv.h>)
# include_next <fenv.h>
#endif
#ifdef __cplusplus

View File

@@ -76,7 +76,9 @@ Macros:
# pragma GCC system_header
#endif
#include_next <float.h>
#if __has_include_next(<float.h>)
# include_next <float.h>
#endif
#ifdef __cplusplus

View File

@@ -248,7 +248,9 @@ uintmax_t wcstoumax(const wchar_t* restrict nptr, wchar_t** restrict endptr, int
# define __STDC_FORMAT_MACROS
#endif
#include_next <inttypes.h>
#if __has_include_next(<inttypes.h>)
# include_next <inttypes.h>
#endif
#ifdef __cplusplus

View File

@@ -44,7 +44,11 @@ Macros:
#endif
#ifndef __GNUC__
#include_next <limits.h>
# if __has_include_next(<limits.h>)
# include_next <limits.h>
# endif
#else
// GCC header limits.h recursively includes itself through another header called
// syslimits.h for some reason. This setup breaks down if we directly

View File

@@ -43,6 +43,8 @@ Functions:
# pragma GCC system_header
#endif
#include_next <locale.h>
#if __has_include_next(<locale.h>)
# include_next <locale.h>
#endif
#endif // _LIBCPP_LOCALE_H

View File

@@ -297,7 +297,9 @@ long double truncl(long double x);
# pragma GCC system_header
#endif
#include_next <math.h>
# if __has_include_next(<math.h>)
# include_next <math.h>
# endif
#ifdef __cplusplus

View File

@@ -31,7 +31,9 @@ void longjmp(jmp_buf env, int val);
# pragma GCC system_header
#endif
#include_next <setjmp.h>
#if __has_include_next(<setjmp.h>)
# include_next <setjmp.h>
#endif
#ifdef __cplusplus

View File

@@ -24,7 +24,9 @@ Macros:
# pragma GCC system_header
#endif
#include_next <stdbool.h>
#if __has_include_next(<stdbool.h>)
# include_next <stdbool.h>
#endif
#ifdef __cplusplus
#undef bool

View File

@@ -42,7 +42,9 @@ Types:
# pragma GCC system_header
#endif
#include_next <stddef.h>
# if __has_include_next(<stddef.h>)
# include_next <stddef.h>
# endif
#ifdef __cplusplus
typedef decltype(nullptr) nullptr_t;

View File

@@ -120,6 +120,8 @@ Macros:
# define __STDC_CONSTANT_MACROS
#endif
#include_next <stdint.h>
#if __has_include_next(<stdint.h>)
# include_next <stdint.h>
#endif
#endif // _LIBCPP_STDINT_H

View File

@@ -104,7 +104,9 @@ void perror(const char* s);
# pragma GCC system_header
#endif
#include_next <stdio.h>
# if __has_include_next(<stdio.h>)
# include_next <stdio.h>
# endif
#ifdef __cplusplus

View File

@@ -90,7 +90,9 @@ void *aligned_alloc(size_t alignment, size_t size); // C11
# pragma GCC system_header
#endif
#include_next <stdlib.h>
# if __has_include_next(<stdlib.h>)
# include_next <stdlib.h>
# endif
#ifdef __cplusplus
extern "C++" {

View File

@@ -57,7 +57,9 @@ size_t strlen(const char* s);
# pragma GCC system_header
#endif
#include_next <string.h>
#if __has_include_next(<string.h>)
# include_next <string.h>
#endif
// MSVCRT, GNU libc and its derivates may already have the correct prototype in
// <string.h>. This macro can be defined by users if their C library provides

View File

@@ -24,13 +24,11 @@
#endif
#ifdef __cplusplus
#include <ctgmath>
#else // __cplusplus
#include_next <tgmath.h>
#endif // __cplusplus
# include <ctgmath>
#else
# if __has_include_next(<tgmath.h>)
# include_next <tgmath.h>
# endif
#endif
#endif // _LIBCPP_TGMATH_H

View File

@@ -120,7 +120,9 @@ size_t wcsrtombs(char* restrict dst, const wchar_t** restrict src, size_t len,
#define __CORRECT_ISO_CPP_WCHAR_H_PROTO
#endif
#include_next <wchar.h>
# if __has_include_next(<wchar.h>)
# include_next <wchar.h>
# endif
// Determine whether we have const-correct overloads for wcschr and friends.
#if defined(_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_)