diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index a09b630a21..a468100e10 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -280,11 +280,30 @@ To run include what you use, install (`brew install include-what-you-use` on macOS), then run: ```bash -cmake -S . -B build-iwyu -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=$(which include-what-you-use) -cmake --build build-iwyu +cmake --preset iwyu +cmake --build --preset iwyu ``` -The report is sent to stderr; you can pipe it into a file if you wish. +The build always succeeds and IWYU writes its advice to stderr; pipe the build +output into a file if you wish. Nothing enforces the result, so read the +report and apply what is correct, with these cautions: + +- The same header is reported once per translation unit that includes it, so + deduplicate before acting. +- Only act on a removal that both standard libraries (macOS and Linux) agree + on; take an addition from either. +- `` must stay the first include (via `detail/common.h`); do not let + a reorder suggestion move it. +- Ignore "should add" lines for `` and other headers that are not real + public headers; a mapping for `` makes IWYU abort. + +Two support files drive the analysis. `tools/iwyu.sh` wraps +`include-what-you-use` and asks it to also check every pybind11 header, except +`pybind11.h` and `cast.h`, which crash IWYU 0.26. `tools/iwyu.imp` maps the +headers a suggestion must not name to the one pybind11 should use: CPython +internals to ``, libc++ detail headers and the C headers of +libstdc++ to the standard C++ header. Read the comment at its top before you +add an entry. ### Build recipes diff --git a/CMakePresets.json b/CMakePresets.json index 42bf3ade9d..b4ccf0ba73 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -38,6 +38,18 @@ "CMAKE_CXX_CLANG_TIDY": "clang-tidy;--use-color;--warnings-as-errors=*", "CMAKE_CXX_STANDARD": "17" } + }, + { + "name": "iwyu", + "displayName": "Include-what-you-use", + "inherits": "venv", + "binaryDir": "build-iwyu", + "cacheVariables": { + "CMAKE_CXX_INCLUDE_WHAT_YOU_USE": "${sourceDir}/tools/iwyu.sh", + "CMAKE_CXX_STANDARD": "17", + "CMAKE_OSX_SYSROOT": "macosx", + "PYBIND11_WERROR": false + } } ], "buildPresets": [ @@ -57,6 +69,11 @@ "configurePreset": "tidy", "nativeToolOptions": ["-k0"] }, + { + "name": "iwyu", + "displayName": "Include-what-you-use Build", + "configurePreset": "iwyu" + }, { "name": "tests", "displayName": "Tests (for workflow)", diff --git a/include/pybind11/attr.h b/include/pybind11/attr.h index d337595a0b..42e201dc39 100644 --- a/include/pybind11/attr.h +++ b/include/pybind11/attr.h @@ -11,10 +11,21 @@ #pragma once #include "detail/common.h" +#include "detail/internals.h" +#include "detail/type_caster_base.h" +#include "detail/typeid.h" +#include "detail/value_and_holder.h" #include "cast.h" +#include "pytypes.h" #include "trampoline_self_life_support.h" +#include #include +#include +#include +#include +#include +#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) diff --git a/include/pybind11/buffer_info.h b/include/pybind11/buffer_info.h index 10fa825a81..5ff4a8db67 100644 --- a/include/pybind11/buffer_info.h +++ b/include/pybind11/buffer_info.h @@ -11,6 +11,11 @@ #include "detail/common.h" +#include +#include +#include +#include + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) diff --git a/include/pybind11/chrono.h b/include/pybind11/chrono.h index 668e458e99..ac4f0005ca 100644 --- a/include/pybind11/chrono.h +++ b/include/pybind11/chrono.h @@ -11,12 +11,17 @@ #pragma once #include "pybind11.h" +#include "detail/common.h" +#include "detail/descr.h" +#include "cast.h" +#include "pytypes.h" #include -#include +#include #include #include #include +#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) diff --git a/include/pybind11/complex.h b/include/pybind11/complex.h index a6ec11a462..8dadbea458 100644 --- a/include/pybind11/complex.h +++ b/include/pybind11/complex.h @@ -10,8 +10,14 @@ #pragma once #include "pybind11.h" +#include "detail/common.h" +#include "detail/descr.h" +#include "cast.h" +#include "pytypes.h" #include +#include +#include /// glibc defines I as a macro which breaks things, e.g., boost template names #ifdef I diff --git a/include/pybind11/conduit/wrap_include_python_h.h b/include/pybind11/conduit/wrap_include_python_h.h index 713dc4bb6a..07bfd8ff6d 100644 --- a/include/pybind11/conduit/wrap_include_python_h.h +++ b/include/pybind11/conduit/wrap_include_python_h.h @@ -41,9 +41,9 @@ // C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed #endif -#include -#include -#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export #if defined(_MSC_VER) # pragma warning(pop) diff --git a/include/pybind11/critical_section.h b/include/pybind11/critical_section.h index 2d26412047..758a7c719d 100644 --- a/include/pybind11/critical_section.h +++ b/include/pybind11/critical_section.h @@ -4,6 +4,7 @@ #pragma once +#include "detail/pybind11_namespace_macros.h" #include "pytypes.h" PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) diff --git a/include/pybind11/detail/argument_vector.h b/include/pybind11/detail/argument_vector.h index 6e2c2ec481..0bd42f9eed 100644 --- a/include/pybind11/detail/argument_vector.h +++ b/include/pybind11/detail/argument_vector.h @@ -16,10 +16,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include diff --git a/include/pybind11/detail/class.h b/include/pybind11/detail/class.h index 06a761de54..4209092a43 100644 --- a/include/pybind11/detail/class.h +++ b/include/pybind11/detail/class.h @@ -12,7 +12,29 @@ #include #include +#include "../buffer_info.h" +#include "../cast.h" +#include "../pytypes.h" +#include "../trampoline_self_life_support.h" +#include "common.h" +#include "cpp_conduit.h" #include "exception_translation.h" +#include "internals.h" +#include "type_caster_base.h" +#include "value_and_holder.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 7f182afb2c..e090c4803d 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -9,7 +9,13 @@ #pragma once -#include +#include // IWYU pragma: export + +#include +#include +#include +#include +#include #if PY_VERSION_HEX < 0x03090000 # error "PYTHON < 3.9 IS UNSUPPORTED. pybind11 v3.0 was the last to support Python 3.8." #endif @@ -44,7 +50,7 @@ PYBIND11_VERSION_RELEASE_LEVEL, \ PYBIND11_VERSION_RELEASE_SERIAL) -#include "pybind11_namespace_macros.h" +#include "pybind11_namespace_macros.h" // IWYU pragma: export #if !(defined(_MSC_VER) && __cplusplus == 199711L) # if __cplusplus >= 201402L @@ -229,14 +235,10 @@ #include #include #include -#include #include #include #include #include -#include -#include -#include #include #if defined(__has_include) # if __has_include() diff --git a/include/pybind11/detail/cpp_conduit.h b/include/pybind11/detail/cpp_conduit.h index 49c199e14f..465872e837 100644 --- a/include/pybind11/detail/cpp_conduit.h +++ b/include/pybind11/detail/cpp_conduit.h @@ -4,6 +4,7 @@ #include +#include "../conduit/pybind11_platform_abi_id.h" #include "common.h" #include "internals.h" diff --git a/include/pybind11/detail/descr.h b/include/pybind11/detail/descr.h index 4f5ae34fc8..baf29148dd 100644 --- a/include/pybind11/detail/descr.h +++ b/include/pybind11/detail/descr.h @@ -11,6 +11,11 @@ #include "common.h" +#include +#include +#include +#include + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) diff --git a/include/pybind11/detail/exception_translation.h b/include/pybind11/detail/exception_translation.h index 22ae8a1c94..a105da6165 100644 --- a/include/pybind11/detail/exception_translation.h +++ b/include/pybind11/detail/exception_translation.h @@ -9,9 +9,13 @@ #pragma once +#include "../pytypes.h" #include "common.h" #include "internals.h" +#include +#include + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) diff --git a/include/pybind11/detail/function_record_pyobject.h b/include/pybind11/detail/function_record_pyobject.h index 42b0e96be7..c7c1c61150 100644 --- a/include/pybind11/detail/function_record_pyobject.h +++ b/include/pybind11/detail/function_record_pyobject.h @@ -10,7 +10,9 @@ #include #include +#include "../cast.h" #include "common.h" +#include "internals.h" #include #include diff --git a/include/pybind11/detail/function_ref.h b/include/pybind11/detail/function_ref.h index a81bdfe13f..7626184f39 100644 --- a/include/pybind11/detail/function_ref.h +++ b/include/pybind11/detail/function_ref.h @@ -41,6 +41,7 @@ #include +#include #include #include #include diff --git a/include/pybind11/detail/holder_caster_foreign_helpers.h b/include/pybind11/detail/holder_caster_foreign_helpers.h index cae571b65c..5705d6bdd2 100644 --- a/include/pybind11/detail/holder_caster_foreign_helpers.h +++ b/include/pybind11/detail/holder_caster_foreign_helpers.h @@ -12,8 +12,12 @@ #include +#include "../pytypes.h" #include "common.h" +#include +#include + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) diff --git a/include/pybind11/detail/init.h b/include/pybind11/detail/init.h index a1083f8457..0d690f22dd 100644 --- a/include/pybind11/detail/init.h +++ b/include/pybind11/detail/init.h @@ -9,8 +9,20 @@ #pragma once -#include "class.h" +#include "../attr.h" +#include "../cast.h" +#include "../pytypes.h" +#include "common.h" +#include "descr.h" +#include "internals.h" +#include "struct_smart_holder.h" +#include "type_caster_base.h" #include "using_smart_holder.h" +#include "value_and_holder.h" + +#include +#include +#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) diff --git a/include/pybind11/detail/internals.h b/include/pybind11/detail/internals.h index 7107b70688..72a07e9645 100644 --- a/include/pybind11/detail/internals.h +++ b/include/pybind11/detail/internals.h @@ -14,15 +14,31 @@ #include #include +#include "../buffer_info.h" #include "common.h" #include "struct_smart_holder.h" +#include "value_and_holder.h" #include #include +#include #include +#include +#include #include +#include #include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include /// Tracks the `internals` and `type_info` ABI version independent of the main library version. /// diff --git a/include/pybind11/detail/native_enum_data.h b/include/pybind11/detail/native_enum_data.h index 6770378fc1..897728849b 100644 --- a/include/pybind11/detail/native_enum_data.h +++ b/include/pybind11/detail/native_enum_data.h @@ -12,6 +12,7 @@ #include #include #include +#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) diff --git a/include/pybind11/detail/type_caster_base.h b/include/pybind11/detail/type_caster_base.h index 161b9884fa..6fa425deb5 100644 --- a/include/pybind11/detail/type_caster_base.h +++ b/include/pybind11/detail/type_caster_base.h @@ -11,27 +11,32 @@ #include #include -#include +#include "../conduit/pybind11_platform_abi_id.h" #include "common.h" #include "cpp_conduit.h" #include "descr.h" -#include "dynamic_raw_ptr_cast_if_possible.h" #include "internals.h" +#include "struct_smart_holder.h" #include "typeid.h" #include "using_smart_holder.h" #include "value_and_holder.h" +#include #include #include +#include #include +#include #include #include #include +#include #include #include #include #include +#include #include #include diff --git a/include/pybind11/detail/typeid.h b/include/pybind11/detail/typeid.h index a67b52135b..f62a1f696b 100644 --- a/include/pybind11/detail/typeid.h +++ b/include/pybind11/detail/typeid.h @@ -9,8 +9,10 @@ #pragma once -#include #include +#include +#include +#include #if defined(__GNUG__) # include diff --git a/include/pybind11/detail/value_and_holder.h b/include/pybind11/detail/value_and_holder.h index b24551e678..f169ab39a5 100644 --- a/include/pybind11/detail/value_and_holder.h +++ b/include/pybind11/detail/value_and_holder.h @@ -6,9 +6,7 @@ #include "common.h" -#include #include -#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) diff --git a/include/pybind11/eigen/matrix.h b/include/pybind11/eigen/matrix.h index ca599c954c..3ebcfc57eb 100644 --- a/include/pybind11/eigen/matrix.h +++ b/include/pybind11/eigen/matrix.h @@ -11,8 +11,18 @@ #include +#include "../pybind11.h" +#include "../detail/common.h" +#include "../detail/descr.h" +#include "../detail/type_caster_base.h" +#include "../cast.h" +#include "../pytypes.h" #include "common.h" +#include +#include +#include + /* HINT: To suppress warnings originating from the Eigen headers, use -isystem. See also: https://stackoverflow.com/questions/2579576/i-dir-vs-isystem-dir diff --git a/include/pybind11/eigen/tensor.h b/include/pybind11/eigen/tensor.h index e5c8441032..3e82e722ac 100644 --- a/include/pybind11/eigen/tensor.h +++ b/include/pybind11/eigen/tensor.h @@ -9,8 +9,21 @@ #include +#include "../detail/common.h" +#include "../detail/descr.h" +#include "../detail/type_caster_base.h" +#include "../cast.h" +#include "../pytypes.h" #include "common.h" +#include +#include +#include +#include +#include + +#include + #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) static_assert(__GNUC__ > 5, "Eigen Tensor support in pybind11 requires GCC > 5.0"); #endif diff --git a/include/pybind11/embed.h b/include/pybind11/embed.h index 078f4198eb..27ce1372e6 100644 --- a/include/pybind11/embed.h +++ b/include/pybind11/embed.h @@ -10,8 +10,12 @@ #pragma once #include "pybind11.h" +#include "detail/common.h" +#include "detail/internals.h" #include "eval.h" +#include + #if defined(PYPY_VERSION) # error Embedding the interpreter is not supported with PyPy #endif diff --git a/include/pybind11/eval.h b/include/pybind11/eval.h index ee24fd3584..d84ae11f7c 100644 --- a/include/pybind11/eval.h +++ b/include/pybind11/eval.h @@ -12,7 +12,12 @@ #pragma once #include "pybind11.h" +#include "detail/common.h" +#include "cast.h" +#include "pytypes.h" +#include +#include #include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) diff --git a/include/pybind11/functional.h b/include/pybind11/functional.h index c06fabe0d6..ef69750b4d 100644 --- a/include/pybind11/functional.h +++ b/include/pybind11/functional.h @@ -10,8 +10,19 @@ #pragma once #include "pybind11.h" +#include "detail/common.h" +#include "detail/descr.h" +#include "detail/function_record_pyobject.h" +#include "detail/internals.h" +#include "attr.h" +#include "cast.h" +#include "gil.h" +#include "pytypes.h" #include +#include +#include +#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) diff --git a/include/pybind11/gil_safe_call_once.h b/include/pybind11/gil_safe_call_once.h index af26272d48..22ba4c0400 100644 --- a/include/pybind11/gil_safe_call_once.h +++ b/include/pybind11/gil_safe_call_once.h @@ -14,7 +14,6 @@ #endif #ifdef PYBIND11_HAS_SUBINTERPRETER_SUPPORT # include -# include # include #endif diff --git a/include/pybind11/iostream.h b/include/pybind11/iostream.h index df7fa3c381..2bbf1de2e9 100644 --- a/include/pybind11/iostream.h +++ b/include/pybind11/iostream.h @@ -20,14 +20,19 @@ #pragma once #include "pybind11.h" +#include "detail/common.h" +#include "detail/descr.h" +#include "detail/internals.h" +#include "attr.h" +#include "cast.h" +#include "gil.h" +#include "pytypes.h" #include #include #include #include #include -#include -#include #include #include diff --git a/include/pybind11/native_enum.h b/include/pybind11/native_enum.h index af166d0c86..f5802529ec 100644 --- a/include/pybind11/native_enum.h +++ b/include/pybind11/native_enum.h @@ -5,14 +5,14 @@ #pragma once #include "detail/common.h" +#include "detail/internals.h" #include "detail/native_enum_data.h" #include "detail/type_caster_base.h" #include "cast.h" +#include "pytypes.h" #include -#include #include -#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index 10c0c9446c..271b62fd68 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -11,21 +11,29 @@ #include "pybind11.h" #include "detail/common.h" +#include "detail/descr.h" +#include "detail/internals.h" +#include "buffer_info.h" +#include "cast.h" #include "complex.h" #include "gil_safe_call_once.h" #include "pytypes.h" #include #include +#include +#include #include -#include -#include #include #include #include +#include #include +#include #include #include +#include +#include #include #include diff --git a/include/pybind11/operators.h b/include/pybind11/operators.h index 16a88ae171..479c219390 100644 --- a/include/pybind11/operators.h +++ b/include/pybind11/operators.h @@ -10,6 +10,12 @@ #pragma once #include "pybind11.h" +#include "detail/pybind11_namespace_macros.h" +#include "attr.h" + +#include +#include +#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index 13a6ebaa4d..b1be641fbd 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -14,14 +14,16 @@ #include #include +#include #include -#include #include #include +#include #include #include #include #include +#include #if defined(PYBIND11_HAS_OPTIONAL) # include diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index 01be0b47c6..611d058aa6 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -13,7 +13,12 @@ #include "detail/common.h" #include "detail/descr.h" #include "detail/type_caster_base.h" +#include "cast.h" +#include "pytypes.h" +#include +#include +#include #include #include #include @@ -21,9 +26,13 @@ #include #include #include +#include +#include #include #include +#include #include +#include // See `detail/common.h` for implementation of these guards. #if defined(PYBIND11_HAS_OPTIONAL) diff --git a/include/pybind11/stl/filesystem.h b/include/pybind11/stl/filesystem.h index 52d2962107..ac4a4834a9 100644 --- a/include/pybind11/stl/filesystem.h +++ b/include/pybind11/stl/filesystem.h @@ -11,6 +11,7 @@ #include #include +#include #if defined(PYBIND11_HAS_FILESYSTEM) # include diff --git a/include/pybind11/stl_bind.h b/include/pybind11/stl_bind.h index 360c2cd7bc..90e8e4c3b4 100644 --- a/include/pybind11/stl_bind.h +++ b/include/pybind11/stl_bind.h @@ -9,14 +9,28 @@ #pragma once +#include "pybind11.h" #include "detail/common.h" +#include "detail/descr.h" +#include "detail/internals.h" #include "detail/type_caster_base.h" +#include "attr.h" +#include "buffer_info.h" #include "cast.h" #include "operators.h" +#include "pytypes.h" #include +#include +#include +#include +#include #include +#include +#include #include +#include +#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) diff --git a/include/pybind11/subinterpreter.h b/include/pybind11/subinterpreter.h index def101ff62..c25eaa614d 100644 --- a/include/pybind11/subinterpreter.h +++ b/include/pybind11/subinterpreter.h @@ -12,8 +12,12 @@ #include "detail/common.h" #include "detail/internals.h" #include "gil.h" +#include "pytypes.h" +#include +#include #include +#include #ifndef PYBIND11_HAS_SUBINTERPRETER_SUPPORT # error "This platform does not support subinterpreters, do not include this file." diff --git a/include/pybind11/trampoline_self_life_support.h b/include/pybind11/trampoline_self_life_support.h index cbfec7f974..65a772dfc6 100644 --- a/include/pybind11/trampoline_self_life_support.h +++ b/include/pybind11/trampoline_self_life_support.h @@ -5,6 +5,7 @@ #pragma once #include "detail/common.h" +#include "detail/struct_smart_holder.h" #include "detail/using_smart_holder.h" #include "detail/value_and_holder.h" diff --git a/include/pybind11/type_caster_pyobject_ptr.h b/include/pybind11/type_caster_pyobject_ptr.h index aa914f9e15..cfa72e0da6 100644 --- a/include/pybind11/type_caster_pyobject_ptr.h +++ b/include/pybind11/type_caster_pyobject_ptr.h @@ -7,6 +7,9 @@ #include "cast.h" #include "pytypes.h" +#include +#include + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) diff --git a/include/pybind11/typing.h b/include/pybind11/typing.h index 4b027dbfea..ce4af488d5 100644 --- a/include/pybind11/typing.h +++ b/include/pybind11/typing.h @@ -11,10 +11,12 @@ #pragma once #include "detail/common.h" +#include "detail/descr.h" #include "cast.h" #include "pytypes.h" #include +#include #if defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911L # define PYBIND11_TYPING_H_HAS_STRING_LITERAL diff --git a/include/pybind11/warnings.h b/include/pybind11/warnings.h index 263b2990e3..db72d48e37 100644 --- a/include/pybind11/warnings.h +++ b/include/pybind11/warnings.h @@ -11,6 +11,10 @@ #include "pybind11.h" #include "detail/common.h" +#include "cast.h" +#include "pytypes.h" + +#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) diff --git a/tools/iwyu.imp b/tools/iwyu.imp new file mode 100644 index 0000000000..5d9b6d4d0e --- /dev/null +++ b/tools/iwyu.imp @@ -0,0 +1,111 @@ +# include-what-you-use mapping file for pybind11. +# +# CPython and both C++ standard libraries make IWYU ask for a header that +# pybind11 must not include directly: CPython symbols come from headers that +# only may include, libc++ (macOS) exposes private detail headers, +# and libstdc++ (Linux) exposes the C headers behind . +# +# Prefer a symbol entry. An include entry only takes effect when the left side +# is private, and declaring a real C header private makes IWYU abort with a +# "same file seen with two different visibilities" assertion. +[ + # CPython headers that includes, generated from the CPython 3.14 + # include directory (one entry per header named in Python.h itself; headers + # such as that Python.h does not include are kept direct). + { include: ["@[\"<]cpython/.*[\">]", private, "", public] }, + { include: ["@[\"<]internal/.*[\">]", private, "", public] }, + { include: ["@[\"<]abstract\\.h[\">]", private, "", public] }, + { include: ["@[\"<]audit\\.h[\">]", private, "", public] }, + { include: ["@[\"<]bltinmodule\\.h[\">]", private, "", public] }, + { include: ["@[\"<]boolobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]bytearrayobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]bytesobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]ceval\\.h[\">]", private, "", public] }, + { include: ["@[\"<]codecs\\.h[\">]", private, "", public] }, + { include: ["@[\"<]compile\\.h[\">]", private, "", public] }, + { include: ["@[\"<]complexobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]critical_section\\.h[\">]", private, "", public] }, + { include: ["@[\"<]descrobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]dictobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]enumobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]fileobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]fileutils\\.h[\">]", private, "", public] }, + { include: ["@[\"<]floatobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]genericaliasobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]import\\.h[\">]", private, "", public] }, + { include: ["@[\"<]intrcheck\\.h[\">]", private, "", public] }, + { include: ["@[\"<]iterobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]listobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]lock\\.h[\">]", private, "", public] }, + { include: ["@[\"<]longobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]memoryobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]methodobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]modsupport\\.h[\">]", private, "", public] }, + { include: ["@[\"<]moduleobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]monitoring\\.h[\">]", private, "", public] }, + { include: ["@[\"<]object\\.h[\">]", private, "", public] }, + { include: ["@[\"<]objimpl\\.h[\">]", private, "", public] }, + { include: ["@[\"<]osmodule\\.h[\">]", private, "", public] }, + { include: ["@[\"<]patchlevel\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pyatomic\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pybuffer\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pycapsule\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pyconfig\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pyerrors\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pyframe\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pyhash\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pylifecycle\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pymacconfig\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pymacro\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pymath\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pymem\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pyport\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pystate\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pystats\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pystrcmp\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pystrtod\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pythonrun\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pythread\\.h[\">]", private, "", public] }, + { include: ["@[\"<]pytypedefs\\.h[\">]", private, "", public] }, + { include: ["@[\"<]rangeobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]refcount\\.h[\">]", private, "", public] }, + { include: ["@[\"<]setobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]sliceobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]structseq\\.h[\">]", private, "", public] }, + { include: ["@[\"<]sysmodule\\.h[\">]", private, "", public] }, + { include: ["@[\"<]traceback\\.h[\">]", private, "", public] }, + { include: ["@[\"<]tupleobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]typeslots\\.h[\">]", private, "", public] }, + { include: ["@[\"<]unicodeobject\\.h[\">]", private, "", public] }, + { include: ["@[\"<]warnings\\.h[\">]", private, "", public] }, + { include: ["@[\"<]weakrefobject\\.h[\">]", private, "", public] }, + + # libstdc++ reports the C header for these C library symbols. + { symbol: ["abs", private, "", public] }, + { symbol: ["free", private, "", public] }, + { symbol: ["malloc", private, "", public] }, + { symbol: ["memcpy", private, "", public] }, + { symbol: ["memset", private, "", public] }, + { symbol: ["size_t", private, "", public] }, + { symbol: ["strcmp", private, "", public] }, + { symbol: ["strlen", private, "", public] }, + + # libc++ detail headers. These are private, so an include entry works and + # covers every symbol at once. + { include: ["<_ctype.h>", private, "", public] }, + { include: ["<_stdio.h>", private, "", public] }, + { include: ["<_stdlib.h>", private, "", public] }, + { include: ["<_string.h>", private, "", public] }, + { include: ["<_time.h>", private, "", public] }, + { include: ["<_wchar.h>", private, "", public] }, + { include: ["<__config>", private, "", public] }, + { include: ["<__config_site>", private, "", public] }, + { include: ["<__hash_table>", private, "", public] }, + { include: ["<__hash_table>", private, "", public] }, + { include: ["<__locale>", private, "", public] }, + + # Eigen detail headers; name the top-level module header instead. + { include: ["@[\"<]Eigen/src/SparseCore/.*[\">]", private, "", public] }, + { include: ["@[\"<]Eigen/src/.*[\">]", private, "", public] }, + { include: ["@[\"<]unsupported/Eigen/CXX11/src/.*[\">]", private, "", public] }, +] diff --git a/tools/iwyu.sh b/tools/iwyu.sh new file mode 100755 index 0000000000..f35c984caa --- /dev/null +++ b/tools/iwyu.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# include-what-you-use wrapper for the "iwyu" CMake preset. +# +# Builds the --check_also list from the headers on disk, so a new header is +# covered without an edit here. Two headers make IWYU 0.26 crash while it +# analyzes them, so they are skipped: +# include/pybind11/pybind11.h (assertion: "There should be a redecl +# specifying the default arg") +# include/pybind11/cast.h (segmentation fault) +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd) + +set -- -Xiwyu --no_fwd_decls "$@" +set -- -Xiwyu "--mapping_file=$root/tools/iwyu.imp" "$@" +for h in "$root"/include/pybind11/*.h "$root"/include/pybind11/*/*.h; do + case $h in + */pybind11/pybind11.h | */pybind11/cast.h) continue ;; + esac + set -- -Xiwyu "--check_also=$h" "$@" +done + +exec include-what-you-use "$@"