Skip to content

Commit

Permalink
[libc++] Diagnose when header search paths are set up incorrectly
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ldionne committed Aug 17, 2022
1 parent 8f8c816 commit 8cedff1
Show file tree
Hide file tree
Showing 17 changed files with 154 additions and 2 deletions.
8 changes: 8 additions & 0 deletions libcxx/include/cctype
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/cerrno
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/cfenv
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/cfloat
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/cinttypes
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/climits
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/clocale
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 10 additions & 1 deletion libcxx/include/cmath
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/csetjmp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 10 additions & 1 deletion libcxx/include/cstddef
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/cstdint
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/cstdio
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/cstdlib
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/cstring
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/cuchar
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/cwchar
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/cwctype
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 8cedff1

Please sign in to comment.