Index: clangd/IncludeFixer.cpp =================================================================== --- clangd/IncludeFixer.cpp +++ clangd/IncludeFixer.cpp @@ -192,8 +192,6 @@ if (!SemaPtr->SourceMgr.isWrittenInMainFile(Typo.getLoc())) return clang::TypoCorrection(); - assert(S && "Enclosing scope must be set."); - UnresolvedName Unresolved; Unresolved.Name = Typo.getAsString(); Unresolved.Loc = Typo.getBeginLoc(); @@ -228,6 +226,8 @@ return TypoCorrection(); } } + if (!SpecifiedScope && !S) // Give up if no scope available. + return TypoCorrection(); auto *Sem = SemaPtr; // Avoid capturing `this`. Unresolved.GetScopes = [Sem, SpecifiedScope, S, LookupKind]() { @@ -235,6 +235,7 @@ if (SpecifiedScope) { Scopes.push_back(*SpecifiedScope); } else { + assert(S); // No scope qualifier is specified. Collect all accessible scopes in the // context. VisitedContextCollector Collector; Index: unittests/clangd/DiagnosticsTests.cpp =================================================================== --- unittests/clangd/DiagnosticsTests.cpp +++ unittests/clangd/DiagnosticsTests.cpp @@ -423,6 +423,21 @@ "Add include \"b.h\" for symbol na::nb::X"))))); } +TEST(IncludeFixerTest, NoCrashMemebrAccess) { + Annotations Test(R"cpp( + struct X { int xyz; }; + void g() { X x; x.$[[xy]] } + )cpp"); + auto TU = TestTU::withCode(Test.code()); + auto Index = buildIndexWithSymbol( + SymbolWithHeader{"na::X", "unittest:///a.h", "\"a.h\""}); + TU.ExternalIndex = Index.get(); + + EXPECT_THAT( + TU.build().getDiagnostics(), + UnorderedElementsAre(Diag(Test.range(), "no member named 'xy' in 'X'"))); +} + } // namespace } // namespace clangd } // namespace clang