Reputation: 872
Imagine being a guest contributor opening a C project similar to the following example code, in an editor using clangd to lint the code:
Makefile:
all:
$(CC) -c -o example.o example.c -DFOO=1
example.c:
int foo = FOO;
int bar = TYPO;
With clangd's default configuration, undeclared_var_use errors will be indicated for both FOO
and for TYPO
. Where TYPO
is intended to illustrate a real error, while the first one is a false positive as FOO
will exist at compile time.
example.c|1 col 11-13 error| clangd: undeclared_var_use|Use of undeclared identifier 'FOO'
example.c|2 col 11-14 error| clangd: undeclared_var_use|Use of undeclared identifier 'TYPO'
Please also consider a larger code base where these symbols could be used in multiple places.
There is the, on some level, similar question: Concise way to disable specific warning instances in Clang, which hints about using #pragma clang diagnostic ignored …
directives. Suppressing warnings is one thing, errors however is another thing. Suppressing the latter neither seems like a reasonable thing to do, is not documented nor does it appear to work when attempting it.
Another similar question is: Make clangd aware of macros given from the compiler, which has an answer requiring to add and maintain a compile_commands.json file. A file which must necessarily live inside the project tree, and can thus be used to avoid the problem this question is asking only when such changes can be made to the codebase.
One thing which is possible to do, is to suppress all occurrences of the error by configuring clangd as:
User's config.yaml (or project's .clangd if there is one):
Diagnostics:
Suppress: undeclared_var_use
While doing so arguable is an improvement, it is not fully satisfactory as it hides real errors. Can one somehow make clangd suppress only the FOO
error? (Random sources suggest putting the problematic variable within parenthesis as argument to the suppress directive, but that seems to be nothing but an unsubstantiated rumour.)
A related bonus question; Is there any documentation for the the diagnostic codes which Suppress takes as arguments, or where could one find them in llvm:s source code? (GitHub issue #649 has an answer for the first part. Searching for the literal strings (e.g. undeclared_var_use) yield surprisingly few results.)
Versions of clangd used debian packaged 1:14.0-55.6 and self-built 17.0.0, commit cd22e7c.
Edit after accepting answer: Stroke out the misconception that compile_commands.json needs to live in the same directory as the source code.
Upvotes: 1
Views: 1790
Reputation: 52779
It's pretty fundamental to clangd's design that to parse your code correctly, it needs to know about the flags used to build the code, including macros defined in the build command such as -DFOO=1
.
Therefore, my advice is to focus on solutions that involve providing clangd with this information, and avoid approaches involving trying to suppress errors except as a very last resort.
You rightly observe that compile_commands.json
is the primary way of providing this information to clangd. As an aside, I'll mention why this is the recommended way: since compile_commands.json
is typically generated by a tool/script from the project's build metadata (for example, for projects with a Makefile
, it's common to generate it with a tool like Bear that wraps the make
invocation and generates the compile_commands.json
as a side effect), this allows keeping the flags (like -DFOO=1
) in one place (namely, the Makefile
) rather than having to repeat them somewhere else for clangd's consumption.
You mentioned not being able to add a compile_commands.json
file to the workspace directory; a couple of thoughts on that:
.gitignore
or similar (though it's fairly common to do that), there are ways to ignore files locally.--compile-commands-dir=<directory>
on clangd's command line. (This is typically specified in your editor's configuration, for example "clangd.arguments"
for vscode.)If none of the above options are satisfying, here is an alternative way of providing the flags to clangd that also does not involve putting any files in the workspace directory:
Create a clangd user config file, e.g. at ~/.config/clangd/config.yaml
.
Use CompileFlags:
Add:
to specify the flags, with If:
PatchMatch:
to scope them to your workspace directory. For example:
If:
PathMatch: /path/to/workspace/.*
CompileFlags:
Add: [-DFOO=1, -DBAR=2]
Configuration for multiple workspaces can be specified in the user config file by having multiple sections separated by ---
:
If:
PathMatch: /path/to/workspace1/.*
CompileFlags:
Add: [-DFOO=1, -DBAR=2]
---
If:
PathMatch: /path/to/workspace2/.*
CompileFlags:
Add: [-DBAZ=3, -DQUX=4]
(It's more common to put this in a project config file (<workspace>/.clangd
), in which case the If:
blocks are unnecessary, but since you're trying to avoid adding files to the workspace directory, I mentioned the approach that avoids that.)
Finally, to directly answer your question of whether an error suppression can be scoped to a particular variable: I haven't come across any such way. Hopefully, one of the above approaches makes this sort of thing unnecessary.
EDIT To answer your bonus question: the easiest way to find out a diagnostic's "diagnostic code" in my experience is to hover over it in the editor. In the hover contents provided by clangd, after the error message you'll see something like clang(typecheck_call_too_many_args_suggest)
; typecheck_call_too_many_args_suggest
is the diagnostic code.
In the clang source code, the diagnostic codes are defind in one of these files (in my experience, the most commonly encountered errors are in DiagnosticSemaKinds.td. You can search for the wording of the error message there to find the corresponding entry, e.g. this one; the diagnostic code will be the part after the err_
.
Upvotes: 1