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/cc_args.py 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
cc_args.py isn’t perfect. Make changes working dirs as it recurses through your code base, so
cc_args.py‘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.