From 0d1be98a67e29b70ccfab23d86a2bea13de117d7 Mon Sep 17 00:00:00 2001 From: Kadir Cetinkaya Date: Wed, 3 May 2023 10:50:46 +0200 Subject: [PATCH] [clang][USR] Prevent crashes on incomplete FunctionDecls FunctionDecls can be created with null types (D124351 added such a new code path), to be filled in later. But parsing can stop before completing the Decl (e.g. if code completion point is reached). Unfortunately most of the methods in FunctionDecl and its derived classes assume a complete decl and don't perform null-checks. Since we're not encountring crashes in the wild along other code paths today introducing extra checks into quite a lot of places didn't feel right (due to extra complexity && run time checks). I believe another alternative would be to change Parser & Sema to never create decls with invalid types, but I can't really see an easy way of doing that, as most of the pieces are structured around filling that information as parsing proceeds. Differential Revision: https://reviews.llvm.org/D149733 --- .../clangd/unittests/CodeCompleteTests.cpp | 13 +++++++++++++ clang/lib/Index/USRGeneration.cpp | 5 +++++ 2 files changed, 18 insertions(+) diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 25d6a7b189ed5..1975488fd035a 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -4002,6 +4002,19 @@ TEST(SignatureHelp, TemplateArguments) { EXPECT_EQ(Second.activeParameter, 1); } +TEST(CompletionTest, DoNotCrash) { + llvm::StringLiteral Cases[] = { + R"cpp( + template struct Foo {}; + auto a = [x(3)](Foo<^>){}; + )cpp", + }; + for (auto Case : Cases) { + SCOPED_TRACE(Case); + auto Completions = completions(Case); + } +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp index 06a3717f9ffaf..b10028a526ed5 100644 --- a/clang/lib/Index/USRGeneration.cpp +++ b/clang/lib/Index/USRGeneration.cpp @@ -226,6 +226,11 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) { if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) return; + if (D->getType().isNull()) { + IgnoreResults = true; + return; + } + const unsigned StartSize = Buf.size(); VisitDeclContext(D->getDeclContext()); if (Buf.size() == StartSize)