[clang] 0d1be98 - [clang][USR] Prevent crashes on incomplete FunctionDecls

Kadir Cetinkaya via cfe-commits cfe-commits at lists.llvm.org
Mon May 15 09:12:15 PDT 2023


Author: Kadir Cetinkaya
Date: 2023-05-15T18:05:48+02:00
New Revision: 0d1be98a67e29b70ccfab23d86a2bea13de117d7

URL: https://github.com/llvm/llvm-project/commit/0d1be98a67e29b70ccfab23d86a2bea13de117d7
DIFF: https://github.com/llvm/llvm-project/commit/0d1be98a67e29b70ccfab23d86a2bea13de117d7.diff

LOG: [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

Added: 
    

Modified: 
    clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
    clang/lib/Index/USRGeneration.cpp

Removed: 
    


################################################################################
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 <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

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)


        


More information about the cfe-commits mailing list