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

The Inlay hints are repeated when changing the function name #400

Closed
Da-Viper opened this issue Oct 23, 2022 · 15 comments
Closed

The Inlay hints are repeated when changing the function name #400

Da-Viper opened this issue Oct 23, 2022 · 15 comments
Labels
bug Something isn't working

Comments

@Da-Viper
Copy link

Please describe the problem

After changing a function name, the inlay hints currently visible is duplicated. you can keep doing this until clangd crashes

System information
clangd version 14.0.5 (Fedora 14.0.5-1.fc36)
Features: linux
Platform: x86_64-unknown-linux-gnu; target=x86_64-redhat-linux-gnu

Log Info
I[12:31:46.178] clangd version 14.0.5 (Fedora 14.0.5-1.fc36)
I[12:31:46.178] Features: linux
I[12:31:46.178] PID: 692405
I[12:31:46.178] Working directory: /home/da-viper/Dev/playground/topics/learn_sockets/hello_sockets
I[12:31:46.178] argv[0]: /usr/bin/clangd
I[12:31:46.178] argv[1]: --background-index
I[12:31:46.178] argv[2]: --clang-tidy
I[12:31:46.178] argv[3]: --compile-commands-dir=build/
I[12:31:46.178] argv[4]: --enable-config=true
I[12:31:46.178] argv[5]: --header-insertion=never
I[12:31:46.178] argv[6]: --fallback-style=Google
I[12:31:46.178] argv[7]: --log=verbose
V[12:31:46.178] User config file is /home/da-viper/.config/clangd/config.yaml
I[12:31:46.178] Starting LSP over stdin/stdout

Stacktrace

#0 0x00007f6ba39c2975 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/lib64/libLLVM-14.so+0xc0c975)
#1 0x00007f6ba39c2bfb (/lib64/libLLVM-14.so+0xc0cbfb)
#2 0x00007f6ba39c0286 llvm::sys::RunSignalHandlers() (/lib64/libLLVM-14.so+0xc0a286)
#3 0x00007f6ba39c321d (/lib64/libLLVM-14.so+0xc0d21d)
#4 0x00007f6ba28e0a70 __restore_rt (/lib64/libc.so.6+0x3ea70)
#5 0x00007f6ba2930c4c __pthread_kill_implementation (/lib64/libc.so.6+0x8ec4c)
#6 0x00007f6ba28e09c6 gsignal (/lib64/libc.so.6+0x3e9c6)
#7 0x00007f6ba28ca7f4 abort (/lib64/libc.so.6+0x287f4)
#8 0x00007f6ba2c59dd0 __gnu_debug::_Safe_sequence_base::_M_get_mutex() (/lib64/libstdc++.so.6+0xd7dd0)
#9 0x0000560e0efd0abd (/usr/bin/clangd+0x1edabd)
#10 0x0000560e0efd4cf0 (/usr/bin/clangd+0x1f1cf0)
#11 0x0000560e0efd599f (/usr/bin/clangd+0x1f299f)
#12 0x00007f6baa4ab179 (/lib64/libclang-cpp.so.14+0x118b179)
#13 0x00007f6baa4e850f clang::Sema::CodeCompleteAfterIf(clang::Scope*, bool) (/lib64/libclang-cpp.so.14+0x11c850f)
#14 0x00007f6ba9dc25b1 clang::Parser::ParseIfStatement(clang::SourceLocation*) (/lib64/libclang-cpp.so.14+0xaa25b1)
#15 0x00007f6ba9db9963 clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector<clang::Stmt*, 32u>&, clang::Parser::ParsedStmtContext, clang::SourceLocation*, clang::ParsedAttributesWithRange&) (/lib64/libclang-cpp.so.14+0xa99963)
#16 0x00007f6ba9dba793 clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector<clang::Stmt*, 32u>&, clang::Parser::ParsedStmtContext, clang::SourceLocation*) (/lib64/libclang-cpp.so.14+0xa9a793)
#17 0x00007f6ba9dbb553 clang::Parser::ParseCompoundStatementBody(bool) (/lib64/libclang-cpp.so.14+0xa9b553)
#18 0x00007f6ba9dbe73a clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) (/lib64/libclang-cpp.so.14+0xa9e73a)
#19 0x00007f6ba9de7213 clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::LateParsedAttrList*) (/lib64/libclang-cpp.so.14+0xac7213)
#20 0x00007f6ba9d3681b clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/lib64/libclang-cpp.so.14+0xa1681b)
#21 0x00007f6ba9de1ec9 (/lib64/libclang-cpp.so.14+0xac1ec9)
#22 0x00007f6ba9de8aec clang::Parser::ParseExternalDeclaration(clang::ParsedAttributesWithRange&, clang::ParsingDeclSpec*) (/lib64/libclang-cpp.so.14+0xac8aec)
#23 0x00007f6ba9de9218 clang::Parser::ParseTopLevelDecl(clang::OpaquePtrclang::DeclGroupRef&, bool) (/lib64/libclang-cpp.so.14+0xac9218)
#24 0x00007f6ba9d12481 clang::ParseAST(clang::Sema&, bool, bool) (/lib64/libclang-cpp.so.14+0x9f2481)
#25 0x00007f6bab6015f9 clang::FrontendAction::Execute() (/lib64/libclang-cpp.so.14+0x22e15f9)
#26 0x0000560e0efc59a2 (/usr/bin/clangd+0x1e29a2)
#27 0x0000560e0efd37b7 (/usr/bin/clangd+0x1f07b7)
#28 0x0000560e0efb1db8 (/usr/bin/clangd+0x1cedb8)
#29 0x0000560e0efb2438 (/usr/bin/clangd+0x1cf438)
#30 0x0000560e0f14e4fd (/usr/bin/clangd+0x36b4fd)
#31 0x0000560e0f2e4d46 (/usr/bin/clangd+0x501d46)
#32 0x00007f6ba292ee2d start_thread (/lib64/libc.so.6+0x8ce2d)
#33 0x00007f6ba29b41b0 __GI___clone3 (/lib64/libc.so.6+0x1121b0)
Signalled during preamble action: CodeComplete
Filename: server.c
Directory: /home/da-viper/Dev/playground/topics/learn_sockets/hello_sockets
Command Line: /usr/bin/clang -Wno-unused-variable -Wno-infinite-recursion -Werror=implicit-function-declaration -Wshadow -Wno-shadow-field-in-constructor-modified -Wno-shadow-ivar -Wuninitialized -Wunused-label -Wunused-lambda-capture -resource-dir=/usr/lib64/clang/14.0.5 -- /home/da-viper/Dev/playground/topics/learn_sockets/hello_sockets/server.c
[Error - 12:32:25] The Clang Language Server server crashed 5 times in the last 3 minutes. The server will not be restarted. See the output for more information.
[Error - 12:32:25] Request textDocument/completion failed.
[object Object]
[Error - 12:32:25] Request textDocument/completion failed.
[object Object]
[Error - 12:32:25] Request textDocument/codeAction failed.
[object Object]
[Error - 12:32:25] Request textDocument/documentSymbol failed.
[object Object]

