Qt Creator and clangd: An Introduction

As I hinted at recently, we have spent the last couple of months implementing a new clangd-based back-end of our C/C++ code model. With the second beta of Qt Creator 6 having been released, I feel we can now  in good conscience ask you to enable this feature and take it for a test drive.

Why?

Let's start with a bit of history. In the beginning, there was our built-in code model: It was fast, quite good with C++98 code, and is still used today for things like quick fixes. However, it soon became clear that it would not be able to keep pace with the rapid progress of C++. We therefore introduced the Clang Code Model, which is based on libclang. Building on the capabilities of LLVM, we were able to offer far better support for features such as symbol completion, code highlighting and diagnostics. However, we still had to employ the built-in code model for all features that require a full index of the project (because libclang does not have one), so the quality of global search results did not improve. In addition, libclang soon stopped being actively developed, while more and more effort was being spent on the newly invented clangd. So ever since we added support for the Language Server Protocol to Qt Creator, there was an obvious way forward.

How?

In Qt Creator 6, clangd will still be opt-in, so you have to actively enable it: Go to Tools -> Options -> C++ -> Clangd (on macOS: Qt Creator -> Preferences -> C++ -> Clangd) and activate the checkbox at the top. Make sure to use a current clangd – Version 13 is required (and shipped with our installer). If you dare to build LLVM yourself from the main branch, you will get rewarded with some improvements relying on recently contributed upstream patches (see below).

clangd-settings

Note that the settings are per-project, so if you want to make use of clangd only for some projects, you can easily do so.

What is new?

Arguably, the most important improvement is based on clangd's index, which finally gives us exact and complete results for "Find References", "Follow Symbol" and locators even in the presence of complex constructs that our built-in code model trips over. As soon as you load your project, clangd will start scanning its source files to build up the index (unless you opt out via the settings; see above). For larger projects, this procedure can take a while, but fear not: The index is persistent and re-scanning is incremental, so nothing is lost by closing and re-starting Qt Creator.

clangd-parsing

We consult clangd only after the indexing procedure has finished. Until then, the results will come from our (somewhat) trusty old built-in code model.

What has improved?

Generally, the user experience should be roughly the same as with the libclang-based code model, with more or less subtle improvements in all areas. One noteworthy example is our document outline, which is now backed by clangd's document symbol support, whereas before we had to assemble the symbol tree manually from libclang's token/cursor data, which was rather error-prone, as some of you have probably noticed.

For an overview of what kinds of bugs will disappear when switching to clangd, click here.

Any drawbacks?

Unfortunately, clangd considers only the on-disk state of included header files when parsing a source file, which means that after you edit a header file, you need to save it before these edits are considered elsewhere for completion, diagnostics and so on.

[Update: This has now been fixed for the next clangd release (LLVM 14).]

It is partly for this reason that starting with Qt Creator 6, we now auto-save files changed by refactoring actions. You can opt out of the new behavior via Tools -> Options -> Environment -> System.

As already mentioned, some clangd improvements required to maintain our feature set did not make it into LLVM 13. Therefore, we have some temporary regressions, the most important of which are:

  • No special highlighting for virtual function calls.
  • No tooltips for included header files (showing the full path).
  • No filtering for signals when completing the second argument to QObject::connect().

All of these will be gone with LLVM 14.

Otherwise, you can expect some glitches and rough edges here and there, particularly in the areas of highlighting and completion. We aim to fix these for the final release. If you observe any other regressions compared to the libclang-based solution, do not hesitate to report them at our bug tracker.

What's next?

Our plan is to continue to improve our clangd integration (not least based on your feedback!) and make it our default code model backend in Qt Creator 7. After that, we will remove the libclang-based backend, while the built-in code model will still serve as a fallback.


Blog Topics:

Comments