This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Try harder to find a plausible `clang` as argv0, particularly on Mac.
ClosedPublic

Authored by sammccall on Nov 29 2019, 10:39 AM.

Details

Summary

Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178

No tests - this is hard to test, and basically impossible to verify what we want
(this produces compile commands that work on a real mac with recent toolchain)

(Need someone on mac to verify it actually fixes these!)

Diff Detail

Event Timeline

sammccall created this revision.Nov 29 2019, 10:39 AM
ilya-biryukov accepted this revision.Dec 2 2019, 12:38 AM

The code LG, but my mac is at home, so I could not verify it.
@kbobyrev, would you mind running this on your machine?

clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
266

NIT: maybe add braces to the for statement?

This revision is now accepted and ready to land.Dec 2 2019, 12:38 AM
kadircet added inline comments.Dec 2 2019, 12:45 AM
clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
266

did you mean "cc" instead of "ccc"? or is that really a think ?

Another interesting consideration: we choose to ask users to whitelists compilers we might run from compile_commands.json that we can.
We are in a better position here, since we're not running the binaries based on user input.

Technically, we could consider using the same mechanism for running xcrun. It will probably never be used in practice, though (and we'll have to whitelist some common xcrun binaries anyway).

The current version of the patch fixes one of the related issues. When running on a simple file like this

#include <iostream>

int main() {
        std::cout << "Hello, world" << std::endl;
        return 0;
}

Clangd would fail to find iostream header and produce errors for std::cout and std::endl which are also not found before the patch. After the patch, this is no longer an issue. Hence, I believe that standard library headers can be identified correctly now.

However, after the patch wchar.h from #include_next is not found and this produces another error. wchar.h there is AFAIK not a part of the standard library and should be found in the SDKROOT.

The following is a log of Clangd failing to find wchar.h:

kbobyrev$ ./bin/clangd -sync < /tmp/mirror                                                                                                                                    
clangd is a language server that provides IDE-like features to editors.

It should be used via an editor plugin rather than invoked directly. For more information, see:
        https://clang.llvm.org/extra/clangd/
        https://microsoft.github.io/language-server-protocol/

clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment variable.

I[11:18:01.774] clangd version 10.0.0 (https://github.com/llvm/llvm-project bd23859f390aa81ddb1bf0b16684cce50ad9d66d)                                                                                          
I[11:18:01.775] PID: 92552
I[11:18:01.775] Working directory: /Users/kbobyrev/dev/build/llvm-release
I[11:18:01.775] argv[0]: ./bin/clangd
I[11:18:01.775] argv[1]: -sync
I[11:18:01.775] Starting LSP over stdin/stdout
I[11:18:01.776] <-- initialize(0)
I[11:18:01.776] --> reply:initialize(0) 0 ms
Content-Length: 800

{"id":0,"jsonrpc":"2.0","result":{"capabilities":{"codeActionProvider":{"codeActionKinds":["quickfix","refactor","info"]},"completionProvider":{"resolveProvider":false,"triggerCharacters":[".",">",":"]},"declarationProvider":true,"definitionProvider":true,"documentFormattingProvider":true,"documentHighlightProvider":true,"documentOnTypeFormattingProvider":{"firstTriggerCharacter":"\n","moreTriggerCharacter":[]},"documentRangeFormattingProvider":true,"documentSymbolProvider":true,"executeCommandProvider":{"commands":["clangd.applyFix","clangd.applyTweak"]},"hoverProvider":true,"referencesProvider":true,"renameProvider":true,"selectionRangeProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",","]},"textDocumentSync":2,"typeHierarchyProvider":true,"workspaceSymbolProvider":true}}}I[11:18:01.776] <-- textDocument/didOpen
I[11:18:01.789] Failed to find compilation database for /private/tmp/test.cpp
I[11:18:01.789] Updating file /private/tmp/test.cpp with command clangd fallback
[/private/tmp]
/Library/Developer/CommandLineTools/usr/bin/clang /private/tmp/test.cpp -fsyntax-only -resource-dir=/Users/kbobyrev/dev/build/llvm-release/lib/clang/10.0.0                                                    
I[11:18:02.155] --> textDocument/publishDiagnostics
Content-Length: 819