@Da-Viper Da-Viper added the bug Something isn't working label Oct 23, 2022
@sam-mccall
Copy link
Member

There are two separate problems here:

  • the crash stack trace is in code completion, near an if statement. This just depends on the code and cursor position, not the rename operations. If you can identify the code that crashes, we can investigate. (Please file against clangd/clangd rather than this repo if so)

  • the duplicated hints after rename. This sounds likely to be a client-side bug. Is this reproducible on a trivial example? This one works for me, renaming f to g.

int f(int x);
int y = f(0);

If not, again please post a minimal example showing the problem.

@Da-Viper
Copy link
Author

It this the case that it crashes with the example above

int foo(int x);

int main() {
    int res = foo(0);
}

for completeness swapping function call foo with anything and back to foo triggers the issue .

I tested it with manual rename ie. removing the letters and typing the new one

stack trace

#0 0x00007fef9e712975 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/lib64/libLLVM-14.so+0xc0c975)
#1 0x00007fef9e712bfb (/lib64/libLLVM-14.so+0xc0cbfb)
#2 0x00007fef9e710286 llvm::sys::RunSignalHandlers() (/lib64/libLLVM-14.so+0xc0a286)
#3 0x00007fef9e71321d (/lib64/libLLVM-14.so+0xc0d21d)
#4 0x00007fef9d630a70 __restore_rt (/lib64/libc.so.6+0x3ea70)
#5 0x00007fef9d680c4c __pthread_kill_implementation (/lib64/libc.so.6+0x8ec4c)
#6 0x00007fef9d6309c6 gsignal (/lib64/libc.so.6+0x3e9c6)
#7 0x00007fef9d61a7f4 abort (/lib64/libc.so.6+0x287f4)
#8 0x00007fef9d9a9dd0 __gnu_debug::_Safe_sequence_base::_M_get_mutex() (/lib64/libstdc++.so.6+0xd7dd0)
#9 0x000056553973fabd (/usr/bin/clangd+0x1edabd)
#10 0x0000565539743cf0 (/usr/bin/clangd+0x1f1cf0)
#11 0x000056553974499f (/usr/bin/clangd+0x1f299f)
#12 0x00007fefa51fb179 (/lib64/libclang-cpp.so.14+0x118b179)
#13 0x00007fefa5234e0c clang::Sema::CodeCompleteExpression(clang::Scope*, clang::Sema::CodeCompleteExpressionData const&) (/lib64/libclang-cpp.so.14+0x11c4e0c)
#14 0x00007fefa52359d4 clang::Sema::CodeCompleteInitializer(clang::Scope*, clang::Decl*) (/lib64/libclang-cpp.so.14+0x11c59d4)
#15 0x00007fefa4a76c3d clang::Parser::ParseDeclarationAfterDeclaratorAndAttributes(clang::Declarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::ForRangeInit*) (/lib64/libclang-cpp.so.14+0xa06c3d)
#16 0x00007fefa4a8636d clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/lib64/libclang-cpp.so.14+0xa1636d)
#17 0x00007fefa4a870fa clang::Parser::ParseSimpleDeclaration(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributesWithRange&, bool, clang::Parser::ForRangeInit*, clang::SourceLocation*) (/lib64/libclang-cpp.so.14+0xa170fa)
#18 0x00007fefa4a8752b clang::Parser::ParseDeclaration(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributesWithRange&, clang::SourceLocation*) (/lib64/libclang-cpp.so.14+0xa1752b)
#19 0x00007fefa4b09f67 clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector<clang::Stmt*, 32u>&, clang::Parser::ParsedStmtContext, clang::SourceLocation*, clang::ParsedAttributesWithRange&) (/lib64/libclang-cpp.so.14+0xa99f67)
#20 0x00007fefa4b0a793 clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector<clang::Stmt*, 32u>&, clang::Parser::ParsedStmtContext, clang::SourceLocation*) (/lib64/libclang-cpp.so.14+0xa9a793)
#21 0x00007fefa4b0b553 clang::Parser::ParseCompoundStatementBody(bool) (/lib64/libclang-cpp.so.14+0xa9b553)
#22 0x00007fefa4b0e73a clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) (/lib64/libclang-cpp.so.14+0xa9e73a)
#23 0x00007fefa4b37213 clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::LateParsedAttrList*) (/lib64/libclang-cpp.so.14+0xac7213)
#24 0x00007fefa4a8681b clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/lib64/libclang-cpp.so.14+0xa1681b)
#25 0x00007fefa4b31ec9 (/lib64/libclang-cpp.so.14+0xac1ec9)
#26 0x00007fefa4b38aec clang::Parser::ParseExternalDeclaration(clang::ParsedAttributesWithRange&, clang::ParsingDeclSpec*) (/lib64/libclang-cpp.so.14+0xac8aec)
#27 0x00007fefa4b39218 clang::Parser::ParseTopLevelDecl(clang::OpaquePtrclang::DeclGroupRef&, bool) (/lib64/libclang-cpp.so.14+0xac9218)
#28 0x00007fefa4a62481 clang::ParseAST(clang::Sema&, bool, bool) (/lib64/libclang-cpp.so.14+0x9f2481)
#29 0x00007fefa63515f9 clang::FrontendAction::Execute() (/lib64/libclang-cpp.so.14+0x22e15f9)
#30 0x00005655397349a2 (/usr/bin/clangd+0x1e29a2)
#31 0x00005655397427b7 (/usr/bin/clangd+0x1f07b7)
#32 0x0000565539720db8 (/usr/bin/clangd+0x1cedb8)
#33 0x0000565539721438 (/usr/bin/clangd+0x1cf438)
#34 0x00005655398bd4fd (/usr/bin/clangd+0x36b4fd)
#35 0x0000565539a53d46 (/usr/bin/clangd+0x501d46)
#36 0x00007fef9d67ee2d start_thread (/lib64/libc.so.6+0x8ce2d)
#37 0x00007fef9d7041b0 __GI___clone3 (/lib64/libc.so.6+0x1121b0)
Signalled during preamble action: CodeComplete
Filename: test.c
Directory: /home/da-viper/Dev/playground/topics/learn_sockets/hello_sockets
Command Line: /usr/bin/clang -Wno-unused-variable -Wno-infinite-recursion -Werror=implicit-function-declaration -Wshadow -Wno-shadow-field-in-constructor-modified -Wno-shadow-ivar -Wuninitialized -Wunused-label -Wunused-lambda-capture -resource-dir=/usr/lib64/clang/14.0.5 -- /home/da-viper/Dev/playground/topics/learn_sockets/hello_sockets/test.c
[Error - 13:22:49] The Clang Language Server server crashed 5 times in the last 3 minutes. The server will not be restarted. See the output for more information.
[Error - 13:22:49] Request textDocument/completion failed.
[object Object]

