Bye Bye OmniCppComplete, Hello Clang Complete

For years OmniCppComplete has been the de facto standard for C++ completion in Vim. But as time progressed, I got more and more annoyed by it’s shortcomings. OmniCppComplete is based on tokenizing provided by ctags. The ctags parsing of C++ code is problematic, you can’t even run it on libstdc++ headers (you need to download modified headers). You want to use an external library? You’ll need to run ctags seperatly on each library. Not to mention it’s inablity to deduce types of anything more than trivial. The core of the problem is that OmniCppComplete isn’t a compiler and you can’t expect something that isn’t a compiler to fully understand code. This what makes Visual Studio’s IntelliSense so great: it uses the Visual C++ compiler for parsing, it isn’t making wild guess at types and what is the current scope – it knows it.

With this on my mind, I set out to look for a better alternative. The first thing I looked for is getting GCC to give me type info. Apparently, GCC doesn’t like to play nice with other and provide this information (I read in couple of places people cite RMS/FSF saying it’s deliberately in order not to allow proprietary software to use GCC without linking against it, like crashing your car so nobody wants to steal it – plain dumb). The only solution is to patch like GCCSense, which does exactly what I looked for, compiler based auto-completion. But patching GCC only to work around perverted FSF policies seems like not the most elegant solution. This is where clang, a modular and developer friendly compiler, came to my mind.

After a quick searching I came across clang complete. This plugin uses clang to parse your code and suggest completion. Auto-complete worked out of the box for the standard library, STL and Boost, and it worked properly (already better than OmniCppComplete). If you want to use libraries which aren’t in your default search path, i.e. gcc need you to specify -I flags or you need -D flags, you’ll need to pass them on to clang. This may sound difficult, but the developers of the vim script provide a wrapper to automatically understand what should be the proper flags from your build system. All you need to do is pass CXX='~/.vim/bin/ g++' to make and the script will record your flags in a .clang_complete file, which it will use from now on. After you do it (except a little glitch, see bellow), omni-completion will work for every library in your code base.

There are still some glitches that need to be polished. First of all, the suggested way to invoke isn’t perfect. Make changes working dirs as it recurses through your code base, so‘s working-dir isn’t the same as yours, but the plugin will search for the .clang_complete file in your working-dir (the one vim has). The solution is just to move the .clang_complete files to the main directory of the project, from whatever subdirectory it created them in, and merge them (simpler than it sounds). Also this task needs to be done once for every project, so no big deal.

There are two other problems that still bother me. The plugin’s author says that if you set the plugin to use libclang it would work much faster and use caching. However, libclang isn’t currently packaged for Ubuntu 11.10. This should be solve next month with the release of Ubuntu 12.04, which provides it. The second problem is a weird bug in clang. When I try to compile a C++11 file with clang (providing the -std=c++0x flag, it segfaults, pretty weird. But I guess a bit more searching and maybe some bug-reporting will fix this issue (sadly, this means that the plugin can’t autocomplete c++11 features as well).

Despite some rough edges it’s way better than any previous C++ completion for Vim I ever seen. At the begging I hesitated when I had to remove OmniCppComplete due to conflicts with clang complete, and now after a (very) shot time using clang complete I don’t think I’ll miss it anytime soon.

Update May 2, 2012: Ubuntu 12.04 got released, so I finally checked the status of the completion using libclang. Apparently, you also need to install the libclang-dev package (in addition to libclang1, or else, clang_complete will output cryptic error messages. The clang 3.0 that comes with Ubuntu 12.04 no longer segfaults on c++11 code, but it refuses the compile anything with boost’s shared_ptr, due to issues with move semantics.

14 thoughts on “Bye Bye OmniCppComplete, Hello Clang Complete”

  1. Does clang work if you have source code in a bunch of different directories? How does it compile your source code if you have external library references?

  2. Yes, the plugin has a useful wrapper around clang that you can pass to your build system. The wrapper, apart from compiling your code, records all the flags that get passed to clang and then passes them on whenever the plugin calls clang to parse your code. This allows it to be aware of special include directories and etc.

  3. What do you use for automatically close (,{ ,[ and < ?
    I saw a lot of stuff at the vim wiki and I'm new to programming ,so I just wanna know what others use?

    Appreciate the suggestion.


  4. Actually I currently don’t have anything like that, and I don’t really miss it. However if you find a good plugin for it, i would be great if you could write which one.

  5. To get clang working, do you need the LLVM source code or can you just use the clang source code? Or do you need both?

  6. You don’t need the source code itself, binary packages will be fine. IIRC clang depends on llvm, but your package manager should handle it for your anyway.

  7. Just wondering for the case without a package manager. Just binaries is still fine? Which one do I use for redhat?

  8. I never tried doing it without the package manager, but if for some reason I would need, I would look at the dependencies that one of the distros list (say the SPEC file in the RPM for fedora) and get the required dependencies from there.

  9. Unfortunately I couldn’t get it to work with Ubuntu 12.10. I used sudo apt-get install clang, but gVim doesn’t complete code in cpp files.

  10. That’s because you need to install the clang-complete plugin separately. It doesn’t come with Ubuntu’s clang package (it isn’t part of the official clang).

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.