Clangd errors in header files

Hey all,

I’m a novice at C and very new to C tooling, so bear with me if this is a dumb issue.

I use neovim + coc with clangd as my lsp to work in C. Right now I’m trying to use this setup to work in suckless org projects like dwm which consist of large .c files, configuration header files which are included well into the file, and a Makefile to build everything.

I can get LSP features to work just fine in the .c files by running a tool called “bear” to generate compiler_commands.json so that clangd knows about the libraries referenced in those files. But these configuration header files reference types that are defined before the header files are included. As a result, when I open the header files, clangd gives a bunch of unknown_typename errors.

Is there any way I can get rid of the unknown_typename errors when viewing these header files but benefit from LSP features? I don’t believe those header files are complete translation units so I don’t think I can make a compiler_commands entry for them, but I was hoping someone could give me some advice (and maybe a sanity check on whether this makes sense to do). Thanks in advance.

IIUC, there’s no effortless way to achieve what you want today. Clangd cannot work on non-self-contained files yet, details in

OTOH, If the header you are looking for is always called “config.h” you can do a postprocessing of your compile_commands.json and add --include="config.h" to all the entries or if you are using clangd-11, you can just have a .clangd file in your project root and add:

If:                               # Apply this config conditionally
  PathMatch: .*\.h                # to all headers...
CompileFlags:                     # Tweak the parse settings
  Add: [--include="config.h"]

more details in

Thank you for the reply!

In this case, the header I am opening up in each project is always called “config.h”. My distribution currently provides clangd 10.0.1, so it sounds like post-processing compile_commands.json would be the way to go.

Just to make sure I understand, is your suggestion to add “–include config.h” to the generated entries of compile_commands.json intended to fix “unknown_typename errors” when viewing config.h? I tried adding that to each of the entries for the .c files in the project. but it didn’t seem to fix the errors I see when viewing config.h.

For clarity, I can currently work with .c files with no issue, including referring to anything declared within the included config.h. It’s the opposite that doesn’t work- viewing types which are declared in .c files when viewing config.h – which gives me an issue.

In case I’m doing a poor job of explaining anything, I’m working off this repo and I checked in compile_commands.json. I’m trying to work with file “config.h” in that project, which is included in dwm.c on line 285 and refers to types defined in dwm.c above its inclusion.

Thanks again for taking the time to help!!

Sorry, looks like i’ve misunderstood your problem. I thought you were trying to include config.h in every file. Unfortunately no, there’s no way for clangd to figure out what should be inserted before parsing config.h.

As a workaround, you can try copying over all the lines in dwm.c before #include "config.h" directive, and pasting them at top of config.h. also include guard that section with something like #ifndef COMING_FROM_DWM_C, then add #define COMING_FROM_DWM_C before the #include "config.h" in dwm.c. Of course you would need to revert those changes before pushing anything, but at least that should provide you with a way to work on both config.h and dwm.c.

I’ve had the same issue (but with Makefile projects using neovim + nvim-lsp), and found a tool that appends compilation commands for header files to the compile_commands.json file. It’s called compdb, here:

Works well, and to make it more convenient I append a little makefile script to do it all in one step:

If you’re reading this 2022: After clangd-12, you don’t need to use compdb(, which is definitely a bad idea, since it’s not maintained). Instead take a look at the section of the CompilationDatabase from the clangd docs.