Qt Creator’s Clang Code Model

Published Tuesday June 5th, 2018
20 Comments on Qt Creator’s Clang Code Model
Posted in Dev Loop, QtCreator

Starting with the upcoming Qt Creator 4.7, the Clang Code Model is enabled by default. That’s a great time to look at the differences between our old code model and the new Clang Code Model. But first things first.

History of C/C++ Support in Qt Creator

Since the beginning of Qt Creator the C/C++ support was implemented around a custom C++ frontend (lexer, preprocessor, parser, lookup). The whole support was referred to as the “C/C++ Code Model”, the code model being the collection of language-specific services, for example code completion and semantic highlighting.

Back then the next C++ standard was a long time in the coming (C++0x – C++1x – C++11), the tooling support from Clang was not where it is today and  a custom C++ front-end gave us some extra flexibility when it comes to performance, error recovery and support of Qt-specifics. The code model around the custom front-end served us well (and still does) – the appropriate trade-offs between precision and performance were made back then. However, maintaining a custom C++ front-end is not a trivial task, notably so during the interesting times for the company we were part of back then, and with only a few developers on it. With the availability of Clang and its tooling, especially from the point on where it became self-hosting, we did some experiments to base the code model on it – the “Clang Code Model” was born. The experiments looked promising in general, but the stability and performance were a problem from the beginning on, especially when considering all platforms.

Fast forward: today C++ evolves much faster, Clang and its tooling are prospering and we have picked up working on the Clang Code Model.

Status of the Clang Code Model

We believe to have addressed the most severe performance and stability issues by now. With the Clang Code Model you get up to date language support based on libclang 6.0, greatly improved precision and diagnostics.

The first big area we have tackled are the services related to the currently open file, not taking any project or global index information into account yet, which is work in progress. Currently, the following services are implemented with the Clang Code Model:

  • Code completion
  • Syntactic and semantic highlighting
  • Diagnostics with fixits and integrated Clang-Tidy and Clazy checks
  • Follow Symbol (partly)
  • Outline of symbols
  • Tooltips
  • Renaming of local symbols

For the not yet ported services, the services based on the custom frontend are used. This includes for example indexing, find usages and refactoring.

Due to Clang’s precision the Clang Code Model is inherently slower than the old code model and has lower error recovery capabilities. However, the extra precision and diagnostics will result in less build errors and thus reduce your edit-build-cycle count.

Differences to the old code model

Now what are the visible changes that you can observe as a user?

Updated language support

The Clang Code Model is based on libclang 6.0 and as such it can parse C++17 and more.

Precision

You will immediately notice the improved precision in highlighting and diagnostics.

For example, our custom front-end never validated function calls and thus you would notice these when building. With the Clang Code Model only valid function calls are properly highlighted, whereas invalid ones will be rendered as “Text”, that is, black by default.

Another example is code completion. Items are no longer offered for declarations that are below your completion position, except class members of course. Also, completion of const objects will take the “constness” into account.

Diagnostics

Chances are that you will notice Clang’s diagnostics early on, as they are displayed as inline annotations in the editor. Detailed information is provided by tooltips. Check out for the light bulb at the end of the line, as these indicate the availability of “Fixits”. These are small/local refactoring actions fixing diagnostics.

Of course the diagnostics for the current document are also available in the Issues pane. This behavior can be disabled by using the “Filter by categories” icon in the Issues pane toolbar.

You can set up diagnostic configurations in C++ > Code Model > “Manage…” in the options dialog. The predefined configurations are really a starting point and it is recommended to adapt them to your needs. For example, you could set up a configuration for a specific project.

Note that Clang-Tidy and Clazy checks are integrated, too. Enabling these checks for the Clang Code Model will naturally slow down re-parsing, but depending on your machine and the specific selection of checks this can be a great help. Starting from this version, it is also possible to run Clang-Tidy and Clazy checks for the whole project or a subset of it (Menu: Analyze > “Clang-Tidy and Clazy…”). For example, you could set up a diagnostic configuration for this mode that also enables the expensive checks and run it once in a while.

