[libcxx-commits] [libcxx] 8cedff1 - [libc++] Diagnose when header search paths are set up incorrectly
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Aug 17 11:05:40 PDT 2022
Author: Louis Dionne
Date: 2022-08-17T14:05:26-04:00
New Revision: 8cedff10a18d8eba9190a645626fa6a509c1f139
URL: https://github.com/llvm/llvm-project/commit/8cedff10a18d8eba9190a645626fa6a509c1f139
DIFF: https://github.com/llvm/llvm-project/commit/8cedff10a18d8eba9190a645626fa6a509c1f139.diff
LOG: [libc++] Diagnose when header search paths are set up incorrectly
An issue I often see in codebases compiled for unusual platforms is
that header search paths are specified manually and are subtly wrong.
For example, people will manually add `-isystem <some-toolchain>/usr/include`,
which ends up messing up the layering of header search paths required by
libc++ (because the C Standard Library now appears *before* libc++ in
the search paths). Without this patch, this will end up causing
compilation errors that are pretty inscrutable. This patch aims to
improve the user experience by diagnosing this issue explicitly.
In all cases I can think of, I would expect that a compilation error
occur if these header search paths are not layered properly. This
should only provide an explicit diagnostic instead of failing due
to seemingly unrelated compilation errors.
Differential Revision: https://reviews.llvm.org/D131441
Added:
Modified:
libcxx/include/cctype
libcxx/include/cerrno
libcxx/include/cfenv
libcxx/include/cfloat
libcxx/include/cinttypes
libcxx/include/climits
libcxx/include/clocale
libcxx/include/cmath
libcxx/include/csetjmp
libcxx/include/cstddef
libcxx/include/cstdint
libcxx/include/cstdio
libcxx/include/cstdlib
libcxx/include/cstring
libcxx/include/cuchar
libcxx/include/cwchar
libcxx/include/cwctype
Removed:
################################################################################
diff --git a/libcxx/include/cctype b/libcxx/include/cctype
index 248f8d98000f..867e7d5b0b35 100644
--- a/libcxx/include/cctype
+++ b/libcxx/include/cctype
@@ -36,8 +36,16 @@ int toupper(int c);
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+
#include <ctype.h>
+#ifndef _LIBCPP_CTYPE_H
+# error <cctype> tried including <ctype.h> but didn't find libc++'s <ctype.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cerrno b/libcxx/include/cerrno
index e9eacd35effe..937ec23c6971 100644
--- a/libcxx/include/cerrno
+++ b/libcxx/include/cerrno
@@ -24,8 +24,17 @@ Macros:
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+
#include <errno.h>
+#ifndef _LIBCPP_ERRNO_H
+# error <cerrno> tried including <errno.h> but didn't find libc++'s <errno.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cfenv b/libcxx/include/cfenv
index e42b46680d15..16b3761ee27b 100644
--- a/libcxx/include/cfenv
+++ b/libcxx/include/cfenv
@@ -54,8 +54,17 @@ int feupdateenv(const fenv_t* envp);
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+
#include <fenv.h>
+#ifndef _LIBCPP_FENV_H
+# error <cfenv> tried including <fenv.h> but didn't find libc++'s <fenv.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cfloat b/libcxx/include/cfloat
index 36a7c51cdda5..4f991dd49ff4 100644
--- a/libcxx/include/cfloat
+++ b/libcxx/include/cfloat
@@ -71,8 +71,17 @@ Macros:
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+
#include <float.h>
+#ifndef _LIBCPP_FLOAT_H
+# error <cfloat> tried including <float.h> but didn't find libc++'s <float.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cinttypes b/libcxx/include/cinttypes
index a4cfe961cc55..09304460986a 100644
--- a/libcxx/include/cinttypes
+++ b/libcxx/include/cinttypes
@@ -237,8 +237,17 @@ uintmax_t wcstoumax(const wchar_t* restrict nptr, wchar_t** restrict endptr, int
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
#include <cstdint>
+
#include <inttypes.h>
+#ifndef _LIBCPP_INTTYPES_H
+# error <cinttypes> tried including <inttypes.h> but didn't find libc++'s <inttypes.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/climits b/libcxx/include/climits
index 16800a652f6d..d773af50d299 100644
--- a/libcxx/include/climits
+++ b/libcxx/include/climits
@@ -39,8 +39,17 @@ Macros:
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+
#include <limits.h>
+#ifndef _LIBCPP_LIMITS_H
+# error <climits> tried including <limits.h> but didn't find libc++'s <limits.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/clocale b/libcxx/include/clocale
index 892604207532..e2ace355d7b6 100644
--- a/libcxx/include/clocale
+++ b/libcxx/include/clocale
@@ -36,8 +36,17 @@ lconv* localeconv();
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+
#include <locale.h>
+#ifndef _LIBCPP_LOCALE_H
+# error <clocale> tried including <locale.h> but didn't find libc++'s <locale.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 65a853165a98..ef3a67843e10 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -306,10 +306,19 @@ constexpr long double lerp(long double a, long double b, long double t) noexcept
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
-#include <math.h>
#include <type_traits>
#include <version>
+#include <math.h>
+
+#ifndef _LIBCPP_MATH_H
+# error <cmath> tried including <math.h> but didn't find libc++'s <math.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/csetjmp b/libcxx/include/csetjmp
index 4f40bcbf61e9..4c64e8327e3f 100644
--- a/libcxx/include/csetjmp
+++ b/libcxx/include/csetjmp
@@ -32,8 +32,17 @@ void longjmp(jmp_buf env, int val);
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+
#include <setjmp.h>
+#ifndef _LIBCPP_SETJMP_H
+# error <csetjmp> tried including <setjmp.h> but didn't find libc++'s <setjmp.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cstddef b/libcxx/include/cstddef
index 7be4348038e1..e3c066917570 100644
--- a/libcxx/include/cstddef
+++ b/libcxx/include/cstddef
@@ -38,9 +38,18 @@ Types:
#include <__type_traits/enable_if.h>
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_integral.h>
-#include <stddef.h>
#include <version>
+#include <stddef.h>
+
+#ifndef _LIBCPP_STDDEF_H
+# error <cstddef> tried including <stddef.h> but didn't find libc++'s <stddef.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cstdint b/libcxx/include/cstdint
index 83cda947b497..829d9398f387 100644
--- a/libcxx/include/cstdint
+++ b/libcxx/include/cstdint
@@ -142,8 +142,17 @@ Types:
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+
#include <stdint.h>
+#ifndef _LIBCPP_STDINT_H
+# error <cstdint> tried including <stdint.h> but didn't find libc++'s <stdint.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cstdio b/libcxx/include/cstdio
index d191086a85da..221b0b314cf9 100644
--- a/libcxx/include/cstdio
+++ b/libcxx/include/cstdio
@@ -97,8 +97,17 @@ void perror(const char* s);
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+
#include <stdio.h>
+#ifndef _LIBCPP_STDIO_H
+# error <cstdio> tried including <stdio.h> but didn't find libc++'s <stdio.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cstdlib b/libcxx/include/cstdlib
index 457c31f625d8..25c9de5165c2 100644
--- a/libcxx/include/cstdlib
+++ b/libcxx/include/cstdlib
@@ -83,8 +83,17 @@ void *aligned_alloc(size_t alignment, size_t size); // C11
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+
#include <stdlib.h>
+#ifndef _LIBCPP_STDLIB_H
+# error <cstdlib> tried including <stdlib.h> but didn't find libc++'s <stdlib.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cstring b/libcxx/include/cstring
index 37c92e149b8f..42bbe73924d3 100644
--- a/libcxx/include/cstring
+++ b/libcxx/include/cstring
@@ -58,8 +58,17 @@ size_t strlen(const char* s);
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+
#include <string.h>
+#ifndef _LIBCPP_STRING_H
+# error <cstring> tried including <string.h> but didn't find libc++'s <string.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cuchar b/libcxx/include/cuchar
index a4ed585d1aeb..b685f470301d 100644
--- a/libcxx/include/cuchar
+++ b/libcxx/include/cuchar
@@ -36,8 +36,17 @@ size_t c32rtomb(char* s, char32_t c32, mbstate_t* ps);
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+
#include <uchar.h>
+#ifndef _LIBCPP_UCHAR_H
+# error <cuchar> tried including <uchar.h> but didn't find libc++'s <uchar.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cwchar b/libcxx/include/cwchar
index 5c69ab2a7bb1..220c817072de 100644
--- a/libcxx/include/cwchar
+++ b/libcxx/include/cwchar
@@ -105,8 +105,17 @@ size_t wcsrtombs(char* restrict dst, const wchar_t** restrict src, size_t len,
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
#include <cwctype>
+
#include <wchar.h>
+#ifndef _LIBCPP_WCHAR_H
+# error <cwchar> tried including <wchar.h> but didn't find libc++'s <wchar.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
diff --git a/libcxx/include/cwctype b/libcxx/include/cwctype
index 429b00c2446d..5a2d2427d847 100644
--- a/libcxx/include/cwctype
+++ b/libcxx/include/cwctype
@@ -52,8 +52,17 @@ wctrans_t wctrans(const char* property);
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
#include <cctype>
+
#include <wctype.h>
+#ifndef _LIBCPP_WCTYPE_H
+# error <cwctype> tried including <wctype.h> but didn't find libc++'s <wctype.h> header. \
+ This usually means that your header search paths are not configured properly. \
+ The header search paths should contain the C++ Standard Library headers before \
+ any C Standard Library, and you are probably using compiler flags that make that \
+ not be the case.
+#endif
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
More information about the libcxx-commits
mailing list