diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -271,9 +271,13 @@ if (!IP) return CB(IP.takeError()); - auto PreambleData = IP->Preamble; - CB(clangd::signatureHelp(File, IP->Command, PreambleData, IP->Contents, Pos, - FS, Index)); + const auto *PreambleData = IP->Preamble; + if (!PreambleData) + return CB(llvm::createStringError(llvm::inconvertibleErrorCode(), + "Failed to parse includes")); + + CB(clangd::signatureHelp(File, IP->Command, *PreambleData, IP->Contents, + Pos, FS, Index)); }; // Unlike code completion, we wait for an up-to-date preamble here. diff --git a/clang-tools-extra/clangd/CodeComplete.h b/clang-tools-extra/clangd/CodeComplete.h --- a/clang-tools-extra/clangd/CodeComplete.h +++ b/clang-tools-extra/clangd/CodeComplete.h @@ -276,7 +276,7 @@ /// Get signature help at a specified \p Pos in \p FileName. SignatureHelp signatureHelp(PathRef FileName, const tooling::CompileCommand &Command, - const PreambleData *Preamble, StringRef Contents, + const PreambleData &Preamble, StringRef Contents, Position Pos, IntrusiveRefCntPtr VFS, const SymbolIndex *Index); diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -1022,7 +1022,7 @@ struct SemaCompleteInput { PathRef FileName; const tooling::CompileCommand &Command; - const PreambleData *Preamble; + const PreambleData &Preamble; llvm::StringRef Contents; size_t Offset; llvm::IntrusiveRefCntPtr VFS; @@ -1054,8 +1054,8 @@ IncludeStructure *Includes = nullptr) { trace::Span Tracer("Sema completion"); llvm::IntrusiveRefCntPtr VFS = Input.VFS; - if (Input.Preamble && Input.Preamble->StatCache) - VFS = Input.Preamble->StatCache->getConsumingFS(std::move(VFS)); + if (Input.Preamble.StatCache) + VFS = Input.Preamble.StatCache->getConsumingFS(std::move(VFS)); ParseInputs ParseInput; ParseInput.CompileCommand = Input.Command; ParseInput.FS = VFS; @@ -1099,9 +1099,7 @@ // NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise // the remapped buffers do not get freed. auto Clang = prepareCompilerInstance( - std::move(CI), - (Input.Preamble && !CompletingInPreamble) ? &Input.Preamble->Preamble - : nullptr, + std::move(CI), !CompletingInPreamble ? &Input.Preamble.Preamble : nullptr, std::move(ContentsBuffer), std::move(VFS), IgnoreDiags); Clang->getPreprocessorOpts().SingleFileParseMode = CompletingInPreamble; Clang->setCodeCompletionConsumer(Consumer.release()); @@ -1118,8 +1116,7 @@ // - but Sema code complete won't see them: as part of the preamble, they're // deserialized only when mentioned. // Force them to be deserialized so SemaCodeComplete sees them. - if (Input.Preamble) - loadMainFilePreambleMacros(Clang->getPreprocessor(), *Input.Preamble); + loadMainFilePreambleMacros(Clang->getPreprocessor(), Input.Preamble); if (Includes) Clang->getPreprocessor().addPPCallbacks( collectIncludeStructureCallback(Clang->getSourceManager(), Includes)); @@ -1758,12 +1755,12 @@ return (!Preamble || Opts.RunParser == CodeCompleteOptions::NeverParse) ? std::move(Flow).runWithoutSema(Contents, *Offset, VFS) : std::move(Flow).run( - {FileName, Command, Preamble, Contents, *Offset, VFS}); + {FileName, Command, *Preamble, Contents, *Offset, VFS}); } SignatureHelp signatureHelp(PathRef FileName, const tooling::CompileCommand &Command, - const PreambleData *Preamble, + const PreambleData &Preamble, llvm::StringRef Contents, Position Pos, llvm::IntrusiveRefCntPtr VFS, const SymbolIndex *Index) { diff --git a/clang-tools-extra/clangd/unittests/ClangdTests.cpp b/clang-tools-extra/clangd/unittests/ClangdTests.cpp --- a/clang-tools-extra/clangd/unittests/ClangdTests.cpp +++ b/clang-tools-extra/clangd/unittests/ClangdTests.cpp @@ -552,15 +552,13 @@ EXPECT_ERROR(runFindDocumentHighlights(Server, FooCpp, Position())); EXPECT_ERROR(runRename(Server, FooCpp, Position(), "new_name", clangd::RenameOptions())); + EXPECT_ERROR(runSignatureHelp(Server, FooCpp, Position())); // Identifier-based fallback completion. EXPECT_THAT(cantFail(runCodeComplete(Server, FooCpp, Position(), clangd::CodeCompleteOptions())) .Completions, ElementsAre(Field(&CodeCompletion::Name, "int"), Field(&CodeCompletion::Name, "main"))); - auto SigHelp = runSignatureHelp(Server, FooCpp, Position()); - ASSERT_TRUE(bool(SigHelp)) << "signatureHelp returned an error"; - EXPECT_THAT(SigHelp->signatures, IsEmpty()); } class ClangdThreadingTest : public ClangdVFSTest {}; diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1049,8 +1049,12 @@ auto Preamble = buildPreamble(testPath(TU.Filename), *CI, /*OldPreamble=*/nullptr, Inputs, /*InMemory=*/true, /*Callback=*/nullptr); - return signatureHelp(testPath(TU.Filename), Inputs.CompileCommand, - Preamble.get(), Text, Point, Inputs.FS, Index.get()); + if (!Preamble) { + ADD_FAILURE() << "Couldn't build Preamble"; + return {}; + } + return signatureHelp(testPath(TU.Filename), Inputs.CompileCommand, *Preamble, + Text, Point, Inputs.FS, Index.get()); } SignatureHelp signatures(llvm::StringRef Text,