Moberg
Moberg

Reputation: 5519

Why does clangd not find all references?

How can I figure out why a reference can't be found by clangd? Can I list the index to understand if what I'm looking for is missing?

Clangd docs

clangd has this information (see https://clangd.llvm.org/faq#why-does-clangd-not-return-all-references-for-a-symbol)

One of the potential reasons is that clangd has not indexed all the files in your project. Please make sure all files are visible to clangd through the project setup and compile_commands.json.

How do I make sure they are visible? Is just that the path of cc file is listed explicitly somewhere in the json file? (In that case, that is achieved)

More info about this particular case

I have a c++ project built with cmake and a compile_commands.json file is created as part of the build.

When I afterwards start my editor with clangd LSP, most LSP features like goto_definition and references work as expected, but some generated source files cant be found until I open them manually with my editor.

Source code files:

Some files cc files are generated by a build step (cmake+ninja+python) and put into build folder:

When I perform lsp-call references() to try to find references from a.cc or a.hh the usages in gen_a_usage.cc file are not listed.

How can I figure out why I can't find gen_a_usage.cc? After I have opened this file from the build folder in my editor, references() start to list references in this file as well.

In reality the project is much bigger than just these three files. Both a.cc have entries and gen_a_usage.cc have entries in the compile_commands.json file.

Can it be that indexing is slow or fails?

extract from compile_commands.json

{
  "directory": "/my_repo/base/build",
  "command": "clang-wrapper-19.1.1/bin/clang++ -I/my_repo/base/build/generated -I/my_repo/base/src -I... -isystem ... -Og -g -std=gnu++20 -fPIC -Wall -Wextra -Wformat-signedness -ggdb -fcolor-diagnostics -o CMakeFiles/objects.dir/src/a.cc.o -c /my_repo/base/src/a.cc",
  "file": "/my_repo/base/src/a.cc",
  "output": "CMakeFiles/objects.dir/src/a.cc.o"
},
{
  "directory": "/my_repo/base/build",
  "command": "clang-wrapper-19.1.1/bin/clang++ -I/my_repo/base/build/generated -I/my_repo/base/src -I... -isystem ... -Og -g -std=gnu++20 -fPIC -Wall -Wextra -Wformat-signedness -ggdb -fcolor-diagnostics -o CMakeFiles/objects.dir/src/gen_a_usage.cc.o -c /my_repo/base/build/generated/gen_a_usage.cc",
  "file": "/my_repo/base/build/generated/gen_a_usage.cc",
  "output": "CMakeFiles/objects.dir/src/gen_a_usage.cc.o"
},

Environment

I have seen this behavior in clangd version 16, 19, and 20. And my colleague has similar issues in vscode.

LspLog has this information

ASTWorker building file /my_repo/base/src/a.cc version 0 with command \n[/my_repo/base/build/generated -I/my_repo/base/src -I... -isystem ... -Og -g -std=gnu++20 -fPIC -Wall -Wextra -Wformat-signedness -ggdb -fcolor-diagnostics -o CMakeFiles/objects.dir/src/a.cc.o -c clang-19.1.1/lib/clang/19 -- /my_repo/base/src/a.cc\n"
Loaded compilation database from /my_repo/base/build/compile_commands.json\n"
--> window/workDoneProgress/create(0)\n"
Enqueueing 930 commands for indexing\n"
<-- reply(0)\nI[11:45:43.742] --> $/progress\nI[11:45:43.742] --> $/progress\n"
Built preamble of size 21624316 for file /my_repo/base/src/a.cc version 0 in 1.46 seconds\n"
--> workspace/semanticTokens/refresh(1)\n"
Indexing c++20 standard library in the context of /my_repo/base/src/a.cc\n"
<-- reply(1)\n"
--> textDocument/publishDiagnostics\n"
Indexed c++20 standard library (incomplete due to errors): 15846 symbols, 2600 filtered\n"
<-- textDocument/references(2)\n"
--> reply:textDocument/references(2) 0 ms\n"
--> $/progress\n"
--> $/progress\nI[11:45:51.571] --> $/progress\nI[11:45:51.571] --> $/progress\n"
Indexed /my_repo/base/src/a.cc (136 symbols, 18679 refs, 475 files)\n"
--> $/progress\n"
Indexed /my_repo/base/src/b.cc (141 symbols, 18527 refs, 463 files)\n"
--> $/progress\n"

Upvotes: -1

Views: 136

Answers (1)

HighCommander4
HighCommander4

Reputation: 52837

I'm not seeing anything obviously wrong or suspect with your setup -- I think this scenario should work.

You've already checked the first thing I would have suggested checking, that the generated source file is present in compile_commands.json.

Presumably you've also verified that the reference in a.cc is found without having to open a.cc first (e.g. with only having opened a.hh), and thereby ruled out an issue with indexing the project in general -- it's specifically gen_a_usage.cc that's behaving differently from a.cc.

So next I would try to narrow down what the difference is between gen_a_usage.cc and a.cc. Two places to check for a difference:

  1. Compile flags. Maybe gen_a_usage.cc has compile flags that are different from a.cc's compile flags in some way that's relevant to the symbol ID clangd computes for the function? The most common examples of these are different languages (e.g. C vs. C++), and macro definitions that affect the function signature (e.g. an INT32 macro in a parameter type that expands to int in one source file but long in another). If possible, try modifying the compile flags of one source file to be exactly the same as the other, and see if the difference persists.
  2. Location on the filesystem. Try moving gen_a_usage.cc into the same directory as a.cc, make a corresponding adjustment to its compile_commands.json entry, then restart clangd to give it a chance to index the file in its new location, and see whether the failure to find the reference persists. I think this shouldn't make a difference, but this is a complex area of clangd's implementation and there may be bugs or edge cases (e.g. maybe around symlinks) that could play a factor.

If these avenues of investigation don't provide any clues, additional ideas would be:

  • Share a complete set of clangd logs for additional analysis.
  • Narrow down the problem to a minimal project that you're able to share in its entirety.

You can then share the logs and/or minimal project in a clangd issue for further help.

Upvotes: -1

Related Questions