Commit f042a64d authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r366455 and r366559:

------------------------------------------------------------------------
r366455 | kadircet | 2019-07-18 18:13:23 +0200 (Thu, 18 Jul 2019) | 9 lines

[clangd] Get rid of dots and dotsdots within GlobalCompilationDatabase

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D64860
------------------------------------------------------------------------

------------------------------------------------------------------------
r366559 | kadircet | 2019-07-19 12:18:52 +0200 (Fri, 19 Jul 2019) | 19 lines

Revert "Revert r366458, r366467 and r366468"

This reverts commit 9c377105.

[clangd][BackgroundIndexLoader] Directly store DependentTU while loading shard

Summary:
We were deferring the population of DependentTU field in LoadedShard
until BackgroundIndexLoader was consumed. This actually triggers a use after
free since the shards FileToTU was pointing at could've been moved while
consuming the Loader.

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D64980
------------------------------------------------------------------------

llvm-svn: 366718
parent f3456bb9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ add_clang_library(clangDaemon
  XRefs.cpp

  index/Background.cpp
  index/BackgroundIndexLoader.cpp
  index/BackgroundIndexStorage.cpp
  index/BackgroundQueue.cpp
  index/BackgroundRebuild.cpp
+2 −1
Original line number Diff line number Diff line
@@ -127,7 +127,8 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
  if (Opts.BackgroundIndex) {
    BackgroundIdx = llvm::make_unique<BackgroundIndex>(
        Context::current().clone(), FSProvider, CDB,
        BackgroundIndexStorage::createDiskBackedStorageFactory());
        BackgroundIndexStorage::createDiskBackedStorageFactory(
            [&CDB](llvm::StringRef File) { return CDB.getProjectInfo(File); }));
    AddIndex(BackgroundIdx.get());
  }
  if (DynamicIdx)
+6 −0
Original line number Diff line number Diff line
@@ -111,5 +111,11 @@ PreambleFileStatusCache::getConsumingFS(
  return llvm::IntrusiveRefCntPtr<CacheVFS>(new CacheVFS(std::move(FS), *this));
}

Path removeDots(PathRef File) {
  llvm::SmallString<128> CanonPath(File);
  llvm::sys::path::remove_dots(CanonPath, /*remove_dot_dot=*/true);
  return CanonPath.str().str();
}

} // namespace clangd
} // namespace clang
+8 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H

#include "Path.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/VirtualFileSystem.h"
@@ -65,6 +66,13 @@ private:
  llvm::StringMap<llvm::vfs::Status> StatCache;
};

/// Returns a version of \p File that doesn't contain dots and dot dots.
/// e.g /a/b/../c -> /a/c
///     /a/b/./c -> /a/b/c
/// FIXME: We should avoid encountering such paths in clangd internals by
/// filtering everything we get over LSP, CDB, etc.
Path removeDots(PathRef File);

} // namespace clangd
} // namespace clang

+22 −12
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "GlobalCompilationDatabase.h"
#include "FS.h"
#include "Logger.h"
#include "Path.h"
#include "clang/Frontend/CompilerInvocation.h"
@@ -15,6 +16,7 @@
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include <string>
@@ -147,9 +149,12 @@ DirectoryBasedGlobalCompilationDatabase::lookupCDB(
          getCDBInDirLocked(*CompileCommandsDir);
      Result.PI.SourceRoot = *CompileCommandsDir;
    } else {
      actOnAllParentDirectories(
          Request.FileName, [this, &SentBroadcast, &Result](PathRef Path) {
            std::tie(Result.CDB, SentBroadcast) = getCDBInDirLocked(Path);
      // Traverse the canonical version to prevent false positives. i.e.:
      // src/build/../a.cc can detect a CDB in /src/build if not canonicalized.
      actOnAllParentDirectories(removeDots(Request.FileName),
                                [this, &SentBroadcast, &Result](PathRef Path) {
                                  std::tie(Result.CDB, SentBroadcast) =
                                      getCDBInDirLocked(Path);
                                  Result.PI.SourceRoot = Path;
                                  return Result.CDB != nullptr;
                                });
@@ -209,7 +214,8 @@ void DirectoryBasedGlobalCompilationDatabase::broadcastCDB(
    actOnAllParentDirectories(File, [&](PathRef Path) {
      if (DirectoryHasCDB.lookup(Path)) {
        if (Path == Result.PI.SourceRoot)
          GovernedFiles.push_back(File);
          // Make sure listeners always get a canonical path for the file.
          GovernedFiles.push_back(removeDots(File));
        // Stop as soon as we hit a CDB.
        return true;
      }
@@ -248,7 +254,7 @@ OverlayCDB::getCompileCommand(PathRef File) const {
  llvm::Optional<tooling::CompileCommand> Cmd;
  {
    std::lock_guard<std::mutex> Lock(Mutex);
    auto It = Commands.find(File);
    auto It = Commands.find(removeDots(File));
    if (It != Commands.end())
      Cmd = It->second;
  }
@@ -272,20 +278,24 @@ tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {

void OverlayCDB::setCompileCommand(
    PathRef File, llvm::Optional<tooling::CompileCommand> Cmd) {
  // We store a canonical version internally to prevent mismatches between set
  // and get compile commands. Also it assures clients listening to broadcasts
  // doesn't receive different names for the same file.
  std::string CanonPath = removeDots(File);
  {
    std::unique_lock<std::mutex> Lock(Mutex);
    if (Cmd)
      Commands[File] = std::move(*Cmd);
      Commands[CanonPath] = std::move(*Cmd);
    else
      Commands.erase(File);
      Commands.erase(CanonPath);
  }
  OnCommandChanged.broadcast({File});
  OnCommandChanged.broadcast({CanonPath});
}

llvm::Optional<ProjectInfo> OverlayCDB::getProjectInfo(PathRef File) const {
  {
    std::lock_guard<std::mutex> Lock(Mutex);
    auto It = Commands.find(File);
    auto It = Commands.find(removeDots(File));
    if (It != Commands.end())
      return ProjectInfo{};
  }
Loading