[clang-tools-extra] r325522 - [clangd] Do not reuse preamble if compile args changed
Ilya Biryukov via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 19 10:18:49 PST 2018
Author: ibiryukov
Date: Mon Feb 19 10:18:49 2018
New Revision: 325522
URL: http://llvm.org/viewvc/llvm-project?rev=325522&view=rev
Log:
[clangd] Do not reuse preamble if compile args changed
Reviewers: hokein, ioeric, sammccall, simark
Reviewed By: simark
Subscribers: klimek, jkorous-apple, cfe-commits, simark
Differential Revision: https://reviews.llvm.org/D43454
Modified:
clang-tools-extra/trunk/clangd/ClangdUnit.cpp
clang-tools-extra/trunk/clangd/ClangdUnit.h
clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
Modified: clang-tools-extra/trunk/clangd/ClangdUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.cpp?rev=325522&r1=325521&r2=325522&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp Mon Feb 19 10:18:49 2018
@@ -34,6 +34,13 @@ using namespace clang;
namespace {
+bool compileCommandsAreEqual(const tooling::CompileCommand &LHS,
+ const tooling::CompileCommand &RHS) {
+ // We don't check for Output, it should not matter to clangd.
+ return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
+ llvm::makeArrayRef(LHS.CommandLine).equals(RHS.CommandLine);
+}
+
template <class T> std::size_t getUsedBytes(const std::vector<T> &Vec) {
return Vec.capacity() * sizeof(T);
}
@@ -417,7 +424,7 @@ CppFile::rebuild(ParseInputs &&Inputs) {
// Compute updated Preamble.
std::shared_ptr<const PreambleData> NewPreamble =
- rebuildPreamble(*CI, Inputs.FS, *ContentsBuffer);
+ rebuildPreamble(*CI, Inputs.CompileCommand, Inputs.FS, *ContentsBuffer);
// Remove current AST to avoid wasting memory.
AST = llvm::None;
@@ -445,6 +452,7 @@ CppFile::rebuild(ParseInputs &&Inputs) {
}
// Write the results of rebuild into class fields.
+ Command = std::move(Inputs.CompileCommand);
Preamble = std::move(NewPreamble);
AST = std::move(NewAST);
return Diagnostics;
@@ -471,11 +479,12 @@ std::size_t CppFile::getUsedBytes() cons
std::shared_ptr<const PreambleData>
CppFile::rebuildPreamble(CompilerInvocation &CI,
+ const tooling::CompileCommand &Command,
IntrusiveRefCntPtr<vfs::FileSystem> FS,
llvm::MemoryBuffer &ContentsBuffer) const {
const auto &OldPreamble = this->Preamble;
auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), &ContentsBuffer, 0);
- if (OldPreamble &&
+ if (OldPreamble && compileCommandsAreEqual(this->Command, Command) &&
OldPreamble->Preamble.CanReuse(CI, &ContentsBuffer, Bounds, FS.get())) {
log("Reusing preamble for file " + Twine(FileName));
return OldPreamble;
Modified: clang-tools-extra/trunk/clangd/ClangdUnit.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.h?rev=325522&r1=325521&r2=325522&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdUnit.h Mon Feb 19 10:18:49 2018
@@ -152,12 +152,15 @@ private:
/// This method is const to ensure we don't incidentally modify any fields.
std::shared_ptr<const PreambleData>
rebuildPreamble(CompilerInvocation &CI,
+ const tooling::CompileCommand &Command,
IntrusiveRefCntPtr<vfs::FileSystem> FS,
llvm::MemoryBuffer &ContentsBuffer) const;
const Path FileName;
const bool StorePreamblesInMemory;
+ /// The last CompileCommand used to build AST and Preamble.
+ tooling::CompileCommand Command;
/// The last parsed AST.
llvm::Optional<ParsedAST> AST;
/// The last built Preamble.
Modified: clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp?rev=325522&r1=325521&r2=325522&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp Mon Feb 19 10:18:49 2018
@@ -373,6 +373,46 @@ struct bar { T x; };
EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
}
+TEST_F(ClangdVFSTest, ForceReparseCompileCommandDefines) {
+ MockFSProvider FS;
+ ErrorCheckingDiagConsumer DiagConsumer;
+ MockCompilationDatabase CDB;
+ ClangdServer Server(CDB, DiagConsumer, FS,
+ /*AsyncThreadsCount=*/0,
+ /*StorePreamblesInMemory=*/true);
+
+ // No need to sync reparses, because reparses are performed on the calling
+ // thread.
+ auto FooCpp = testPath("foo.cpp");
+ const auto SourceContents = R"cpp(
+#ifdef WITH_ERROR
+this
+#endif
+
+int main() { return 0; }
+)cpp";
+ FS.Files[FooCpp] = "";
+ FS.ExpectedFile = FooCpp;
+
+ // Parse with define, we expect to see the errors.
+ CDB.ExtraClangFlags = {"-DWITH_ERROR"};
+ Server.addDocument(FooCpp, SourceContents);
+ EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
+
+ // Parse without the define, no errors should be produced.
+ CDB.ExtraClangFlags = {};
+ // Currently, addDocument never checks if CompileCommand has changed, so we
+ // expect to see the errors.
+ Server.addDocument(FooCpp, SourceContents);
+ EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
+ // But forceReparse should reparse the file with proper flags.
+ Server.forceReparse(FooCpp);
+ EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+ // Subsequent addDocument call should finish without errors too.
+ Server.addDocument(FooCpp, SourceContents);
+ EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+}
+
TEST_F(ClangdVFSTest, MemoryUsage) {
MockFSProvider FS;
ErrorCheckingDiagConsumer DiagConsumer;
More information about the cfe-commits
mailing list