{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"diagnostics":[{"code":"pp_file_not_found","message":"In included file: 'wchar.h' file not found","range":{"end":{"character":10,"line":0},"start":{"character":9,"line":0}},"relatedInformation":[{"location":{"range":{"end":{"character":23,"line":118},"start":{"character":14,"line":118}},"uri":"file:///Library/Developer/CommandLineTools/usr/include/c%2B%2B/v1/wchar.h"},"message":"Error occurred here"}],"severity":1,"source":"clang"},{"code":"typecheck_invalid_operands","message":"Invalid operands to binary expression ('std::__1::ostream' (aka 'int') and 'const char [13]')","range":{"end":{"character":13,"line":3},"start":{"character":11,"line":3}},"relatedInformation":[],"severity":1,"source":"clang"}],"uri":"file:///private/tmp/test.cpp"}}I[11:18:02.155] Warning: Missing Content-Length header, or zero-length message.
E[11:18:02.155] Transport error: Input/output error
I[11:18:02.155] LSP finished, exiting with status 1

This can be fixed manually by appending env SDKROOT=$(xcrun --show-sdk-path) to the clangd invocation (or simply defining the environment variable for all invocations), but I believe we might want to deal with it on the Clangd side, too.

sammccall planned changes to this revision.Dec 2 2019, 2:23 AM

@kbobyrev tested this and it turns out we also have to set $SDKROOT. And we probably want to fix clang in compile_commands.json too.

Another interesting consideration: we choose to ask users to whitelists compilers we might run from compile_commands.json that we can.
We are in a better position here, since we're not running the binaries based on user input.

Interesting idea. Wouldn't mix it with this patch as the purposes don't overlap much...

  • apple clang in practice won't report the required info to the driver query until the next major xcode release I think (with your driver patch)
  • the motivating case for this patch is the fallback compile command

Technically, we could consider using the same mechanism for running xcrun. It will probably never be used in practice, though (and we'll have to whitelist some common xcrun binaries anyway).

You mean the whitelist? The security risk we were worried about with --query_driver is that compile_commands.json is easily attacker-controlled. The string xcrun is fixed, and the attack "put a different xcrun on the user's PATH" requires way more privileges - generally you're owned at that point anyway. I don't think it's worth guarding.

sammccall updated this revision to Diff 231674.Dec 2 2019, 4:32 AM

Also add detected -isysroot on mac unless $SDKROOT is set.
Also add path to driver when bare driver name comes from CDB.
While here, address -resource-dir fixme.

This revision is now accepted and ready to land.Dec 2 2019, 4:32 AM

@kbobyrev would you mind testing this again?

Dropping an empty compile_flags.txt should also work (and test the other codepath)

kbobyrev accepted this revision.Dec 2 2019, 5:41 AM

@kbobyrev would you mind testing this again?

Dropping an empty compile_flags.txt should also work (and test the other codepath)

I've tested again (and also with empty compile_flags.txt) and this works now.

@kbobyrev would you mind testing this again?

Dropping an empty compile_flags.txt should also work (and test the other codepath)

I've tested again (and also with empty compile_flags.txt) and this works now.

Woohoo, thanks!

This revision was automatically updated to reflect the committed changes.

@sammccall Sam, it looks like the tests are failing on the darwin bots:

http://lab.llvm.org:8080/green/job/clang-stage1-RA/4243/consoleFull

Value of: CDB.getFallbackCommand(testPath("bar.cc")).CommandLine
Expected: has 6 elements where
element #0 ends with "clang",
element #1 is equal to "-DA=2",
element #2 is equal to "/clangd-test/bar.cc",
element #3 is equal to "-DA=4",
element #4 is equal to "-fsyntax-only",
element #5 starts with "-resource-dir"
  Actual: { "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-DA=2", "/clangd-test/bar.cc", "-DA=4", "-fsyntax-only", "-resource-dir=/Users/buildslave/jenkins/workspace/clang-stage1-RA/clang-build/tools/clang/tools/extra/clangd/lib/clang/10.0.0", "-isysroot", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" }, which has 8 elements

Can you please take a look?

@sammccall Sam, it looks like the tests are failing on the darwin bots:

http://lab.llvm.org:8080/green/job/clang-stage1-RA/4243/consoleFull

Thanks, and sorry! Fingers crossed that 82039cbc8d2a0f6fb5995f54e0e42919999bcfd0 will fix it...