“Unused include” warning

#includeing headers that are not used can confuse readers, slow down build times, and make code harder to refactor. clangd can warn about this:

Unused include warning in VSCode

Often, these #include directive has no effect and can simply be removed. This isn’t always the case: the analysis makes assumptions about code style.

Which headers are used?

clangd follows the include-what-you-use model: each source file should #include headers that declare the symbols it references, and no others.

This means:

This is opinionated, and stricter than “will it compile”. It implies adding #includes that the compiler does not strictly need. Some #includes that satisfy the compiler should be replaced with more specific ones.

There can be exceptions to these rules. Nevertheless, if your codebase does not broadly aim to follow this style, you should disable this feature.

Scenarios and solutions

A header X is marked unused, but itself #includes Y which I use

This is a transitive include. Generally you should avoid this, but there are times when it’s needed, especially with external libraries.

A header is marked unusued, but is needed by other headers I later include

The later headers are not self-contained; our idea of dependencies breaks down.

I’m editing header X and #include "Y.h" is marked unused. This header should provide all of Y’s symbols

You are exporting a header: this makes dependencies less clear and coarser-grained, but is sometimes useful.

I’m using a symbol in a tricky way (e.g. through a template), but the header is marked as unused

There are some types of uses the analysis cannot find.

A header is marked unused, but removing it breaks my build!

clangd’s definition of “unused” isn’t the same as the compiler’s (see above section). You may have to add missing includes too, or do other cleanups.

Adjusting behavior

Configuration

In your configuration file, set Diagnostics.UnusedIncludes to Strict or None. You can also disable analysis of particular files (using If blocks), and suppress all warnings of certain headers.

If:
  PathMatch: .*/project1/.*\.cpp
Diagnostics:
  UnusedIncludes: Strict
  Includes:
    IgnoreHeader: Python\.h

IWYU pragmas

These are magic comments compatible with the include-what-you-use tool. clangd supports only a subset.

✏️