From 7a65437e23706e4820392dc456c3acccbf196dd6 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 17 Dec 2025 20:28:42 +0000 Subject: [PATCH 1/6] iwyu: Add patch to prefer angled brackets over quotes for includes --- .gitignore | 1 + ci/test/01_base_install.sh | 1 + ci/test/01_iwyu.patch | 14 ++++++++++++++ ci/test_imagefile | 2 +- 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 ci/test/01_iwyu.patch diff --git a/.gitignore b/.gitignore index 3b22e358dca..b92988f6a3d 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ # Only ignore unexpected patches *.patch +!ci/test/*.patch !contrib/guix/patches/*.patch !depends/patches/**/*.patch diff --git a/ci/test/01_base_install.sh b/ci/test/01_base_install.sh index a0f4164bbc5..f1accd713b5 100755 --- a/ci/test/01_base_install.sh +++ b/ci/test/01_base_install.sh @@ -81,6 +81,7 @@ fi if [[ "${RUN_TIDY}" == "true" ]]; then ${CI_RETRY_EXE} git clone --depth=1 https://github.com/include-what-you-use/include-what-you-use -b clang_"${TIDY_LLVM_V}" /include-what-you-use + (cd /include-what-you-use && patch -p1 < /ci_container_base/ci/test/01_iwyu.patch) cmake -B /iwyu-build/ -G 'Unix Makefiles' -DCMAKE_PREFIX_PATH=/usr/lib/llvm-"${TIDY_LLVM_V}" -S /include-what-you-use make -C /iwyu-build/ install "$MAKEJOBS" fi diff --git a/ci/test/01_iwyu.patch b/ci/test/01_iwyu.patch new file mode 100644 index 00000000000..f976349bf57 --- /dev/null +++ b/ci/test/01_iwyu.patch @@ -0,0 +1,14 @@ +Prefer angled brackets over quotes for include directives. +See: https://en.cppreference.com/w/cpp/preprocessor/include.html. + +--- a/iwyu_path_util.cc ++++ b/iwyu_path_util.cc +@@ -211,7 +211,7 @@ bool IsQuotedInclude(const string& s) { + } + + string AddQuotes(string include_name, bool angled) { +- if (angled) { ++ if (true) { + return "<" + include_name + ">"; + } + return "\"" + include_name + "\""; diff --git a/ci/test_imagefile b/ci/test_imagefile index a0e1714ed5f..c0a25d88d88 100644 --- a/ci/test_imagefile +++ b/ci/test_imagefile @@ -15,7 +15,7 @@ ARG BASE_ROOT_DIR ENV BASE_ROOT_DIR=${BASE_ROOT_DIR} COPY ./ci/retry/retry /usr/bin/retry -COPY ./ci/test/00_setup_env.sh ./${FILE_ENV} ./ci/test/01_base_install.sh /ci_container_base/ci/test/ +COPY ./ci/test/00_setup_env.sh ./${FILE_ENV} ./ci/test/01_base_install.sh ./ci/test/01_iwyu.patch /ci_container_base/ci/test/ # Bash is required, so install it when missing RUN sh -c "bash -c 'true' || ( apk update && apk add --no-cache bash )" From 73f7844cdb1e225099223a355d88da0522d7d69b Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 17 Dec 2025 20:28:55 +0000 Subject: [PATCH 2/6] iwyu: Add patch to prefer C++ headers over C counterparts --- ci/test/01_iwyu.patch | 584 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 584 insertions(+) diff --git a/ci/test/01_iwyu.patch b/ci/test/01_iwyu.patch index f976349bf57..e14316bfb3c 100644 --- a/ci/test/01_iwyu.patch +++ b/ci/test/01_iwyu.patch @@ -12,3 +12,587 @@ See: https://en.cppreference.com/w/cpp/preprocessor/include.html. return "<" + include_name + ">"; } return "\"" + include_name + "\""; + + +Prefer C++ headers over C counterparts. +See: https://github.com/include-what-you-use/include-what-you-use/blob/clang_21/iwyu_include_picker.cc#L587-L629. + +--- a/iwyu_include_picker.cc ++++ b/iwyu_include_picker.cc +@@ -100,20 +100,20 @@ const IncludeMapEntry libc_symbol_map[] = { + // equal. The visibility on the symbol-name is ignored; by convention + // we always set it to kPrivate. + { "_POSIX_VDISABLE", kPrivate, "", kPublic }, +- { "abort", kPrivate, "", kPublic }, ++ { "abort", kPrivate, "", kPrivate }, + { "aiocb", kPrivate, "", kPublic }, + { "blkcnt_t", kPrivate, "", kPublic }, + { "blksize_t", kPrivate, "", kPublic }, + { "cc_t", kPrivate, "", kPublic }, +- { "clock_t", kPrivate, "", kPublic }, ++ { "clock_t", kPrivate, "", kPrivate }, + { "clock_t", kPrivate, "", kPublic }, + { "clockid_t", kPrivate, "", kPublic }, +- { "ctermid", kPrivate, "", kPublic }, ++ { "ctermid", kPrivate, "", kPrivate }, + { "daddr_t", kPrivate, "", kPublic }, + { "dev_t", kPrivate, "", kPublic }, +- { "div_t", kPrivate, "", kPublic }, +- { "double_t", kPrivate, "", kPublic }, +- { "error_t", kPrivate, "", kPublic }, ++ { "div_t", kPrivate, "", kPrivate }, ++ { "double_t", kPrivate, "", kPrivate }, ++ { "error_t", kPrivate, "", kPrivate }, + { "error_t", kPrivate, "", kPublic }, + { "error_t", kPrivate, "", kPublic }, + { "FD_CLR", kPrivate, "", kPublic }, +@@ -122,10 +122,10 @@ const IncludeMapEntry libc_symbol_map[] = { + { "fd_set", kPrivate, "", kPublic }, + { "FD_SETSIZE", kPrivate, "", kPublic }, + { "FD_ZERO", kPrivate, "", kPublic }, +- { "fenv_t", kPrivate, "", kPublic }, +- { "fexcept_t", kPrivate, "", kPublic }, +- { "FILE", kPrivate, "", kPublic }, +- { "float_t", kPrivate, "", kPublic }, ++ { "fenv_t", kPrivate, "", kPrivate }, ++ { "fexcept_t", kPrivate, "", kPrivate }, ++ { "FILE", kPrivate, "", kPrivate }, ++ { "float_t", kPrivate, "", kPrivate }, + { "fsblkcnt_t", kPrivate, "", kPublic }, + { "fsfilcnt_t", kPrivate, "", kPublic }, + { "getopt", kPrivate, "", kPublic }, +@@ -135,31 +135,31 @@ const IncludeMapEntry libc_symbol_map[] = { + { "in_addr_t", kPrivate, "", kPublic }, + { "in_port_t", kPrivate, "", kPublic }, + { "id_t", kPrivate, "", kPublic }, +- { "imaxdiv_t", kPrivate, "", kPublic }, +- { "intmax_t", kPrivate, "", kPublic }, +- { "uintmax_t", kPrivate, "", kPublic }, ++ { "imaxdiv_t", kPrivate, "", kPrivate }, ++ { "intmax_t", kPrivate, "", kPrivate }, ++ { "uintmax_t", kPrivate, "", kPrivate }, + { "ino64_t", kPrivate, "", kPublic }, + { "ino_t", kPrivate, "", kPublic }, +- { "int8_t", kPrivate, "", kPublic }, +- { "int16_t", kPrivate, "", kPublic }, +- { "int32_t", kPrivate, "", kPublic }, +- { "int64_t", kPrivate, "", kPublic }, +- { "uint8_t", kPrivate, "", kPublic }, +- { "uint16_t", kPrivate, "", kPublic }, +- { "uint32_t", kPrivate, "", kPublic }, +- { "uint64_t", kPrivate, "", kPublic }, +- { "intptr_t", kPrivate, "", kPublic }, +- { "uintptr_t", kPrivate, "", kPublic }, ++ { "int8_t", kPrivate, "", kPrivate }, ++ { "int16_t", kPrivate, "", kPrivate }, ++ { "int32_t", kPrivate, "", kPrivate }, ++ { "int64_t", kPrivate, "", kPrivate }, ++ { "uint8_t", kPrivate, "", kPrivate }, ++ { "uint16_t", kPrivate, "", kPrivate }, ++ { "uint32_t", kPrivate, "", kPrivate }, ++ { "uint64_t", kPrivate, "", kPrivate }, ++ { "intptr_t", kPrivate, "", kPrivate }, ++ { "uintptr_t", kPrivate, "", kPrivate }, + { "iovec", kPrivate, "", kPublic }, +- { "itimerspec", kPrivate, "", kPublic }, ++ { "itimerspec", kPrivate, "", kPrivate }, + { "key_t", kPrivate, "", kPublic }, +- { "L_ctermid", kPrivate, "", kPublic }, +- { "lconv", kPrivate, "", kPublic }, +- { "ldiv_t", kPrivate, "", kPublic }, +- { "lldiv_t", kPrivate, "", kPublic }, +- { "locale_t", kPrivate, "", kPublic }, +- { "max_align_t", kPrivate, "", kPublic }, +- { "mbstate_t", kPrivate, "", kPublic }, ++ { "L_ctermid", kPrivate, "", kPrivate }, ++ { "lconv", kPrivate, "", kPrivate }, ++ { "ldiv_t", kPrivate, "", kPrivate }, ++ { "lldiv_t", kPrivate, "", kPrivate }, ++ { "locale_t", kPrivate, "", kPrivate }, ++ { "max_align_t", kPrivate, "", kPrivate }, ++ { "mbstate_t", kPrivate, "", kPrivate }, + { "mcontext_t", kPrivate, "", kPublic }, + { "mode_t", kPrivate, "", kPublic }, + { "nl_item", kPrivate, "", kPublic }, +@@ -175,8 +175,8 @@ const IncludeMapEntry libc_symbol_map[] = { + { "optind", kPrivate, "", kPublic }, + { "optopt", kPrivate, "", kPublic }, + { "pid_t", kPrivate, "", kPublic }, +- { "posix_memalign", kPrivate, "", kPublic }, +- { "printf", kPrivate, "", kPublic }, ++ { "posix_memalign", kPrivate, "", kPrivate }, ++ { "printf", kPrivate, "", kPrivate }, + { "pthread_attr_t", kPrivate, "", kPublic }, + { "pthread_cond_t", kPrivate, "", kPublic }, + { "pthread_condattr_t", kPrivate, "", kPublic }, +@@ -187,7 +187,7 @@ const IncludeMapEntry libc_symbol_map[] = { + { "pthread_rwlock_t", kPrivate, "", kPublic }, + { "pthread_rwlockattr_t", kPrivate, "", kPublic }, + { "pthread_t", kPrivate, "", kPublic }, +- { "ptrdiff_t", kPrivate, "", kPublic }, ++ { "ptrdiff_t", kPrivate, "", kPrivate }, + { "regex_t", kPrivate, "", kPublic }, + { "regmatch_t", kPrivate, "", kPublic }, + { "regoff_t", kPrivate, "", kPublic }, +@@ -218,51 +218,51 @@ const IncludeMapEntry libc_symbol_map[] = { + { "SCHED_FIFO", kPrivate, "", kPublic }, + { "SCHED_OTHER", kPrivate, "", kPublic }, + { "SCHED_RR", kPrivate, "", kPublic }, +- { "SEEK_CUR", kPrivate, "", kPublic }, +- { "SEEK_END", kPrivate, "", kPublic }, +- { "SEEK_SET", kPrivate, "", kPublic }, +- { "sig_atomic_t", kPrivate, "", kPublic }, +- { "sigevent", kPrivate, "", kPublic }, +- { "siginfo_t", kPrivate, "", kPublic }, +- { "sigset_t", kPrivate, "", kPublic }, +- { "sigval", kPrivate, "", kPublic }, ++ { "SEEK_CUR", kPrivate, "", kPrivate }, ++ { "SEEK_END", kPrivate, "", kPrivate }, ++ { "SEEK_SET", kPrivate, "", kPrivate }, ++ { "sig_atomic_t", kPrivate, "", kPrivate }, ++ { "sigevent", kPrivate, "", kPrivate }, ++ { "siginfo_t", kPrivate, "", kPrivate }, ++ { "sigset_t", kPrivate, "", kPrivate }, ++ { "sigval", kPrivate, "", kPrivate }, + { "sockaddr", kPrivate, "", kPublic }, + { "socklen_t", kPrivate, "", kPublic }, + { "ssize_t", kPrivate, "", kPublic }, +- { "stack_t", kPrivate, "", kPublic }, ++ { "stack_t", kPrivate, "", kPrivate }, + { "stat", kPrivate, "", kPublic }, + { "suseconds_t", kPrivate, "", kPublic }, +- { "time_t", kPrivate, "", kPublic }, ++ { "time_t", kPrivate, "", kPrivate }, + { "time_t", kPrivate, "", kPublic }, + { "timer_t", kPrivate, "", kPublic }, +- { "timespec", kPrivate, "", kPublic }, ++ { "timespec", kPrivate, "", kPrivate }, + { "timeval", kPrivate, "", kPublic }, +- { "tm", kPrivate, "", kPublic }, ++ { "tm", kPrivate, "", kPrivate }, + { "u_char", kPrivate, "", kPublic }, + { "ucontext_t", kPrivate, "", kPublic }, + { "uid_t", kPrivate, "", kPublic }, + { "useconds_t", kPrivate, "", kPublic }, +- { "wchar_t", kPrivate, "", kPublic }, +- { "wctrans_t", kPrivate, "", kPublic }, +- { "wctype_t", kPrivate, "", kPublic }, ++ { "wchar_t", kPrivate, "", kPrivate }, ++ { "wctrans_t", kPrivate, "", kPrivate }, ++ { "wctype_t", kPrivate, "", kPrivate }, + { "winsize", kPrivate, "", kPublic }, +- { "wint_t", kPrivate, "", kPublic }, ++ { "wint_t", kPrivate, "", kPrivate }, + // It is unspecified if the cname headers provide ::size_t. + // is the one header which defines NULL but not size_t. +- { "size_t", kPrivate, "", kPublic }, // 'canonical' location for size_t +- { "size_t", kPrivate, "", kPublic }, +- { "size_t", kPrivate, "", kPublic }, +- { "size_t", kPrivate, "", kPublic }, +- { "size_t", kPrivate, "", kPublic }, +- { "size_t", kPrivate, "", kPublic }, +- { "size_t", kPrivate, "", kPublic }, +- { "size_t", kPrivate, "", kPublic }, ++ { "size_t", kPrivate, "", kPrivate }, // 'canonical' location for size_t ++ { "size_t", kPrivate, "", kPrivate }, ++ { "size_t", kPrivate, "", kPrivate }, ++ { "size_t", kPrivate, "", kPrivate }, ++ { "size_t", kPrivate, "", kPrivate }, ++ { "size_t", kPrivate, "", kPrivate }, ++ { "size_t", kPrivate, "", kPrivate }, ++ { "size_t", kPrivate, "", kPrivate }, + // Macros that can be defined in more than one file, don't have the + // same __foo_defined guard that other types do, so the grep above + // doesn't discover them. Until I figure out a better way, I just + // add them in by hand as I discover them. +- { "EOF", kPrivate, "", kPublic }, +- { "FILE", kPrivate, "", kPublic }, ++ { "EOF", kPrivate, "", kPrivate }, ++ { "FILE", kPrivate, "", kPrivate }, + { "IBSHIFT", kPrivate, "", kPublic }, + { "MAP_POPULATE", kPrivate, "", kPublic }, + { "MAP_POPULATE", kPrivate, "", kPublic }, +@@ -270,22 +270,22 @@ const IncludeMapEntry libc_symbol_map[] = { + { "MAP_STACK", kPrivate, "", kPublic }, + { "MAXHOSTNAMELEN", kPrivate, "", kPublic }, + { "MAXHOSTNAMELEN", kPrivate, "", kPublic }, +- { "SIGABRT", kPrivate, "", kPublic }, +- { "SIGCHLD", kPrivate, "", kPublic }, +- { "va_arg", kPrivate, "", kPublic }, +- { "va_copy", kPrivate, "", kPublic }, +- { "va_end", kPrivate, "", kPublic }, +- { "va_list", kPrivate, "", kPublic }, +- { "va_start", kPrivate, "", kPublic }, +- { "WEOF", kPrivate, "", kPublic }, ++ { "SIGABRT", kPrivate, "", kPrivate }, ++ { "SIGCHLD", kPrivate, "", kPrivate }, ++ { "va_arg", kPrivate, "", kPrivate }, ++ { "va_copy", kPrivate, "", kPrivate }, ++ { "va_end", kPrivate, "", kPrivate }, ++ { "va_list", kPrivate, "", kPrivate }, ++ { "va_start", kPrivate, "", kPrivate }, ++ { "WEOF", kPrivate, "", kPrivate }, + // These are symbols that could be defined in either stdlib.h or + // malloc.h, but we always want the stdlib location. +- { "malloc", kPrivate, "", kPublic }, +- { "calloc", kPrivate, "", kPublic }, +- { "realloc", kPrivate, "", kPublic }, +- { "free", kPrivate, "", kPublic }, ++ { "malloc", kPrivate, "", kPrivate }, ++ { "calloc", kPrivate, "", kPrivate }, ++ { "realloc", kPrivate, "", kPrivate }, ++ { "free", kPrivate, "", kPrivate }, + // Entries for NULL +- { "NULL", kPrivate, "", kPublic }, // 'canonical' location for NULL ++ { "NULL", kPrivate, "", kPrivate }, // 'canonical' location for NULL + { "NULL", kPrivate, "", kPublic }, + { "NULL", kPrivate, "", kPublic }, + { "NULL", kPrivate, "", kPublic }, +@@ -293,13 +293,13 @@ const IncludeMapEntry libc_symbol_map[] = { + { "NULL", kPrivate, "", kPublic }, + { "NULL", kPrivate, "", kPublic }, + { "NULL", kPrivate, "", kPublic }, +- { "NULL", kPrivate, "", kPublic }, +- { "NULL", kPrivate, "", kPublic }, +- { "NULL", kPrivate, "", kPublic }, +- { "NULL", kPrivate, "", kPublic }, +- { "NULL", kPrivate, "", kPublic }, +- { "NULL", kPrivate, "", kPublic }, +- { "offsetof", kPrivate, "", kPublic }, ++ { "NULL", kPrivate, "", kPrivate }, ++ { "NULL", kPrivate, "", kPrivate }, ++ { "NULL", kPrivate, "", kPrivate }, ++ { "NULL", kPrivate, "", kPrivate }, ++ { "NULL", kPrivate, "", kPrivate }, ++ { "NULL", kPrivate, "", kPrivate }, ++ { "offsetof", kPrivate, "", kPrivate }, + }; + + // Common kludges for C++ standard libraries +@@ -355,7 +355,7 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -363,18 +363,18 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -382,24 +382,24 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPrivate }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -409,17 +409,17 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -429,22 +429,22 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPrivate }, +@@ -459,12 +459,12 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -474,11 +474,11 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + // Sometimes libc tells you what mapping to do via an '#error': + // # error "Never use directly; include instead." +@@ -488,7 +488,7 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -498,38 +498,38 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + // Top-level #includes that just forward to another file: +@@ -541,13 +541,13 @@ const IncludeMapEntry libc_include_map[] = { + // on the POSIX.1-2024 list, I just choose the top-level one. + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -567,21 +567,21 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPrivate }, + // I don't know what grep would have found these. I found them + // via user report. +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, // PATH_MAX ++ { "", kPrivate, "", kPrivate }, // PATH_MAX + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + // System headers available on AIX, BSD, Solaris and other Unix systems + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + // Exports guaranteed by the C standard +- { "", kPublic, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + }; + + const IncludeMapEntry stdlib_c_include_map[] = { +@@ -601,31 +601,31 @@ const IncludeMapEntry stdlib_c_include_map[] = { + // + // $ curl -s -N https://raw.githubusercontent.com/cplusplus/draft/c%2B%2B20/source/lib-intro.tex | sed -n '/begin{multicolfloattable}.*{headers.cpp.c}/,/end{multicolfloattable}/p' | grep tcode | perl -nle 'm/tcode{}/ && print qq@ { "<$1.h>", kPublic, "", kPublic },@' | sort + { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, + }; + + const char* stdlib_cpp_public_headers[] = { From 0f81e005197fa4201a38e635ddf8c5dcc12a3878 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 17 Dec 2025 20:29:03 +0000 Subject: [PATCH 3/6] cmake: Make `codegen` target dependent on `generate_build_info` --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 47aee937a57..43d67f40201 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,7 +43,7 @@ add_custom_target(generate_build_info COMMENT "Generating bitcoin-build-info.h" VERBATIM ) -add_library(bitcoin_clientversion STATIC EXCLUDE_FROM_ALL +add_library(bitcoin_clientversion STATIC clientversion.cpp ) target_link_libraries(bitcoin_clientversion From 94e4f04d7cf4b0fef9a28d3771e73f1dc9fb0528 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 17 Dec 2025 20:29:16 +0000 Subject: [PATCH 4/6] cmake: Fix target name The executable target run by ctest is `mptest`. This change removes unnecessary steps when building the `codegen` target. --- cmake/libmultiprocess.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/libmultiprocess.cmake b/cmake/libmultiprocess.cmake index 5db8f4e9e54..32da8f8c5a0 100644 --- a/cmake/libmultiprocess.cmake +++ b/cmake/libmultiprocess.cmake @@ -27,7 +27,7 @@ function(add_libmultiprocess subdir) mark_as_advanced(CapnProto_kj-tls_IMPORTED_LOCATION) if(BUILD_TESTS) # Add tests to "all" target so ctest can run them - set_target_properties(mptests PROPERTIES EXCLUDE_FROM_ALL OFF) + set_target_properties(mptest PROPERTIES EXCLUDE_FROM_ALL OFF) endif() # Exclude examples from compilation database, because the examples are not # built by default, and they contain generated c++ code. Without this From 2c78814e0e182853ce44d9fd63d24ee6cab5223e Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 17 Dec 2025 20:29:25 +0000 Subject: [PATCH 5/6] ci: Add IWYU job The change in `src/crypto/hex_base.cpp` is because GCC 14 is not affected by an IWYU bug. See: https://github.com/include-what-you-use/include-what-you-use/issues/1763. --- .github/workflows/ci.yml | 6 ++++++ ci/test/00_setup_env_native_iwyu.sh | 25 +++++++++++++++++++++++++ ci/test/01_base_install.sh | 2 +- ci/test/03_test_script.sh | 18 ++++++++++++------ contrib/devtools/iwyu/bitcoin.core.imp | 4 ++++ src/crypto/hex_base.cpp | 1 - 6 files changed, 48 insertions(+), 8 deletions(-) create mode 100755 ci/test/00_setup_env_native_iwyu.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f5dc7721003..d1476f5a889 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -522,6 +522,12 @@ jobs: fail-fast: false matrix: include: + - name: 'iwyu' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md' + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_native_iwyu.sh' + - name: '32 bit ARM' cirrus-runner: 'ubuntu-24.04-arm' # Cirrus' Arm runners are Apple (with virtual Linux aarch64), which doesn't support 32-bit mode fallback-runner: 'ubuntu-24.04-arm' diff --git a/ci/test/00_setup_env_native_iwyu.sh b/ci/test/00_setup_env_native_iwyu.sh new file mode 100755 index 00000000000..dbb45ed7dae --- /dev/null +++ b/ci/test/00_setup_env_native_iwyu.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +export LC_ALL=C.UTF-8 + +export CI_IMAGE_NAME_TAG="mirror.gcr.io/debian:trixie" # To build codegen, CMake must be 3.31 or newer. +export CONTAINER_NAME=ci_native_iwyu +export TIDY_LLVM_V="21" +export APT_LLVM_V="${TIDY_LLVM_V}" +export PACKAGES="clang-${TIDY_LLVM_V} libclang-${TIDY_LLVM_V}-dev llvm-${TIDY_LLVM_V}-dev jq libevent-dev libboost-dev libzmq3-dev systemtap-sdt-dev qt6-base-dev qt6-tools-dev qt6-l10n-tools libqrencode-dev libsqlite3-dev libcapnp-dev capnproto" +export NO_DEPENDS=1 +export RUN_UNIT_TESTS=false +export RUN_FUNCTIONAL_TESTS=false +export RUN_FUZZ_TESTS=false +export RUN_CHECK_DEPS=false +export RUN_IWYU=true +export GOAL="codegen" +export BITCOIN_CONFIG="\ + --preset dev-mode -DBUILD_GUI=OFF \ + -DCMAKE_C_COMPILER=clang-${TIDY_LLVM_V} \ + -DCMAKE_CXX_COMPILER=clang++-${TIDY_LLVM_V} \ +" diff --git a/ci/test/01_base_install.sh b/ci/test/01_base_install.sh index f1accd713b5..0ac56208f9b 100755 --- a/ci/test/01_base_install.sh +++ b/ci/test/01_base_install.sh @@ -79,7 +79,7 @@ if [[ -n "${USE_INSTRUMENTED_LIBCPP}" ]]; then rm -rf /llvm-project fi -if [[ "${RUN_TIDY}" == "true" ]]; then +if [[ "${RUN_IWYU}" == true ]]; then ${CI_RETRY_EXE} git clone --depth=1 https://github.com/include-what-you-use/include-what-you-use -b clang_"${TIDY_LLVM_V}" /include-what-you-use (cd /include-what-you-use && patch -p1 < /ci_container_base/ci/test/01_iwyu.patch) cmake -B /iwyu-build/ -G 'Unix Makefiles' -DCMAKE_PREFIX_PATH=/usr/lib/llvm-"${TIDY_LLVM_V}" -S /include-what-you-use diff --git a/ci/test/03_test_script.sh b/ci/test/03_test_script.sh index e61dc33edc9..32739a139f8 100755 --- a/ci/test/03_test_script.sh +++ b/ci/test/03_test_script.sh @@ -41,10 +41,10 @@ echo "=== BEGIN env ===" env echo "=== END env ===" -# Don't apply patches in the tidy job, because it relies on the `git diff` -# command to detect IWYU errors. It is safe to skip this patch in the tidy job +# Don't apply patches in the iwyu job, because it relies on the `git diff` +# command to detect IWYU errors. It is safe to skip this patch in the iwyu job # because it doesn't run a UB detector. -if [ "$RUN_TIDY" != "true" ]; then +if [[ "${RUN_IWYU}" != true ]]; then # compact->outputs[i].file_size is uninitialized memory, so reading it is UB. # The statistic bytes_written is only used for logging, which is disabled in # CI, so as a temporary minimal fix to work around UB and CI failures, leave @@ -120,7 +120,7 @@ BASE_BUILD_DIR=${BASE_BUILD_DIR:-$BASE_SCRATCH_DIR/build-$HOST} BITCOIN_CONFIG_ALL="$BITCOIN_CONFIG_ALL -DCMAKE_INSTALL_PREFIX=$BASE_OUTDIR -Werror=dev" -if [[ "${RUN_TIDY}" == "true" ]]; then +if [[ "${RUN_IWYU}" == true || "${RUN_TIDY}" == true ]]; then BITCOIN_CONFIG_ALL="$BITCOIN_CONFIG_ALL -DCMAKE_EXPORT_COMPILE_COMMANDS=ON" fi @@ -132,11 +132,15 @@ cmake -S "$BASE_ROOT_DIR" -B "$BASE_BUILD_DIR" "${CMAKE_ARGS[@]}" || ( false ) +if [[ "${GOAL}" != all && "${GOAL}" != codegen ]]; then + GOAL="all ${GOAL}" +fi + # shellcheck disable=SC2086 -cmake --build "${BASE_BUILD_DIR}" "$MAKEJOBS" --target all $GOAL || ( +cmake --build "${BASE_BUILD_DIR}" "$MAKEJOBS" --target $GOAL || ( echo "Build failure. Verbose build follows." # shellcheck disable=SC2086 - cmake --build "${BASE_BUILD_DIR}" -j1 --target all $GOAL --verbose + cmake --build "${BASE_BUILD_DIR}" -j1 --target $GOAL --verbose false ) @@ -204,7 +208,9 @@ if [ "${RUN_TIDY}" = "true" ]; then echo "^^^ ⚠️ Failure generated from clang-tidy" false fi +fi +if [[ "${RUN_IWYU}" == true ]]; then # TODO: Consider enforcing IWYU across the entire codebase. FILES_WITH_ENFORCED_IWYU="/src/(crypto|index)/.*\\.cpp" jq --arg patterns "$FILES_WITH_ENFORCED_IWYU" 'map(select(.file | test($patterns)))' "${BASE_BUILD_DIR}/compile_commands.json" > "${BASE_BUILD_DIR}/compile_commands_iwyu_errors.json" diff --git a/contrib/devtools/iwyu/bitcoin.core.imp b/contrib/devtools/iwyu/bitcoin.core.imp index c3195e519d4..9067bc327d0 100644 --- a/contrib/devtools/iwyu/bitcoin.core.imp +++ b/contrib/devtools/iwyu/bitcoin.core.imp @@ -13,4 +13,8 @@ { "symbol": ["SEEK_CUR", "private", "", "public"] }, { "symbol": ["SEEK_END", "private", "", "public"] }, { "symbol": ["SEEK_SET", "private", "", "public"] }, + + # IWYU bug. + # See: https://github.com/include-what-you-use/include-what-you-use/issues/1863. + { "symbol": ["std::vector", "private", "", "public"] }, ] diff --git a/src/crypto/hex_base.cpp b/src/crypto/hex_base.cpp index 7098aba7b8a..f8b1ca2f07d 100644 --- a/src/crypto/hex_base.cpp +++ b/src/crypto/hex_base.cpp @@ -8,7 +8,6 @@ #include #include #include -#include namespace { From 56750c4f87d089c6a3f093eb2bf2edd07170d4a8 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 17 Dec 2025 20:29:36 +0000 Subject: [PATCH 6/6] iwyu, clang-format: Sort includes --- ci/test/00_setup_env_native_iwyu.sh | 2 +- ci/test/03_test_script.sh | 1 + src/.clang-format | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ci/test/00_setup_env_native_iwyu.sh b/ci/test/00_setup_env_native_iwyu.sh index dbb45ed7dae..3868510d43a 100755 --- a/ci/test/00_setup_env_native_iwyu.sh +++ b/ci/test/00_setup_env_native_iwyu.sh @@ -10,7 +10,7 @@ export CI_IMAGE_NAME_TAG="mirror.gcr.io/debian:trixie" # To build codegen, CMak export CONTAINER_NAME=ci_native_iwyu export TIDY_LLVM_V="21" export APT_LLVM_V="${TIDY_LLVM_V}" -export PACKAGES="clang-${TIDY_LLVM_V} libclang-${TIDY_LLVM_V}-dev llvm-${TIDY_LLVM_V}-dev jq libevent-dev libboost-dev libzmq3-dev systemtap-sdt-dev qt6-base-dev qt6-tools-dev qt6-l10n-tools libqrencode-dev libsqlite3-dev libcapnp-dev capnproto" +export PACKAGES="clang-${TIDY_LLVM_V} clang-format-${TIDY_LLVM_V} libclang-${TIDY_LLVM_V}-dev llvm-${TIDY_LLVM_V}-dev jq libevent-dev libboost-dev libzmq3-dev systemtap-sdt-dev qt6-base-dev qt6-tools-dev qt6-l10n-tools libqrencode-dev libsqlite3-dev libcapnp-dev capnproto" export NO_DEPENDS=1 export RUN_UNIT_TESTS=false export RUN_FUNCTIONAL_TESTS=false diff --git a/ci/test/03_test_script.sh b/ci/test/03_test_script.sh index 32739a139f8..9bfa2bb10f4 100755 --- a/ci/test/03_test_script.sh +++ b/ci/test/03_test_script.sh @@ -226,6 +226,7 @@ if [[ "${RUN_IWYU}" == true ]]; then -Xiwyu --max_line_length=160 \ 2>&1 | tee /tmp/iwyu_ci.out python3 "/include-what-you-use/fix_includes.py" --nosafe_headers < /tmp/iwyu_ci.out + git diff -U0 | ./contrib/devtools/clang-format-diff.py -binary="clang-format-${TIDY_LLVM_V}" -p1 -i -v } run_iwyu "compile_commands_iwyu_errors.json" diff --git a/src/.clang-format b/src/.clang-format index c5fcd0b48cf..4db09138556 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -97,7 +97,7 @@ ForEachMacros: - BOOST_FOREACH IfMacros: - KJ_IF_MAYBE -IncludeBlocks: Preserve +IncludeBlocks: Regroup IncludeCategories: - Regex: '^' Priority: -1