diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index edbb1722ae38..55982f41250f 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -486,6 +486,9 @@ private: // we need to complete 'forward<$1>($0)'. return "($0)"; + if (Snippet->empty()) + return ""; + bool MayHaveArgList = Completion.Kind == CompletionItemKind::Function || Completion.Kind == CompletionItemKind::Method || Completion.Kind == CompletionItemKind::Constructor || @@ -524,8 +527,6 @@ private: return *Snippet; // Replace argument snippets with a simplified pattern. - if (Snippet->empty()) - return ""; if (MayHaveArgList) { // Functions snippets can be of 2 types: // - containing only function arguments, e.g. diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 5050ab203b8d..079a4ec70623 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1014,6 +1014,23 @@ TEST(CodeCompleteTest, NoColonColonAtTheEnd) { EXPECT_THAT(Results.Completions, Not(Contains(labeled("clang::")))); } +TEST(CompletionTests, EmptySnippetDoesNotCrash) { + // See https://github.com/clangd/clangd/issues/1216 + auto Results = completions(R"cpp( + int main() { + auto w = [&](auto &&f) { return f(f); }; + auto f = w([&](auto &&f) { + return [&](auto &&n) { + if (n == 0) { + return 1; + } + return n * ^(f)(n - 1); + }; + })(10); + } + )cpp"); +} + TEST(CompletionTest, BacktrackCrashes) { // Sema calls code completion callbacks twice in these cases. auto Results = completions(R"cpp(