Code Completion

In general, the completion is more context-sensitive now. For example, completing after “switch (“, “case “, “int foo = ” or after “return ” will put more relevant items to the top of the completion list.

The completion of templated classes and functions is improved. Completion of unique_ptr<>/shared_ptr<> objects and friends works now on all platforms.

Does your code base make use of doxygen comments? Then you will probably be happy to see doxygen comments as part of the completion item, too.

Miscellaneous

Italic arguments in a function call indicate that the function call might modify the argument (“Output Argument” in the text editor settings).

Tooltips resolve “auto” properly and show also doxygen comments.

A visible document is automatically re-parsed if one of its headers is modified, either in an editor or on disk.

Future of C/C++ Support

Given the evolving tooling around C++ it is pretty unlikely that we will go back to a custom front-end.

Given the raise of the Language Server Protocol and the development of clangd, how to proceed from here on? The implementation of an LSP client makes sense for any IDE to also get support for other languages. And we are actively working on that. Having that, it will also help us to evaluate clangd further.

Do you like this? Share it
Share on LinkedInGoogle+Share on FacebookTweet about this on Twitter

Posted in Dev Loop, QtCreator

20 comments

Louis says:

Hello,

Concretely when I develop I spend most of my time doing Ctrl+Space to open the completion context menu or doing “obj->” and let the completion context open and be filtered while typing the first letters of the function, and then pressing Enter to validate the proposal.

I have followed for a long time the changes on the Clang Code Model and even if I see that it is indeed more precise and more suited to “compile less”, the slowness of the tool for the example above makes me a bit reluctant from updating Qt Creator. I really “feel” the delay, and that makes the development less fluid from my point of view, because it forces you to depend less on the completion. I have tried recently (QtCreator 4.6) and still had this feeling.

Did you have this issue on your side?

James says:

I type very fast, and the only auto-complete tool that has ever worked for me is Visual Assist X. It’s super-fast, it’s instantaneous.
For any other tool, I am faster to type the whole variable/function/class name manually, which completely defeats the purpose.

Eike Ziller Eike Ziller says:

I suppose the only way to find out if completion speed is sufficient for you, is to try it.

Note that you can update to Qt Creator 4.7 in any case. The built-in model still exists, just disable the ClangCodeModel plugin.

Nikolai Kosjar says:

Hi!

> I really “feel” the delay, and that makes the development less fluid from my point of view
> Did you have this issue on your side?

libclang makes use of a cache and this works fine here. There are quite some reasons why completion might be slow (cache not working, completion job is not run immediately for some reason, number of completion items to process).

Currently there is also a case for which the completion is actually triggered twice under the hood (is this your main case?): For member completion of a e.g. raw pointer with the dot (“foo.”) the completion fails and we try again with “foo->” for convenience and then correct the dot to arrow. Work going on to address this case to a single completion operation (https://reviews.llvm.org/D46862).

> I have tried recently (QtCreator 4.6) and still had this feeling.

Suggestion: Try the 4.7 beta and report back (https://bugreports.qt.io/), preferably with something to reproduce.

jon says:

basically I’m ok with you, but current most clang based code model does only cache the data in the ram, which is pretty suck when working with boost , v8 js,other heavy header only and other chromium based project sources with heavy template codes when the fact that you only have to work with 2gb ram. I’m just upset it should be possible to cache metadata about clang AST into the disk at cost of long initialization at start up.

d3fault says:

use a massive “swap” partition/file and you will get the exact behavior you desire.

CarelC says:

Well done on getting this far. Previously I have never used the clang code model but since Qt Creator 4.6 I have been using it with much success and much less frustration than before.

As the developer of the SpellChecker plugin[1] for Qt Creator, what are the current plans with the old code model?
My plugin still uses this model and its information to extract comments and literals from the code. Thus I need to plan the future for the plugin based on the Clang Code Model “taking over”.

So far (QtC 4.6) the plugin works well even if the Clang Code model is enabled, will this still be the case for Qt Creator 4.7 and the upcoming versions?
When will this stop working?

[1] https://github.com/CJCombrink/SpellChecker-Plugin

Nikolai Kosjar says:

Thanks CarelC!

> …what are the current plans with the old code model?

We port piece after piece over to the Clang Code Model. Eventually, the functionality of the old code model will be fully replaced.

> So far (QtC 4.6) the plugin works well even if the Clang Code model is enabled, will this still be the case for Qt Creator 4.7 and the upcoming versions?
> When will this stop working?

Your plugin should work fine with 4.7 and probably also with subsequent versions. As your code relies on CppTools::CppModelManager::documentUpdated it can take a while until we have a proper replacement for that. Note that your plugin is not the only one relying on that.

It seems that clang has also some spell checking capabilities (“-fspell-checking”), although it is disabled for performance reasons – this might be an alternative to the current approach. Investigation would be needed here.

In general it is hard to tell as it depends on how fast we progress with porting existing functionality to the ClangCodeModel and of course the problems we encounter when doing so.

tim blechmann says:

i’m wondering, is there a difference between the old and new code model in terms of the memory usage? since you mention the cpu load, are there any thoughts about switching between old and new code model dynamically? e.g. to improve battery life when working on a laptop.

Ivan Ivan says:

Unfortunately they have to work together when ClangCodeModel is enabled. For example when you use “follow symbol” ClangCodeModel tries to find a match in the current TU but if it is not successful old code model finishes the job.
In terms of memory usage – it’s not that good because both code models consume memory.

pc2005 says:

Sorry, but the poor performance still renders it unusable under Windows with anything but small projects – it’s been like this for years and it’s been reported to death 🙁
It’s faster to write name of a method manually than wait ~10s for autocompletion on i7 6700K@4.5Ghz after ‘ . ‘ or ‘->’.

Thanks anyway, I’m sure it’s working for someone and I can image it’s great – I loved it besides the performance, Qt Creator integration is very well done.

Cristian says:

You can tune the clang plugin to your source code. From 10s you might be able to get to 6s. See https://cristianadam.eu/20160104/speeding-up-libclang-on-windows/

Kevin says:

Unfortunately, for an autocompletion engine anything over a second is going to be long enough to be annoying. 6 seconds just doesn’t cut it.

I wonder if the Qt Creator team has checked out cquery, and whether they perform any better here? https://github.com/cquery-project/cquery — perhaps there’s something to learn / use with their own libclang integration.

Eike Ziller Eike Ziller says:

We ship Qt Creator with a MinGW profile optimized libclang since a while now (because of your experiments and comparison!). Of course not trained with “your” code, but trained for the use cases in Qt Creator in general. So I wonder how much improvement can be still squeezed out of that approach?

Jakub Narolewski says:

+1

Horrible autocompletion, and clang background compile performance on ryzen 2700x, win 10 x64

Unusable as of now.

As a plus, TODO plugin finally got an icon in options menu 😛

Ivan Ivan says:

The big fix for ‘.’ to ‘->’ and back is almost there. We’re going to have it before release.

Nikolai Kosjar says:

> … and it’s been reported to death 🙁

“10s for autioncompletion” sounds as something is heavily broken there, and probably not only completion.

Please provide a link to the bug report or create a new report with something to reproduce.

Konstantin says:

+1

I agree that autocopletition is unusable. Lag with ~10 seconds slow down my work.

Can you do this:
1. Make autocopletition working with old code model.
2. In a background run clang with warnings
?

Vadim Peretokin says:

Thanks so much for working on this. Having the clang and clazy fixits integrated is amazing.

Danny says:

As someone who develops Objective-C code in Creator, the Clang code model is absolutely necessary. The built in code model was only ever usable with C++ code; it has problems even with C99.

Commenting closed.

Get started today with Qt Download now