diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -646,9 +646,7 @@ const DidOpenTextDocumentParams &Params) { PathRef File = Params.textDocument.uri.file(); - const std::string &Contents = Params.textDocument.text; - - Server->addDocument(File, Contents, + Server->addDocument(File, Params.textDocument.text, encodeVersion(Params.textDocument.version), WantDiagnostics::Yes); } @@ -677,8 +675,9 @@ return; } } - Server->addDocument(File, NewCode, encodeVersion(Params.textDocument.version), - WantDiags, Params.forceRebuild); + Server->addDocument(File, std::move(NewCode), + encodeVersion(Params.textDocument.version), WantDiags, + Params.forceRebuild); } void ClangdLSPServer::onDocumentDidSave( 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 @@ -211,16 +211,17 @@ } } -void ClangdServer::addDocument(PathRef File, llvm::StringRef Contents, +void ClangdServer::addDocument(PathRef File, StringRef Contents, llvm::StringRef Version, WantDiagnostics WantDiags, bool ForceRebuild) { - std::string ActualVersion = DraftMgr.addDraft(File, Version, Contents); + auto RefContents = std::make_shared(Contents); + std::string ActualVersion = DraftMgr.addDraft(File, Version, RefContents); ParseOptions Opts; // Compile command is set asynchronously during update, as it can be slow. ParseInputs Inputs; Inputs.TFS = &TFS; - Inputs.Contents = std::string(Contents); + Inputs.Contents = std::move(RefContents); Inputs.Version = std::move(ActualVersion); Inputs.ForceRebuild = ForceRebuild; Inputs.Opts = std::move(Opts); @@ -358,7 +359,7 @@ SpecFuzzyFind->CachedReq = CachedCompletionFuzzyFindRequestByFile[File]; } } - ParseInputs ParseInput{IP->Command, &TFS, IP->Contents.str()}; + ParseInputs ParseInput{IP->Command, &TFS, IP->Contents}; ParseInput.Index = Index; CodeCompleteOpts.MainFileSignals = IP->Signals; @@ -403,7 +404,7 @@ if (!PreambleData) return CB(error("Failed to parse includes")); - ParseInputs ParseInput{IP->Command, &TFS, IP->Contents.str()}; + ParseInputs ParseInput{IP->Command, &TFS, IP->Contents}; ParseInput.Index = Index; CB(clangd::signatureHelp(File, Pos, *PreambleData, ParseInput)); }; @@ -522,7 +523,7 @@ return CB(R.takeError()); if (Opts.WantFormat) { - auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents, + auto Style = getFormatStyleForFile(File, *InpAST->Inputs.Contents, *InpAST->Inputs.TFS); llvm::Error Err = llvm::Error::success(); for (auto &E : R->GlobalChanges) @@ -542,10 +543,10 @@ // vector of pointers because GCC doesn't like non-copyable Selection. static llvm::Expected>> tweakSelection(const Range &Sel, const InputsAndAST &AST) { - auto Begin = positionToOffset(AST.Inputs.Contents, Sel.start); + auto Begin = positionToOffset(*AST.Inputs.Contents, Sel.start); if (!Begin) return Begin.takeError(); - auto End = positionToOffset(AST.Inputs.Contents, Sel.end); + auto End = positionToOffset(*AST.Inputs.Contents, Sel.end); if (!End) return End.takeError(); std::vector> Result; @@ -693,7 +694,7 @@ if (!InpAST) return CB(InpAST.takeError()); format::FormatStyle Style = getFormatStyleForFile( - File, InpAST->Inputs.Contents, *InpAST->Inputs.TFS); + File, *InpAST->Inputs.Contents, *InpAST->Inputs.TFS); CB(clangd::getHover(InpAST->AST, Pos, std::move(Style), Index)); }; @@ -871,11 +872,11 @@ if (!Inputs) return CB(Inputs.takeError()); unsigned Start, End; - if (auto Offset = positionToOffset(Inputs->Inputs.Contents, R.start)) + if (auto Offset = positionToOffset(*Inputs->Inputs.Contents, R.start)) Start = *Offset; else return CB(Offset.takeError()); - if (auto Offset = positionToOffset(Inputs->Inputs.Contents, R.end)) + if (auto Offset = positionToOffset(*Inputs->Inputs.Contents, R.end)) End = *Offset; else return CB(Offset.takeError()); 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 @@ -1142,10 +1142,10 @@ FrontendOpts.CodeCompletionAt.FileName = std::string(Input.FileName); std::tie(FrontendOpts.CodeCompletionAt.Line, FrontendOpts.CodeCompletionAt.Column) = - offsetToClangLineColumn(Input.ParseInput.Contents, Input.Offset); + offsetToClangLineColumn(*Input.ParseInput.Contents, Input.Offset); std::unique_ptr ContentsBuffer = - llvm::MemoryBuffer::getMemBuffer(Input.ParseInput.Contents, + llvm::MemoryBuffer::getMemBuffer(*Input.ParseInput.Contents, Input.FileName); // The diagnostic options must be set before creating a CompilerInstance. CI->getDiagnosticOpts().IgnoreWarnings = true; @@ -1323,9 +1323,9 @@ CodeCompleteResult run(const SemaCompleteInput &SemaCCInput) && { trace::Span Tracer("CodeCompleteFlow"); - HeuristicPrefix = guessCompletionPrefix(SemaCCInput.ParseInput.Contents, + HeuristicPrefix = guessCompletionPrefix(*SemaCCInput.ParseInput.Contents, SemaCCInput.Offset); - populateContextWords(SemaCCInput.ParseInput.Contents); + populateContextWords(*SemaCCInput.ParseInput.Contents); if (Opts.Index && SpecFuzzyFind && SpecFuzzyFind->CachedReq.hasValue()) { assert(!SpecFuzzyFind->Result.valid()); SpecReq = speculativeFuzzyFindRequestForCompletion( @@ -1342,7 +1342,7 @@ CCContextKind = Recorder->CCContext.getKind(); IsUsingDeclaration = Recorder->CCContext.isUsingDeclaration(); auto Style = getFormatStyleForFile(SemaCCInput.FileName, - SemaCCInput.ParseInput.Contents, + *SemaCCInput.ParseInput.Contents, *SemaCCInput.ParseInput.TFS); const auto NextToken = Lexer::findNextToken( Recorder->CCSema->getPreprocessor().getCodeCompletionLoc(), @@ -1352,7 +1352,7 @@ // If preprocessor was run, inclusions from preprocessor callback should // already be added to Includes. Inserter.emplace( - SemaCCInput.FileName, SemaCCInput.ParseInput.Contents, Style, + SemaCCInput.FileName, *SemaCCInput.ParseInput.Contents, Style, SemaCCInput.ParseInput.CompileCommand.Directory, &Recorder->CCSema->getPreprocessor().getHeaderSearchInfo()); for (const auto &Inc : Includes.MainFileIncludes) @@ -1848,7 +1848,7 @@ const ParseInputs &ParseInput, CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind) { - auto Offset = positionToOffset(ParseInput.Contents, Pos); + auto Offset = positionToOffset(*ParseInput.Contents, Pos); if (!Offset) { elog("Code completion position was invalid {0}", Offset.takeError()); return CodeCompleteResult(); @@ -1857,7 +1857,7 @@ FileName, Preamble ? Preamble->Includes : IncludeStructure(), SpecFuzzyFind, Opts); return (!Preamble || Opts.RunParser == CodeCompleteOptions::NeverParse) - ? std::move(Flow).runWithoutSema(ParseInput.Contents, *Offset, + ? std::move(Flow).runWithoutSema(*ParseInput.Contents, *Offset, *ParseInput.TFS) : std::move(Flow).run({FileName, *Offset, *Preamble, // We want to serve code completions with @@ -1868,7 +1868,7 @@ SignatureHelp signatureHelp(PathRef FileName, Position Pos, const PreambleData &Preamble, const ParseInputs &ParseInput) { - auto Offset = positionToOffset(ParseInput.Contents, Pos); + auto Offset = positionToOffset(*ParseInput.Contents, Pos); if (!Offset) { elog("Signature help position was invalid {0}", Offset.takeError()); return SignatureHelp(); diff --git a/clang-tools-extra/clangd/Compiler.h b/clang-tools-extra/clangd/Compiler.h --- a/clang-tools-extra/clangd/Compiler.h +++ b/clang-tools-extra/clangd/Compiler.h @@ -44,7 +44,7 @@ struct ParseInputs { tooling::CompileCommand CompileCommand; const ThreadsafeFS *TFS; - std::string Contents; + std::shared_ptr Contents; // Version identifier for Contents, provided by the client and opaque to us. std::string Version = "null"; // Prevent reuse of the cached preamble/AST. Slow! Useful to workaround diff --git a/clang-tools-extra/clangd/DraftStore.h b/clang-tools-extra/clangd/DraftStore.h --- a/clang-tools-extra/clangd/DraftStore.h +++ b/clang-tools-extra/clangd/DraftStore.h @@ -13,6 +13,7 @@ #include "support/Path.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/VirtualFileSystem.h" #include #include @@ -21,6 +22,10 @@ namespace clang { namespace clangd { +std::unique_ptr +getSharedStringBuffer(std::shared_ptr Contents, + StringRef BufferName = ""); + /// A thread-safe container for files opened in a workspace, addressed by /// filenames. The contents are owned by the DraftStore. /// Each time a draft is updated, it is assigned a version. This can be @@ -43,7 +48,7 @@ /// If version is empty, one will be automatically assigned. /// Returns the version. std::string addDraft(PathRef File, llvm::StringRef Version, - StringRef Contents); + std::shared_ptr Contents); /// Remove the draft from the store. void removeDraft(PathRef File); diff --git a/clang-tools-extra/clangd/DraftStore.cpp b/clang-tools-extra/clangd/DraftStore.cpp --- a/clang-tools-extra/clangd/DraftStore.cpp +++ b/clang-tools-extra/clangd/DraftStore.cpp @@ -74,13 +74,13 @@ } std::string DraftStore::addDraft(PathRef File, llvm::StringRef Version, - llvm::StringRef Contents) { + std::shared_ptr Contents) { std::lock_guard Lock(Mutex); auto &D = Drafts[File]; updateVersion(D.D, Version); std::time(&D.MTime); - D.D.Contents = std::make_shared(Contents); + D.D.Contents = std::move(Contents); return D.D.Version; } @@ -119,10 +119,16 @@ auto MemFS = llvm::makeIntrusiveRefCnt(); std::lock_guard Guard(Mutex); for (const auto &Draft : Drafts) - MemFS->addFile(Draft.getKey(), Draft.getValue().MTime, - std::make_unique( - Draft.getValue().D.Contents, Draft.getKey())); + MemFS->addFile( + Draft.getKey(), Draft.getValue().MTime, + getSharedStringBuffer(Draft.getValue().D.Contents, Draft.getKey())); return MemFS; } +std::unique_ptr +getSharedStringBuffer(std::shared_ptr Contents, + StringRef BufferName) { + return std::make_unique(std::move(Contents), BufferName); +} + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -14,6 +14,7 @@ #include "Compiler.h" #include "Config.h" #include "Diagnostics.h" +#include "DraftStore.h" #include "Headers.h" #include "IncludeFixer.h" #include "Preamble.h" @@ -270,8 +271,7 @@ } auto Clang = prepareCompilerInstance( std::move(CI), PreamblePCH, - llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents, Filename), VFS, - ASTDiags); + getSharedStringBuffer(Inputs.Contents, Filename), VFS, ASTDiags); if (!Clang) return None; @@ -359,9 +359,9 @@ llvm::Optional FixIncludes; auto BuildDir = VFS->getCurrentWorkingDirectory(); if (Inputs.Index && !BuildDir.getError()) { - auto Style = getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.TFS); + auto Style = getFormatStyleForFile(Filename, *Inputs.Contents, *Inputs.TFS); auto Inserter = std::make_shared( - Filename, Inputs.Contents, Style, BuildDir.get(), + Filename, *Inputs.Contents, Style, BuildDir.get(), &Clang->getPreprocessor().getHeaderSearchInfo()); if (Preamble) { for (const auto &Inc : Preamble->Includes.MainFileIncludes) diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp --- a/clang-tools-extra/clangd/Preamble.cpp +++ b/clang-tools-extra/clangd/Preamble.cpp @@ -237,7 +237,6 @@ EmptyFS FS; // Build and run Preprocessor over the preamble. ParseInputs PI; - PI.Contents = Contents.str(); PI.TFS = &FS; PI.CompileCommand = Cmd; IgnoringDiagConsumer IgnoreDiags; @@ -320,7 +319,7 @@ // Note that we don't need to copy the input contents, preamble can live // without those. auto ContentsBuffer = - llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName); + llvm::MemoryBuffer::getMemBuffer(*Inputs.Contents, FileName); auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), *ContentsBuffer, 0); trace::Span Tracer("BuildPreamble"); @@ -373,7 +372,7 @@ const ParseInputs &Inputs, PathRef FileName, const CompilerInvocation &CI) { auto ContentsBuffer = - llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName); + llvm::MemoryBuffer::getMemBuffer(*Inputs.Contents, FileName); auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), *ContentsBuffer, 0); auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory); return compileCommandsAreEqual(Inputs.CompileCommand, @@ -417,7 +416,7 @@ BaselineScan.takeError()); return PreamblePatch::unmodified(Baseline); } - auto ModifiedScan = scanPreamble(Modified.Contents, Modified.CompileCommand); + auto ModifiedScan = scanPreamble(*Modified.Contents, Modified.CompileCommand); if (!ModifiedScan) { elog("Failed to scan modified contents of {0}: {1}", FileName, ModifiedScan.takeError()); @@ -470,7 +469,8 @@ } // Include is new in the modified preamble. Inject it into the patch and // use #line to set the presumed location to where it is spelled. - auto LineCol = offsetToClangLineColumn(Modified.Contents, Inc.HashOffset); + auto LineCol = + offsetToClangLineColumn(*Modified.Contents, Inc.HashOffset); Patch << llvm::formatv("#line {0}\n", LineCol.first); Patch << llvm::formatv( "#{0} {1}\n", spellingForIncDirective(Inc.Directive), Inc.Written); diff --git a/clang-tools-extra/clangd/TUScheduler.h b/clang-tools-extra/clangd/TUScheduler.h --- a/clang-tools-extra/clangd/TUScheduler.h +++ b/clang-tools-extra/clangd/TUScheduler.h @@ -40,7 +40,7 @@ }; struct InputsAndPreamble { - llvm::StringRef Contents; + std::shared_ptr Contents; const tooling::CompileCommand &Command; // This can be nullptr if no preamble is available. const PreambleData *Preamble; diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp --- a/clang-tools-extra/clangd/TUScheduler.cpp +++ b/clang-tools-extra/clangd/TUScheduler.cpp @@ -753,6 +753,14 @@ #endif } +static bool areInputsSame(const ParseInputs &L, const ParseInputs &R) { + if (L.CompileCommand != R.CompileCommand) + return false; + StringRef LContents = L.Contents ? StringRef(*L.Contents) : ""; + StringRef RContents = R.Contents ? StringRef(*R.Contents) : ""; + return LContents == RContents; +} + void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags, bool ContentChanged) { std::string TaskName = llvm::formatv("Update ({0})", Inputs.Version); @@ -783,9 +791,7 @@ else Inputs.CompileCommand = CDB.getFallbackCommand(FileName); - bool InputsAreTheSame = - std::tie(FileInputs.CompileCommand, FileInputs.Contents) == - std::tie(Inputs.CompileCommand, Inputs.Contents); + bool InputsAreTheSame = areInputsSame(FileInputs, Inputs); // Cached AST is invalidated. if (!InputsAreTheSame) { IdleASTs.take(this); @@ -1015,9 +1021,7 @@ return; } // Used to check whether we can update AST cache. - bool InputsAreLatest = - std::tie(FileInputs.CompileCommand, FileInputs.Contents) == - std::tie(Inputs.CompileCommand, Inputs.Contents); + bool InputsAreLatest = areInputsSame(FileInputs, Inputs); // Take a shortcut and don't report the diagnostics, since they should be the // same. All the clients should handle the lack of OnUpdated() call anyway to // handle empty result from buildAST. @@ -1439,7 +1443,7 @@ struct TUScheduler::FileData { /// Latest inputs, passed to TUScheduler::update(). - std::string Contents; + std::shared_ptr Contents; ASTWorkerHandle Worker; }; @@ -1500,7 +1504,7 @@ FD = std::unique_ptr( new FileData{Inputs.Contents, std::move(Worker)}); ContentChanged = true; - } else if (FD->Contents != Inputs.Contents) { + } else if (*FD->Contents != *Inputs.Contents) { ContentChanged = true; FD->Contents = Inputs.Contents; } diff --git a/clang-tools-extra/clangd/tool/Check.cpp b/clang-tools-extra/clangd/tool/Check.cpp --- a/clang-tools-extra/clangd/tool/Check.cpp +++ b/clang-tools-extra/clangd/tool/Check.cpp @@ -125,11 +125,12 @@ Inputs.TFS = &TFS; Inputs.ClangTidyProvider = Opts.ClangTidyProvider; if (Contents.hasValue()) { - Inputs.Contents = *Contents; - log("Imaginary source file contents:\n{0}", Inputs.Contents); + Inputs.Contents = std::make_shared(*Contents); + log("Imaginary source file contents:\n{0}", *Inputs.Contents); } else { if (auto Contents = TFS.view(llvm::None)->getBufferForFile(File)) { - Inputs.Contents = Contents->get()->getBuffer().str(); + Inputs.Contents = + std::make_shared(Contents->get()->getBuffer()); } else { elog("Couldn't read {0}: {1}", File, Contents.getError().message()); return false; @@ -148,7 +149,7 @@ // FIXME: Check that resource-dir/built-in-headers exist? - Style = getFormatStyleForFile(File, Inputs.Contents, TFS); + Style = getFormatStyleForFile(File, *Inputs.Contents, TFS); return true; } @@ -197,7 +198,7 @@ for (const auto &Tok : SpelledTokens) { unsigned Start = AST->getSourceManager().getFileOffset(Tok.location()); unsigned End = Start + Tok.length(); - Position Pos = offsetToPosition(Inputs.Contents, Start); + Position Pos = offsetToPosition(*Inputs.Contents, Start); // FIXME: dumping the tokens may leak sensitive code into bug reports. // Add an option to turn this off, once we decide how options work. vlog(" {0} {1}", Pos, Tok.text(AST->getSourceManager())); 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 @@ -153,7 +153,8 @@ MockFS FS; Annotations Test(Text); - ParseInputs ParseInput{tooling::CompileCommand(), &FS, Test.code().str()}; + ParseInputs ParseInput{tooling::CompileCommand(), &FS, + std::make_shared(Test.code())}; return codeComplete(FilePath, Test.point(), /*Preamble=*/nullptr, ParseInput, Opts); } diff --git a/clang-tools-extra/clangd/unittests/DraftStoreTests.cpp b/clang-tools-extra/clangd/unittests/DraftStoreTests.cpp --- a/clang-tools-extra/clangd/unittests/DraftStoreTests.cpp +++ b/clang-tools-extra/clangd/unittests/DraftStoreTests.cpp @@ -22,20 +22,21 @@ DraftStore DS; Path File = "foo.cpp"; - EXPECT_EQ("25", DS.addDraft(File, "25", "")); + EXPECT_EQ("25", DS.addDraft(File, "25", std::make_shared(""))); EXPECT_EQ("25", DS.getDraft(File)->Version); EXPECT_EQ("", *DS.getDraft(File)->Contents); - EXPECT_EQ("26", DS.addDraft(File, "", "x")); + EXPECT_EQ("26", DS.addDraft(File, "", std::make_shared("x"))); EXPECT_EQ("26", DS.getDraft(File)->Version); EXPECT_EQ("x", *DS.getDraft(File)->Contents); - EXPECT_EQ("27", DS.addDraft(File, "", "x")) << "no-op change"; + EXPECT_EQ("27", DS.addDraft(File, "", std::make_shared("x"))) + << "no-op change"; EXPECT_EQ("27", DS.getDraft(File)->Version); EXPECT_EQ("x", *DS.getDraft(File)->Contents); // We allow versions to go backwards. - EXPECT_EQ("7", DS.addDraft(File, "7", "y")); + EXPECT_EQ("7", DS.addDraft(File, "7", std::make_shared("y"))); EXPECT_EQ("7", DS.getDraft(File)->Version); EXPECT_EQ("y", *DS.getDraft(File)->Contents); } diff --git a/clang-tools-extra/clangd/unittests/FileIndexTests.cpp b/clang-tools-extra/clangd/unittests/FileIndexTests.cpp --- a/clang-tools-extra/clangd/unittests/FileIndexTests.cpp +++ b/clang-tools-extra/clangd/unittests/FileIndexTests.cpp @@ -295,12 +295,12 @@ )cpp"; PI.TFS = &FS; - PI.Contents = R"cpp( + PI.Contents = std::make_shared(R"cpp( #include "foo.h" namespace ns_in_source { int func_in_source(); } - )cpp"; + )cpp"); // Rebuild the file. IgnoreDiagnostics IgnoreDiags; diff --git a/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp b/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp --- a/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp +++ b/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp @@ -93,7 +93,7 @@ ParseInputs Inputs; Inputs.CompileCommand = *CDB.getCompileCommand(File); Inputs.TFS = &FS; - Inputs.Contents = std::move(Contents); + Inputs.Contents = std::make_shared(std::move(Contents)); Inputs.Opts = ParseOptions(); return Inputs; } @@ -528,7 +528,7 @@ EXPECT_EQ(File, boundPath()); ASSERT_TRUE((bool)AST); - EXPECT_EQ(AST->Inputs.Contents, Inputs.Contents); + EXPECT_EQ(*AST->Inputs.Contents, *Inputs.Contents); EXPECT_EQ(AST->Inputs.Version, Inputs.Version); EXPECT_EQ(AST->AST.version(), Inputs.Version); @@ -548,7 +548,7 @@ EXPECT_EQ(File, boundPath()); ASSERT_TRUE((bool)Preamble); - EXPECT_EQ(Preamble->Contents, Inputs.Contents); + EXPECT_EQ(*Preamble->Contents, *Inputs.Contents); std::lock_guard Lock(Mut); ++TotalPreambleReads; diff --git a/clang-tools-extra/clangd/unittests/TestTU.cpp b/clang-tools-extra/clangd/unittests/TestTU.cpp --- a/clang-tools-extra/clangd/unittests/TestTU.cpp +++ b/clang-tools-extra/clangd/unittests/TestTU.cpp @@ -54,7 +54,7 @@ Argv.push_back(FullFilename); Inputs.CompileCommand.Filename = FullFilename; Inputs.CompileCommand.Directory = testRoot(); - Inputs.Contents = Code; + Inputs.Contents = std::make_shared(Code); if (OverlayRealFileSystemForModules) FS.OverlayRealFileSystemForModules = true; Inputs.TFS = &FS;