from code complete expression

@sam-mccall
Copy link
Member

There are two possibilities here:

  • there's a code completion bug (unrelated to rename), and a separate issue that causes duplicate inlay hints (related to rename)
  • there's a code completion bug (unrelated to rename), and the resulting crash causes the issue with duplicate inlay hints

Either way, we need precise steps to reproduce this, not just "change foo to anything and back" (at least I can't get that to crash).

Can you please provide complete logs from a minimal crashing session (with -log=verbose, not just the top of the log, not just the stack trace)? That way it's possible to see

@Da-Viper
Copy link
Author

Maybe I am not explaining it the right way but

I made a short video of the issue
https://youtu.be/yi2KalF2lZw

here is the full log attached.
log-clangd.txt

@sam-mccall
Copy link
Member

Sorry, I get it now - somehow I fixated on "changing the function name" == rename when in fact we're just making the call match/unmatch.

I wonder whether the vim plugin is related here: in the past I've seen different behavior in vscode-languageclient based on the different sequence of events produced when editing with this plugin enabled.

The video is helpful, I can't reproduce though (even when using the vim plugin).

I'll dig into the log...

@sam-mccall
Copy link
Member

First observation is that there are 5 crashes in the log, which very likely corresponds to the duplication we're seeing. My guess is that vscode-languageclient isn't cleaning up the inlay hints when it restarts the server. So if we fix the completion crash that should address all symptoms.

(It would be nice if vscode-languageclient was more robust against crashes though).

@sam-mccall
Copy link
Member

sam-mccall commented Oct 23, 2022

I reduced the critical sequence to log-clangd-trimmed.txt

I can't get it to crash on my machine, either at head or with our released 14.0.3 binary (we didn't cut one for 14.0.5 and none of the few changes look relevant).

