diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -65,7 +65,7 @@ return MaybeStat.getError(); assert(!MaybeStat->isDirectory() && "not a file"); assert(isValid() && "not initialized"); - return Contents.str(); + return Contents->getBuffer(); } /// \returns The error or the status of the entry. @@ -94,11 +94,7 @@ private: llvm::ErrorOr MaybeStat; - // Store the contents in a small string to allow a - // move from the small string for the minimized contents. - // Note: small size of 1 allows us to store an empty string with an implicit - // null terminator without any allocations. - llvm::SmallString<1> Contents; + std::unique_ptr Contents; PreprocessorSkippedRangeMapping PPSkippedRangeMapping; }; diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -9,6 +9,7 @@ #include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h" #include "clang/Lex/DependencyDirectivesSourceMinimizer.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SmallVectorMemoryBuffer.h" #include "llvm/Support/Threading.h" using namespace clang; @@ -43,11 +44,7 @@ // FIXME: Propage the diagnostic if desired by the client. CachedFileSystemEntry Result; Result.MaybeStat = std::move(*Stat); - Result.Contents.reserve(Buffer->getBufferSize() + 1); - Result.Contents.append(Buffer->getBufferStart(), Buffer->getBufferEnd()); - // Implicitly null terminate the contents for Clang's lexer. - Result.Contents.push_back('\0'); - Result.Contents.pop_back(); + Result.Contents = std::move(*MaybeBuffer); return Result; } @@ -65,10 +62,12 @@ // std::move will preserve it even if it needs to do a copy if the // SmallString still has the small capacity. MinimizedFileContents.push_back('\0'); - Result.Contents = std::move(MinimizedFileContents); - // Now make the null terminator implicit again, so that Clang's lexer can find - // it right where the buffer ends. - Result.Contents.pop_back(); + Result.Contents = std::make_unique( + std::move(MinimizedFileContents), [](SmallVectorImpl &SV) { + // Now make the null terminator implicit again, so that Clang's lexer + // can find it right where the buffer ends. + SV.pop_back(); + }); // Compute the skipped PP ranges that speedup skipping over inactive // preprocessor blocks. diff --git a/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h b/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h --- a/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h +++ b/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h @@ -14,6 +14,7 @@ #ifndef LLVM_SUPPORT_SMALLVECTORMEMORYBUFFER_H #define LLVM_SUPPORT_SMALLVECTORMEMORYBUFFER_H +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" @@ -48,6 +49,16 @@ init(this->SV.begin(), this->SV.end(), false); } + /// Construct a SmallVectorMemoryBuffer from the given SmallVector r-value, + /// and invoke the given function right after the move. + SmallVectorMemoryBuffer( + SmallVectorImpl &&SV, + llvm::function_ref &)> AfterMove) + : SV(std::move(SV)), BufferName("") { + AfterMove(this->SV); + init(this->SV.begin(), this->SV.end(), false); + } + // Key function. ~SmallVectorMemoryBuffer() override;