Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't complete any C++ system headers and only some C system headers but jumping to their definition works #125

Closed
bfrg opened this issue Nov 19, 2018 · 7 comments
Labels
client question Further information is requested

Comments

@bfrg
Copy link

bfrg commented Nov 19, 2018

I'm on Gentoo Linux using ccls through vim-lsp. Further system info see below.

Issues

ccls doesn't find any C++ system headers and only a few C system headers:
screenshot-2018-11-19_205850

Completion of std::vector doesn't work:
screenshot-2018-11-19_210105

But completing a std::vector method or nested type works:
screenshot-2018-11-19_223733

Completing the methods of a std::vector instance works, too:
screenshot-2018-11-19_210007

Jumping to the definition of std::vector (or any of its methods) works, too:
screenshot-2018-11-19_210335

System info

This is how I built ccls:

$ mkdir build && cd build
$ cmake .. -DSYSTEM_CLANG=on -DCMAKE_PREFIX_PATH=/usr/lib/llvm/7 -DLLVM_ENABLE_RTTI=on
$ make -j4

My system include directories (output of clang -E -v -xc++ /dev/null):

/usr/include/c++/v1
/usr/lib64/llvm/7/bin/../../../../lib/clang/7.0.0/include
/usr/include
$ clang++ -print-resource-dir
/usr/lib64/llvm/7/bin/../../../../lib/clang/7.0.0

This issue is similar to #37.

@MaskRay
Copy link
Owner

MaskRay commented Nov 20, 2018

This issue is similar to #37.

It is different. See my comment at #37 (comment)

From your clang -E -v -xc++ /dev/null output, /usr/include/c++/v1 indicates your clang uses libc++ for its -stdlib=platform. Are you using default-libcxx?

libstdc++

Can you try this .ccls configuration?

clang++
-stdlib=libstdc++

Alternatively, set the initialization option clang.extraArgs, e.g.

  • command line: ccls -index ~/project -init='{"clang":{"extraArgs": ["--stdlib=libstdc++"]}}'
  • client setting: check out how to pass initialization options

libc++

See https://github.com/llvm-mirror/clang/tree/master/lib/Driver/ToolChains/Linux.cpp#L872

void Linux::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
                                  llvm::opt::ArgStringList &CC1Args) const {
  const std::string& SysRoot = computeSysRoot();
  const std::string LibCXXIncludePathCandidates[] = {
      DetectLibcxxIncludePath(getDriver().ResourceDir + "/include/c++"),
      DetectLibcxxIncludePath(getDriver().Dir + "/../include/c++"),
      // If this is a development, non-installed, clang, libcxx will
      // not be found at ../include/c++ but it likely to be found at
      // one of the following two locations:
      DetectLibcxxIncludePath(SysRoot + "/usr/local/include/c++"),
      DetectLibcxxIncludePath(SysRoot + "/usr/include/c++") };

In a debug session, I find the 4 DetectLibcxxIncludePath calls all return "".

DetectLibcxxIncludePath(SysRoot + "/usr/include/c++") is empty for my case because I have not installed system libc++ headers. After some investigation, I find I can do:

c-index-test -code-completion-at=a.cc:7:10 -stdlib=libc++ a.cc -ccc-install-dir ~/llvm/Release/bin -resource-dir=~/llvm/Release/lib/clang/8.0.0

ccc-install-dir should point to your clang installation directory (getDriver().Dir)

BTW, if you use clang 8, its clangSema implements a native #include completion which ccls uses to replace include_complete.cc.

@MaskRay MaskRay closed this as completed Nov 20, 2018
@bfrg
Copy link
Author

bfrg commented Nov 20, 2018

Yes, I do have the default-libcxx USE flag enabled and ccls jumps to the correct std::vector definition (see last screenshot).

libstdc++

I've added the -stdlib=libstdc++ option and completion works better now, but it still won't list all system include headers.

libc++

Running c-index-test (cursor at #include <s▎, see first screenshot):

c-index-test -code-completion-at=main.cpp:3:12 -stdlib=libc++ main.cpp -ccc-install-dir /usr/lib64/llvm/7/bin -resource-dir /usr/lib/clang/7.0.0

outputs:

Completion contexts:
Unknown
Any type
Any value
Objective-C object value
Objective-C selector value
C++ class type value
Dot member access
Arrow member access
Objective-C property access
Enum tag
Union tag
Struct tag
Class name
Namespace or namespace alias
Nested name specifier
Objective-C interface
Objective-C protocol
Objective-C category
Objective-C instance method
Objective-C class method
Objective-C selector name
Macro name
Natural language

@MaskRay
Copy link
Owner

MaskRay commented Nov 20, 2018

@bfrg #include completion is available in clang 8. The just released clang 7 does not include the feature.

I've added the -stdlib=libstdc++ option and completion works better now, but it still won't list all system include headers.

Check the output of clang -E -v -stdlib=libstdc++ -xc++ /dev/null and https://github.com/llvm-mirror/clang/tree/master/lib/Driver/ToolChains/Linux.cpp

Adding -ccc-install-dir /usr/lib64/llvm/7/bin also helps. I still believe think it is likely a configuration issue. If (very unlikely) that is not the case, use -isystem

You can find relevant -isystem options with clang -fsyntax-only '-###' -stdlib=libstdc++ -xc++ /dev/null

@bfrg
Copy link
Author

bfrg commented Nov 20, 2018

The #include completion isn't so important. I have my own small C preprocessor completion for Vim that works fine. I will just wait until Clang 8 is available on Gentoo Linux.

I have removed libc++ from my system since I don't need it anyway. This is now the output of the preprocessor:

$ clang -E -v -xc++ /dev/null
 /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/g++-v8
 /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/g++-v8/x86_64-pc-linux-gnu
 /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/g++-v8/backward
 /usr/lib64/llvm/7/bin/../../../../lib/clang/7.0.0/include
 /usr/include

The followings works (▎is the cursor position where I start the completion):

#include <vector>

int main()
{
    std::v▎
    std::vector<int> v{1,2,3};
}

ccls will list two candidates:

vector<typename _Tp>   class
vector<typename _Tp, typename _Alloc>   class

But when I start the completion below the vector instantiation:

#include <vector>

int main()
{
    std::vector<int> v{1,2,3};
    std::v▎
}

ccls will list void_t<typename> class as the only completion candidate.

Then, when I go back and try to complete above the line std::vector<int> v{1,2,3}; (as before), the completion menu will list only valarray<typename _Tp> class.
I'm not sure if that's ccls or vim-lsp that is causing this behavior.

@MaskRay
Copy link
Owner

MaskRay commented Nov 20, 2018

You may use strace/sysdig to dump LSP requests/responses
https://github.com/MaskRay/ccls/wiki/Debugging#dump-lsp-requestsresponses

#include <vector>

int main()
{
    std::vector<int> v{1,2,3};
    std::▎  // trigger textDocument/completion manually, is `vector` on the list?
}

@bfrg
Copy link
Author

bfrg commented Nov 21, 2018

I've tried it with VS Code using your ccls extension and everything works fine. So it's definitively the language server client that I'm using (vim-lsp).

Thank you for your help!

@avnotaklu
Copy link

I had gcc 12 installed but did not have libstdc++ for it.
I worked after installing it using
sudo apt install libstdc++-12-dev

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants