xavierd / clang_complete

Vim plugin that use clang for completing C/C++ code.
http://www.vim.org/scripts/script.php?script_id=3302
1.96k stars 308 forks source link

Path caching helpers clang.vim and cache.vim creates conflicts on header usage by clang #182

Open oblitum opened 12 years ago

oblitum commented 12 years ago

I compile both clang and libclang from repository and put them at /usr/local because I want to make use of the newer c++11 features.

clang_complete works fine with them, except that I was noticing it failing completion for some header files, like for members from <random> for example.

I configure g:clang_user_options as let g:clang_user_options='-O0 -std=c++11 -stdlib=libc++' and these options work fine to compile (from the command line) a source file that includes the header <random> and I thought the options that were being passed to clang_complete were mainly these ones set through g:clang_user_options.

So, to debug these completion failings I've disabled g:clang_use_library to get the diagnostics window open, so I could see in case there was some compilation problem happening.

I got a bunch of compilation errors when trying completion inside a source file that included <random>. I suspected clang_complete was using the wrong header files for my configuration, so to track down I've logged the clang startup line done by clang_complete.vim at this section:

let l:command = g:clang_exec . ' -cc1 -fsyntax-only'
        \ . ' -fno-caret-diagnostics -fdiagnostics-print-source-range-info'
        \ . ' -code-completion-at=' . l:escaped_tempfile . ':'
        \ . line('.') . ':' . b:col . ' ' . l:escaped_tempfile
        \ . ' ' . b:clang_parameters . ' ' . b:clang_user_options . ' ' . g:clang_user_options

I've figured out that b:clang_user_options was expanding to something including contents from the header cache file cpp.clang.cache generated by cache.vim, this file had this contents:

-I/usr/include/c++/4.2.1/
-I/usr/include/c++/4.2.1/backward/
-I/usr/local/include/
-I/usr/local/lib/clang/3.2/include/
-I/usr/include/

and trying to compile from the command line with similar configuration as the one clang_complete was getting:

clang++ -I/usr/include                      \
        -I/usr/include/c++/4.2.1/           \
        -I/usr/include/c++/4.2.1/backward/  \
        -I/usr/local/include/               \
        -I/usr/local/lib/clang/3.2/include/ \
        -I/usr/include/                     \
        -std=c++11 -stdlib=libc++ main.cpp 

has made the exactly same kind of errors show up in compilation.

The problem is that this header path caching is making clang_complete to load headers from unexpected locations overwriting the default/expected include locations as done from the command line.

oblitum commented 12 years ago

by just makingclang_complete/autoload/getopts/cpp.clang.cache an empty file keeps everything working. Just wondering why this path cache anyway.

oblitum commented 12 years ago

Well, looking at both path cache scripts (autoload/getopts/clang.vim and autoload/getopts/cache.vim) I see it fills the cpp.clang.cache file with include directories parsed from the following command:

echo | clang -v -E -x c++ -

Which on my system gives:

