[clang-tidy] misc-include-cleaner reports <variant> unused for std::get when the variant type comes from an alias in another header
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
`misc-include-cleaner` reports `` as unused in a file that calls `std::get` on a
`std::variant`, when the variant type reaches the file through an alias declared in another
header. `std::get`'s variant overloads are declared in ``, so the file does use a
declaration from it.
Unlike a plain unused-include false positive this one does not break the build: the alias
header pulls `` in transitively, so removing it still compiles. That is precisely
the transitive-dependency case the check exists to flag, so the suggestion quietly moves the
file in the wrong direction.
The missing-includes half does not ask for a `std::get` provider either, even with both
`` and `` removed, which suggests the call is not attributed to any header
rather than being attributed to the wrong one.
### Version
```
$ clang-tidy --version
LLVM (http://llvm.org/):
LLVM version 22.1.8
Optimized build.
```
Installed from PyPI (`clang-tidy==22.1.8`). Reproduced on macOS with libc++.
### Reproducer
`cfg.h`:
```c++
#pragma once
#include
#include
#include
namespace cfg {
using ConfigValue = std::variant;
using ConfigMap = std::map;
}
```
`g6.cc`:
```c++
#include
#include "cfg.h"
double f(const cfg::ConfigMap &m) {
return std::get(m.at("k"));
}
```
`.clang-tidy`:
```yaml
Checks: '-*,misc-include-cleaner'
CheckOptions:
- key: misc-include-cleaner.MissingIncludes
value: 'false'
```
A compilation database is required; `--` on the command line is not sufficient.
```
$ clang-tidy -p . --quiet g6.cc
g6.cc:1:1: warning: included header variant is not used directly [misc-include-cleaner]
```
### Expected
No diagnostic. `std::get(std::variant<...>&)` is declared in ``.
### Notes on the trigger
The alias-in-another-header part matters. If the variant type is spelled in the same file,
the check is correct and reports nothing:
```c++
#include
using V = std::variant;
double f(const V &v) { return std::get(v); } // no diagnostic, correct
```
Only when `std::variant` itself is never named in the file — the type arriving as
`cfg::ConfigValue` — does `` get reported, even though `std::get` is named directly
and its relevant overloads live there.
### Possibly related
#94459 was a symbol-to-header mapping problem in the same family: `` was reported
unused for `std::ranges::upper_bound` while an internal header was suggested instead.
Contributor guide
Research direction
Start by reproducing the diagnostic with cfg.h, g6.cc, the .clang-tidy configuration, and a compilation database using clang-tidy -p . --quiet g6.cc. Trace misc-include-cleaner’s attribution of std::get when the std::variant type arrives through cfg::ConfigValue, comparing it with the direct-alias example. Done means the reproducer emits no unused diagnostic while the check still handles genuine transitive dependencies.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100