kadircet created this revision. kadircet added reviewers: aaron.ballman, ilya-biryukov. Herald added a subscriber: arphaman. Herald added a project: All. kadircet requested review of this revision. Herald added projects: clang, clang-tools-extra. Herald added a subscriber: cfe-commits.
FunctionDecls can be created with null types (D124351 <https://reviews.llvm.org/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. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D149733 Files: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp clang/lib/Index/USRGeneration.cpp Index: clang/lib/Index/USRGeneration.cpp =================================================================== --- clang/lib/Index/USRGeneration.cpp +++ clang/lib/Index/USRGeneration.cpp @@ -226,6 +226,11 @@ 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) Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -4002,6 +4002,19 @@ EXPECT_EQ(Second.activeParameter, 1); } +TEST(CompletionTest, DoNotCrash) { + llvm::StringLiteral Cases[] = { + R"cpp( + template <typename = int> struct Foo {}; + auto a = [x(3)](Foo<^>){}; + )cpp", + }; + for (auto Case : Cases) { + SCOPED_TRACE(Case); + auto Completions = completions(Case); + } +} + } // namespace } // namespace clangd } // namespace clang
Index: clang/lib/Index/USRGeneration.cpp =================================================================== --- clang/lib/Index/USRGeneration.cpp +++ clang/lib/Index/USRGeneration.cpp @@ -226,6 +226,11 @@ 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) Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -4002,6 +4002,19 @@ EXPECT_EQ(Second.activeParameter, 1); } +TEST(CompletionTest, DoNotCrash) { + llvm::StringLiteral Cases[] = { + R"cpp( + template <typename = int> struct Foo {}; + auto a = [x(3)](Foo<^>){}; + )cpp", + }; + for (auto Case : Cases) { + SCOPED_TRACE(Case); + auto Completions = completions(Case); + } +} + } // namespace } // namespace clangd } // namespace clang
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits