This PR continues the ongoing effort to enforce IWYU warnings.
See Developer Notes.
src/util and treat them as errors
#34448
This PR continues the ongoing effort to enforce IWYU warnings.
See Developer Notes.
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
See the guideline for information on the review process. A summary of reviews will appear here.
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
0In file included from /home/admin/actions-runner/_work/_temp/src/hash.h:16:
1/home/admin/actions-runner/_work/_temp/src/uint256.h:150:17: error: no member named 'HexDigit' in the global namespace
2 150 | *p1 = ::HexDigit(str[--digits]);
3 | ^~~~~~~~
4/home/admin/actions-runner/_work/_temp/src/uint256.h:152:38: error: no member named 'HexDigit' in the global namespace
5 152 | *p1 |= ((unsigned char)::HexDigit(str[--digits]) << 4);
6 | ^~~~~~~~
72 errors generated.
🚧 At least one of the CI tasks failed.
Task Valgrind, fuzz: https://github.com/bitcoin/bitcoin/actions/runs/21484505843/job/61889746047
LLM reason (✨ experimental): Compilation failed due to missing #include causing std::vector to be undefined in string.h and related code.
Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:
Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.
A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.
An intermittent issue.
Leave a comment here, if you need help tracking down a confusing failure.
7@@ -8,13 +8,16 @@
8 # libc symbols.
9 { "symbol": ["AT_HWCAP", "private", "<sys/auxv.h>", "public"] },
10 { "symbol": ["AT_HWCAP2", "private", "<sys/auxv.h>", "public"] },
11+ { "symbol": ["sched_param", "private", "<sched.h>", "public"] },
sched_param mentioned in https://github.com/include-what-you-use/include-what-you-use/issues/1809. Are you opening separate issues for different symbols, or just adding new missing symbols to https://github.com/include-what-you-use/include-what-you-use/issues/1809? Any reason to not add the missing mappings upstream; otherwise it seems like we are just accumulating workarounds for things that are not being fixed.
I don’t see
sched_parammentioned in include-what-you-use/include-what-you-use#1809.
An upstream fix has been proposed in https://github.com/include-what-you-use/include-what-you-use/pull/1918.
Any reason to not add the missing mappings upstream; otherwise it seems like we are just accumulating workarounds for things that are not being fixed.
Fixed upstream in https://github.com/include-what-you-use/include-what-you-use/pull/1923.
7@@ -8,13 +8,16 @@
8 # libc symbols.
9 { "symbol": ["AT_HWCAP", "private", "<sys/auxv.h>", "public"] },
10 { "symbol": ["AT_HWCAP2", "private", "<sys/auxv.h>", "public"] },
11+ { "symbol": ["sched_param", "private", "<sched.h>", "public"] },
12
13 # Fixed in https://github.com/include-what-you-use/include-what-you-use/pull/1706.
Fixed in https://github.com/include-what-you-use/include-what-you-use/pull/1706.
This was fixed in IWYU 0.25, which we are using, so this whole block should be able to be dropped?
8 #include <util/syserror.h>
9
10+#include <string>
11+
12 #if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
13-#include <pthread.h>
5@@ -6,8 +6,11 @@
6 #ifndef BITCOIN_UTIL_TIME_H
7 #define BITCOIN_UTIL_TIME_H
8
9+#include <compat/compat.h>
compat.h being added here (with sys/time.h being added to it), rather than just including sys/time.h here? It seems like compat.h is starting to become a catch-all for includes, which is going in the opposite of the direction we want (and defeats the point of IWYU).
Why is
compat.hbeing added here (withsys/time.hbeing added to it), rather than just includingsys/time.hhere?
Without #include <compat/compat.h>, the code has to be:
0#ifdef WIN32
1#include <winsock2.h>
2#else
3#include <sys/time.h>
4#endif
This was actually my first iteration while working on this PR.
It seems like
compat.his starting to become a catch-all for includes, which is going in the opposite of the direction we want (and defeats the point of IWYU).
I agree. It would be great to have clearly documented use cases for compat.h.
Without #include <compat/compat.h>, the code has to be:
What is wrong with that code?
winsock2.h change seems unrelated, given IWYU is not run for Windows.
Also, the
winsock2.hchange seems unrelated, given IWYU is not run for Windows.
We still cross-compile for it and support native Windows builds. The winsock2.h header defines the timeval structure used here: https://github.com/bitcoin/bitcoin/blob/9f8764c814ead48d45b3822dfcc4cc2b3bda80d6/src/util/time.h#L151-L159
The code currently compiles without it only because of transitive includes, which is going in the opposite of the direction we want.
Without #include <compat/compat.h>, the code has to be:
What is wrong with that code?
I think it is missing the IWYU export. Generally, those should be avoided, but when it comes to compat headers, I think there is a benefit to just have them imported once to get one symbol cross-platform and then IWYU export them.
Otherwise, all call-sites will have to add:
0#ifdef WIN32
1#include <winsock2.h>
2#else
3#include <sys/time.h>
4#endif
,which is verbose, and hard to review, and easy to get wrong: As you say iwyu is not run on Windows and the transitive include can hide a missing winsock2 include.
So I think the options are either:
Otherwise, all call-sites will have to add:
Isn’t this the only callsite though? I don’t really see why we’d add #include <sys/time.h> to compat.h, just to have it included hundreds of places it isn’t needed, for the sake of saving 1 #ifdef.
I think before we make any more changes, we need to decide if we are actually doing IWYU, or only when it’s convenient/not inconvenient for Windows, and otherwise bundling things in 1 header to include everywhere else.
Isn’t this the only callsite though?
0$ git grep -l timeval -- src ":(exclude)src/leveldb" ":(exclude)src/secp256k1"
1src/crypto/ctaes/bench.c
2src/httpserver.cpp
3src/httpserver.h
4src/randomenv.cpp
5src/torcontrol.cpp
6src/util/sock.cpp
7src/util/time.cpp
8src/util/time.h
compat.h already includes sys/select.h, which also defines timeval. So why does sys/time.h need to be added to compat.h?
Alternatively, we can introduce a new compat_time.h header, which exports both winsock2.h and sys/time.h, and specify a new mapping in iwyu/bitcoin.core.imp:
0{ "symbol": ["timeval", "private", "<compat_time.h>", "public"] },
Isn’t this the only callsite though?
0$ git grep -l timeval -- src ":(exclude)src/leveldb" ":(exclude)src/secp256k1" 1src/crypto/ctaes/bench.c 2src/httpserver.cpp 3src/httpserver.h 4src/randomenv.cpp 5src/torcontrol.cpp 6src/util/sock.cpp 7src/util/time.cpp 8src/util/time.h
Right, my understanding is that all those would have to add the same
0#ifdef WIN32
1#include <winsock2.h>
2#else
3#include <sys/time.h>
4#endif
Alternatively, we can introduce a new
compat_time.hheader, which exports bothwinsock2.handsys/time.h, and specify a new mapping iniwyu/bitcoin.core.imp:0{ "symbol": ["timeval", "private", "<compat_time.h>", "public"] },
Yeah, that is a bit cleaner than the “iwyu export” hack. Maybe it can be named ./src/compat/time.h though?
compat.h?
compat.h, into many more of these mini-compat headers, and have many new includes (which themselves are some #ifdef logic + includes) in every file that previously only included compat.h? I do wonder if that will make it more or less likely to run into issues like #34454, or if that is really worth it to save some (hopefully comparatively ) small amount of code duplication/preprocessor time.
I’d say it would just be two:
But no strong opinion. Leaving this pull as-is is also fine.
compat.h, because timeval is already defined by sys/select.h.
along with reporting upstream
https://github.com/include-what-you-use/include-what-you-use/pull/1927.
Not sure how heavy the full compat net stack headers are to parse every time util/time.h is included. It may be faster to just include what is needed via compat/time.h instead of compat/compat.h, but I haven’t benchmarked this.
A third alternative could be to just move MillisToTimeval into compat.h
compat.h (or any other facade header) does not guarantee adherence to the ‘include what you use’ paradigm, as the timeval symbol can be defined in any of four different headers. Therefore, the decision of which header to include should be based on the headers already present in the given file.