clang version 3.2 (http://llvm.org/git/clang.git 77b1ae5656cc6ca41bf02831b37fae2d9b27c2a4) (http://llvm.org/git/llvm.git e11246c64eb8ea3da0060be4ddb9596c8cc04439)
Target: x86_64-apple-darwin12.0.0
Thread model: posix
 "/usr/local/bin/clang" -cc1 -triple x86_64-apple-macosx10.8.0 -E -disable-free -disable-llvm-verifier -main-file-name - -pic-level 2 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 128.2 -v -resource-dir /usr/local/bin/../lib/clang/3.2 -fmodule-cache-path /var/folders/hq/z21jx8qj6n1c84tf8cgcz1k40000gn/T/clang-module-cache -fdeprecated-macro -fdebug-compilation-dir /Users/francisco/Desktop -ferror-limit 19 -fmessage-length 181 -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.8.0 -fobjc-dispatch-method=mixed -fobjc-default-synthesize-properties -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o - -x c++ -
clang -cc1 version 3.2 based upon LLVM 3.2svn default target x86_64-apple-darwin12.0.0
ignoring nonexistent directory "/usr/include/c++/4.2.1/i686-apple-darwin10/x86_64"
ignoring nonexistent directory "/usr/include/c++/4.0.0"
ignoring nonexistent directory "/usr/include/c++/4.0.0/i686-apple-darwin8/"
ignoring nonexistent directory "/usr/include/c++/4.0.0/backward"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/4.2.1
 /usr/include/c++/4.2.1/backward
 /usr/local/include
 /usr/local/bin/../lib/clang/3.2/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.
# 1 "<stdin>"
# 1 "<stdin>" 1
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 161 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "<stdin>" 2

I'm not using the default standard library, that's why I set let g:clang_user_options='-O0 -std=c++11 -stdlib=libc++'.

Executing the same command with this configuration:

echo | clang -std=c++11 -stdlib=libc++ -v -E -x c++ -

gives a different output and a different set of include directories:

clang version 3.2 (http://llvm.org/git/clang.git 77b1ae5656cc6ca41bf02831b37fae2d9b27c2a4) (http://llvm.org/git/llvm.git e11246c64eb8ea3da0060be4ddb9596c8cc04439)
Target: x86_64-apple-darwin12.0.0
Thread model: posix
 "/usr/local/bin/clang" -cc1 -triple x86_64-apple-macosx10.8.0 -E -disable-free -disable-llvm-verifier -main-file-name - -pic-level 2 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 128.2 -v -resource-dir /usr/local/bin/../lib/clang/3.2 -fmodule-cache-path /var/folders/hq/z21jx8qj6n1c84tf8cgcz1k40000gn/T/clang-module-cache -stdlib=libc++ -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /Users/francisco/Desktop -ferror-limit 19 -fmessage-length 181 -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.8.0 -fobjc-dispatch-method=mixed -fobjc-default-synthesize-properties -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o - -x c++ -
clang -cc1 version 3.2 based upon LLVM 3.2svn default target x86_64-apple-darwin12.0.0
ignoring nonexistent directory "/usr/include/c++/v1"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/bin/../lib/c++/v1
 /usr/local/include
 /usr/local/bin/../lib/clang/3.2/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.
# 1 "<stdin>"
# 1 "<stdin>" 1
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 163 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "<stdin>" 2

So this header path cache generation will ignore if I'm using libc++ or c++11 and these include paths will override my include priority that I could set through let g:clang_user_options.

Also, just by not making use of these cached includes doesn't break anything since, as far as I know, the compiler will include the correct defaults anyway.

Another problem with this obscure header path cache generation is that the script, once creating and filling cpp.clang.cache the first time it doesn't find the file, will let it untouched, loading it as is, just by checking whether it already exists, and ence, aways overriding other include directories with the same ones of the first cache generation.

That's also why letting cpp.clang.cache empty, but not deleting, keeps everything working.

oblitum commented 12 years ago

I've found the option g:clang_auto_user_options controls the loading of the path caching helpers, I've set it as let g:clang_auto_user_options = '.clang_complete' only, so I know for sure which include paths are set to be used by clang_complete.

I suggest this as the default, and most stable, option.

The default now is: 'path, .clang_complete, clang'.

With the last being the cause of this issue.

If the user wants optimization it should go and deal with the docs instead of getting it by default with the risk of getting in trouble like myself. By doing this he would be more likely to know beforehand the implications of his settings.

So, after setting g:clang_auto_user_options the path cache helpers won't load anymore and I can just delete cpp.clang.cache without problems.

xaizek commented 12 years ago

So does fix for #195 work for you? I think it should.

The reason why g:clang_auto_user_options contains clang by default is that there were several issues that people can't make clang_complete work because of need to specify include paths.

Making clang_complete work out of the box without the need to read documentation should be considered to be good. Otherwise we should provide a starting tutorial with instructions on include paths, which some users still can ignore and create new issues about not working completions.

oblitum commented 12 years ago

I still hadn't applied this patch, I've read briefly the added documentation and code and it seems there's added logic now, appending includes at the end, etc. For me, this option should really be removed, it's too error prone and complicated to support, a tutorial or notice about passing compiler options through the original g:clang_user_options is much better, because in the end, the dude is a compiler user!

Even with the current corrections, I still will not use g:clang_auto_user_options because there're two problems, that I know from before, and will still persist.

The first one is that adding too many sources for includes will make Clang provide too many results, from all places it can get, so the completion experience is not best. I want results only from libc++, e.g., libc++ implements std::bind with variadic templates, but when I was using g:clang_auto_user_options I was getting a bunch of overloaded parameter implementation for std::bind too, by not using it I just get one single correct result from the correct library, the one I want to use.

Second problem, too many results slow things down.

oblitum commented 12 years ago

Also, I think adding cached includes automatically, makes errors relating to include ordering and other possible problematic behavior a bit hidden.