Can you confirm that clangd -sync -input-style=delimited < log-clangd-trimmed.txt crashes with a stack trace?
If so, does the crash go away when using our binary releases?

My best guess at this point is there's a problem specific to the fedora packages, either locally applied changes or an issue with the compiler they're building them with.
EDIT: or of course latent UB in clang that crashes only when build with that toolchain.

@sam-mccall
Copy link
Member

(note to self: I thought this was a clang parsing/completion bug but there are clangd frames on top of the stack, they're just not symbolized. It looks like libclang-cpp.so has symbols, but fedora's clangd binary itself is stripped :-()

@sam-mccall
Copy link
Member

I think I found it!

From the trace, we can see _Safe_sequence_base, which is part of libstdc++ debug checks, related to checking bounds/iterator access. (Surprising to me, as this carries performance implications)
This explains why we'd only see this issue on fedora, if some out-of-bounds access is "otherwise harmless" in practice.

Running the reproducer insider fedora 36 in docker, I see the assertion message:

/usr/include/c++/12/bits/basic_string.h:1292: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::const_reference std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::front() const [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; const_reference = const char&]: Assertion '!empty()' failed.

Putting these together, and looking at front() calls on std::string in CodeComplete.cpp (which is where libclang-cpp calls back into clangd), we see things like:

        if (Snippet->front() == '<') {

with no obvious reason that Snippet is nonempty.
front() on an empty string is not allowed, but without debug checks, Snippet->front() is equivalent to Snippet[0] which is totally fine (strings are guaranteed to be backed by a null-terminated char array).

So we do have latent UB here, and these binaries really go looking for it.

@sam-mccall
Copy link
Member

I'm going to fix this upstream, but it won't retroactively fix the fedora packages.

As a workaround I suggest you use our release binaries from github (which aren't built with libstdc++ debug iterators) or check if other available versions have the same issue.

Once I check in a fix I'll file a bug with fedora to see if they'll fix this somehow.

@sam-mccall
Copy link
Member

Ah, this was already fixed by @tom-anders in llvm/llvm-project@60528c6 for #1216 (thanks tom!)

@sam-mccall
Copy link
Member

There is already a relevant fedora bug for this: https://bugzilla.redhat.com/show_bug.cgi?id=2097457

I added a comment at the end (though I fear it getting lost in automated bugmail).
@tstellar: the fedora36 packaged clangd 14 is (probably unusably) crashy due to a clangd bug that shows up with debug libstd++. The fix will arrive with LLVM 16, you might consider backporting llvm/llvm-project@60528c6 until then. Let me know if I can help!

@Da-Viper
Copy link
Author

Sorry for the late reply, it is the case that this bug only applies to fedora,

I downloaded the clangd binary and it works ok

Thanks

@HighCommander4
Copy link
Contributor

@sam-mccall looks like there will be a 15.0.4 release, should we try and get the fix into that?

@sam-mccall
Copy link
Member

@HighCommander4 nice catch, thanks! Filed llvm/llvm-project#58574

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants