Thanks for trying things out, and sorry for the bad header-file experience.
Hello list,
thank you for all the work on clangd. I tried it for the first time
with VSCode and I’m really impressed how useful it is just out of the
box.
I however encountered a problem with code completion in header files
and I would like to know if it’s a bug in clangd or a problem in my
setup.
Yeah, this is a known missing feature - guessing the right compile flags for headers.
If you have a compilation database (e.g. compile_commands.json) that provides compile commands for headers, then clangd works as expected. However most build systems don’t provide this information. (Bazel, for one, does).
When there’s no compile command provided, we fall back to ‘clang $filename’. Clang treats .h files as C.
But it’s also missing a bunch of other information: include paths, defines etc that are likely required to get useful results.
So I don’t think just diverging from clang here will actually help many projects (feel free to try this out by editing compile_commands.json - if this works for you it’d be good to know).
What can we do then? A few ideas:
- we can preprocess all the files from compile_commands.json on startup (https://reviews.llvm.org/D41911 is the start of this). But we can’t guarantee we get to the file you care about in time, so behavior will be erratic.
- we can pick a compile command arbitrarily and take its flags, which will get include paths and defines right if they’re uniform across the project
- we can just refuse to provide any diagnostics/completions where we don’t have a known-good set of flags.
I’ve dumped these thoughts into https://bugs.llvm.org/show_bug.cgi?id=36899 - I also want to solicit some thoughts on this problem at the BoF session at the next LLVM dev meeting.
I’d like to find time to work on this in the next quarter, but I’m not certain - if anyone is interested in attacking this problem, let me know!
I work on a C++ project which has headers with .h extension and
clangd incorrectly assumes it’s a C code because it emits (besides
other things) “unknown type name ‘namespace’” diagnostics message for
the namespace definition.
I run clangd -input-mirror-file for a while and I can see
textDocument/didOpen calls for the .h headers with “languageId” set to
“cpp”. If I rename a header to .hpp, the problem disappears. I also
tried configuring custom file extension association for C++ in VSCode
and it worked as well. So I believe there must be something wrong just
with .h (i.e. clangd seems not to respect languageId for .h files).
Please, can you guide me how to diagnose the problem better so I can
eventually fill a bug report?
I think you’ve diagnosed it pretty well, but you can get a bit of extra information from the logs clangd writes to stderr. In VSCode, these are visible in the “output” pane, under “clang language server”. This will include the command used to build each file.
I also wonder how the completion is supposed to work in headers in
general. Is there some heuristics to guess the compilation flags
because the headers are not in the compilation database (at least when
generated by cmake)?
Regards,
Jan
Cheers, Sam