Header Context
The Problem
The compilation database (compile_commands.json) only contains entries for source files, not header files. Since headers are included into source files, their meaning can change depending on the including context.
Context-Dependent Headers
// a.h
#ifdef TEST
struct X { ... };
#else
struct Y { ... };
#endif
// b.cpp
#define TEST
#include "a.h"
// c.cpp
#include "a.h"a.h has different states in b.cpp (defines X) and c.cpp (defines Y). A language server that treats a.h as an independent source file can only show one state.
Non-Self-Contained Headers
// a.h
struct Y {
X x;
};
// b.cpp
struct X {};
#include "a.h"a.h cannot be compiled standalone, but compiles correctly when included from b.cpp. clangd reports errors in such headers because it compiles them independently. This pattern appears frequently in libstdc++ and popular header-only libraries.
clice's Solution
clice implements header context switching — when you navigate to a header file, it uses the source file you came from as the compilation context.
How It Works
Context resolution (
Compiler::resolve_header_context): When a header is opened, clice finds host source files that include it (viaDependencyGraph::find_host_sources). It builds a chain of includes from the host source to the target header.Preamble injection: All source content preceding the
#includethat pulls in the target header is written to a temporary preamble file. The header is then compiled with-include <preamble>injected into its flags. This gives the header the exact preprocessor state it would have when included from that source file.Context selection: When a header is opened, clice picks a host source from its include graph. If no explicit context has been set via
clice/switchContext, it falls back to the first host source with a compilation database entry (not necessarily the one you navigated from).Manual switching: Users can explicitly switch context via the
clice/switchContextcommand, which presents a list of available host sources for the current header.
Context Invalidation
When the host source's preamble changes (include order modified, macros added), the header context is invalidated. A content hash of the preamble determines staleness — if the hash changes, the context is rebuilt on next query.