I have another minimal reproducer for this:
**a.cpp**:
```c++
#include <vector>
#include "b.h"
int main() {
std::vector<int> vec;
vec.push_back(42);
return 0;
}
```
**b.h**:
```c++
#pragma once
#include <algorithm>
```
command line:
```
$ include-what-you-use -std=c++17 a.cpp
a.cpp should add these lines:
#include <algorithm> // for max
a.cpp should remove these lines:
- #include "b.h" // lines 2-2
The full include-list for a.cpp:
#include <algorithm> // for max
#include <vector> // for vector
---
```
The false positive shows up if `std::vector::push_back()` or `std::vector::emplace_back()` is used, and `<algorithm>` is included via another header, and only with `-std=c++17`. Here, the order of including `"b.h"` and `<vector>` does not matter.
In addition, this causes other weird behaviour down the line, with a slightly expanded version of the previous example:
**a.cpp**:
```c++
#define CCCC 1
#include <vector>
#include "b.h"
#include "c.h"
int main() {
std::vector<int> vec;
vec.push_back(42);
return 0;
}
```
**b.h**:
```c++
#pragma once
#include <algorithm>
```
**c.h**:
```c++
#pragma once
struct C {};
static void ccc() {
#ifdef CCCC
C c;
#endif
}
```
command line:
```
$ include-what-you-use -std=c++17 a.cpp
a.cpp should add these lines:
#include <algorithm> // for max
a.cpp should remove these lines:
- #include "b.h" // lines 4-4
The full include-list for a.cpp:
#include <algorithm> // for max
#include <vector> // for vector
#include "c.h" // lines 5-5
---
```
Note that `c.h` is not deemed unnecessary, despite nothing from it being used in `a.cpp`. If you remove `#include "b.h"` then `c.h` is correctly marked as unnecessary.
I think that last example is by design -- it's a common pattern with x-macros to generate code using the C preprocessor:
```
// x.def
struct X_NAME {
X_NAME(X_TYPE v)
: name(#X_NAME),
value(v) {
}
std::string name;
X_TYPE value;
};
// mytypes.h
#define X_NAME IntType
#define X_TYPE int
#include "x.def"
#define X_NAME FloatType
#define X_TYPE float
#include "x.def"
...
```
IWYU actually has a rule to detect that if an included header depends on a symbol defined in the includer, we keep that header.
But let's discuss that separately if necessary, so we don't confuse these two issues.