bnbarham created this revision.
bnbarham added reviewers: keith, dexonsmith, JDevlieghere, vsapsai.
Herald added a subscriber: carlosgalvezp.
Herald added a project: All.
bnbarham requested review of this revision.
Herald added projects: clang, LLDB, LLVM, clang-tools-extra.
Herald added subscribers: cfe-commits, llvm-commits, lldb-commits.

Includes two test fixes (since chained mappings are no longer allowed)
and adds a new test for multiple overlays.

Uses other than `CompilerInvocation.cpp` are simple 1:1 mappings, but
without the need to read into a buffer first.

Depends on D121421 <https://reviews.llvm.org/D121421> and D121423 
<https://reviews.llvm.org/D121423> and D121424 
<https://reviews.llvm.org/D121424> and D121425 
<https://reviews.llvm.org/D121425>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121426

Files:
  clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/VFS/Inputs/vfsroot.yaml
  clang/test/VFS/directory.c
  clang/test/VFS/multiple-overlays.c
  clang/test/VFS/vfsroot-with-overlay.c
  lldb/source/Commands/CommandObjectReproducer.cpp
  llvm/include/llvm/Support/Error.h
  llvm/tools/dsymutil/Reproducer.cpp
  llvm/tools/dsymutil/Reproducer.h

Index: llvm/tools/dsymutil/Reproducer.h
===================================================================
--- llvm/tools/dsymutil/Reproducer.h
+++ llvm/tools/dsymutil/Reproducer.h
@@ -59,8 +59,7 @@
 };
 
 /// Reproducer instance used to use an existing reproducer. The VFS returned by
-/// this instance is a RedirectingFileSystem that remaps paths to their
-/// counterpart in the reproducer.
+/// remaps paths to their counterpart in the reproducer.
 class ReproducerUse : public Reproducer {
 public:
   ReproducerUse(StringRef Root, std::error_code &EC);
Index: llvm/tools/dsymutil/Reproducer.cpp
===================================================================
--- llvm/tools/dsymutil/Reproducer.cpp
+++ llvm/tools/dsymutil/Reproducer.cpp
@@ -48,15 +48,15 @@
 ReproducerUse::ReproducerUse(StringRef Root, std::error_code &EC) {
   SmallString<128> Mapping(Root);
   sys::path::append(Mapping, "mapping.yaml");
-  ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
-      vfs::getRealFileSystem()->getBufferForFile(Mapping.str());
 
-  if (!Buffer) {
-    EC = Buffer.getError();
+  auto OverlayFS = llvm::vfs::getVFSFromYAMLs(Mapping.str());
+  if (auto Err = OverlayFS.takeError()) {
+    llvm::handleAllErrors(std::move(Err), [&](const llvm::ErrorInfoBase &E) {
+      EC = E.convertToErrorCode();
+    });
     return;
   }
-
-  VFS = llvm::vfs::getVFSFromYAML(std::move(Buffer.get()), nullptr, Mapping);
+  VFS = std::move(*OverlayFS);
 }
 
 llvm::Expected<std::unique_ptr<Reproducer>>
Index: llvm/include/llvm/Support/Error.h
===================================================================
--- llvm/include/llvm/Support/Error.h
+++ llvm/include/llvm/Support/Error.h
@@ -1281,7 +1281,7 @@
     return OS.str();
   }
 
-  StringRef getFileName() { return FileName; }
+  StringRef getFileName() const { return FileName; }
 
   Error takeError() { return Error(std::move(Err)); }
 
Index: lldb/source/Commands/CommandObjectReproducer.cpp
===================================================================
--- lldb/source/Commands/CommandObjectReproducer.cpp
+++ lldb/source/Commands/CommandObjectReproducer.cpp
@@ -409,23 +409,19 @@
     switch (m_options.provider) {
     case eReproducerProviderFiles: {
       FileSpec vfs_mapping = loader->GetFile<FileProvider::Info>();
+      std::string overlay_path = vfs_mapping.GetPath();
 
-      // Read the VFS mapping.
-      ErrorOr<std::unique_ptr<MemoryBuffer>> buffer =
-          vfs::getRealFileSystem()->getBufferForFile(vfs_mapping.GetPath());
-      if (!buffer) {
-        SetError(result, errorCodeToError(buffer.getError()));
+      Expected<IntrusiveRefCntPtr<vfs::FileSystem>> vfs =
+          vfs::getVFSFromYAMLs(StringRef(overlay_path));
+      if (auto err = vfs.takeError()) {
+        SetError(result, std::move(err));
         return false;
       }
 
-      // Initialize a VFS from the given mapping.
-      IntrusiveRefCntPtr<vfs::FileSystem> vfs = vfs::getVFSFromYAML(
-          std::move(buffer.get()), nullptr, vfs_mapping.GetPath());
-
       // Dump the VFS to a buffer.
       std::string str;
       raw_string_ostream os(str);
-      static_cast<vfs::RedirectingFileSystem &>(*vfs).dump(os);
+      (*vfs)->dump(os);
       os.flush();
 
       // Return the string.
Index: clang/test/VFS/vfsroot-with-overlay.c
===================================================================
--- clang/test/VFS/vfsroot-with-overlay.c
+++ clang/test/VFS/vfsroot-with-overlay.c
@@ -1,7 +1,7 @@
 // RUN: rm -rf %t
 // RUN: mkdir -p %t
 // RUN: sed -e "s@TEST_DIR@%{/S:regex_replacement}@g" -e "s@OUT_DIR@%{/t:regex_replacement}@g" %S/Inputs/vfsroot.yaml > %t.yaml
-// RUN: sed -e "s@INPUT_DIR@/indirect-vfs-root-files@g" -e "s@OUT_DIR@/overlay-dir@g" %S/Inputs/vfsoverlay.yaml > %t/vfsoverlay.yaml
+// RUN: sed -e "s@INPUT_DIR@%{/S:regex_replacement}/Inputs@g" -e "s@OUT_DIR@/overlay-dir@g" %S/Inputs/vfsoverlay.yaml > %t/vfsoverlay.yaml
 // RUN: %clang_cc1 -Werror -ivfsoverlay %t.yaml -ivfsoverlay /direct-vfs-root-files/vfsoverlay.yaml -I /overlay-dir -fsyntax-only /tests/vfsroot-with-overlay.c
 
 #include "not_real.h"
Index: clang/test/VFS/multiple-overlays.c
===================================================================
--- /dev/null
+++ clang/test/VFS/multiple-overlays.c
@@ -0,0 +1,39 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s@EXTERNAL_DIR@%{/t:regex_replacement}/B@g" -e "s@NAME_DIR@%{/t:regex_replacement}/A@g" %t/vfs/base.yaml > %t/vfs/a-b.yaml
+// RUN: sed -e "s@EXTERNAL_DIR@%{/t:regex_replacement}/C@g" -e "s@NAME_DIR@%{/t:regex_replacement}/B@g" %t/vfs/base.yaml > %t/vfs/b-c.yaml
+
+// Overlays should not be transitive, ie. given overlays of A -> B and B -> C, A should not remap to
+// C.
+
+// RUN: %clang_cc1 -Werror -I %t/A -ivfsoverlay %t/vfs/b-c.yaml -ivfsoverlay %t/vfs/a-b.yaml -fsyntax-only -E -C %t/main.c 2>&1 | FileCheck --check-prefix=FROM_B %s
+// FROM_B: # 1 "{{.*(/|\\\\)B(/|\\\\)}}Header.h"
+// FROM_B: // Header.h in B
+
+// RUN: %clang_cc1 -Werror -I %t/B -ivfsoverlay %t/vfs/b-c.yaml -ivfsoverlay %t/vfs/a-b.yaml -fsyntax-only -E -C %t/main.c 2>&1 | FileCheck --check-prefix=FROM_C %s
+// FROM_C: # 1 "{{.*(/|\\\\)C(/|\\\\)}}Header.h"
+// FROM_C: // Header.h in C
+
+//--- main.c
+#include "Header.h"
+
+//--- A/Header.h
+// Header.h in A
+
+//--- B/Header.h
+// Header.h in B
+
+//--- C/Header.h
+// Header.h in C
+
+//--- vfs/base.yaml
+{
+  'version': 0,
+  'redirecting-with': 'fallthrough',
+  'roots': [
+    { 'name': 'NAME_DIR',
+      'type': 'directory-remap',
+      'external-contents': 'EXTERNAL_DIR'
+    }
+  ]
+}
Index: clang/test/VFS/directory.c
===================================================================
--- clang/test/VFS/directory.c
+++ clang/test/VFS/directory.c
@@ -1,13 +1,11 @@
 // RUN: rm -rf %t
 // RUN: mkdir -p %t/Underlying
 // RUN: mkdir -p %t/Overlay
-// RUN: mkdir -p %t/Middle
 // RUN: echo '// B.h in Underlying' > %t/Underlying/B.h
 // RUN: echo '#ifdef NESTED' >> %t/Underlying/B.h
 // RUN: echo '#include "C.h"' >> %t/Underlying/B.h
 // RUN: echo '#endif' >> %t/Underlying/B.h
 // RUN: echo '// C.h in Underlying' > %t/Underlying/C.h
-// RUN: echo '// C.h in Middle' > %t/Middle/C.h
 // RUN: echo '// C.h in Overlay' > %t/Overlay/C.h
 
 // 1) Underlying -> Overlay (C.h found, B.h falling back to Underlying)
@@ -17,31 +15,11 @@
 // RUN: sed -e "s@INPUT_DIR@Overlay@g" -e "s@OUT_DIR@%{/t:regex_replacement}/Underlying@g" %S/Inputs/vfsoverlay-directory-relative.yaml > %t/vfs-relative.yaml
 // RUN: %clang_cc1 -Werror -I %t/Underlying -ivfsoverlay %t/vfs-relative.yaml -fsyntax-only -E -C %s 2>&1 | FileCheck --check-prefix=DIRECT %s
 
+// DIRECT: # 1 "{{.*(/|\\\\)Underlying(/|\\\\)}}B.h"
 // DIRECT: {{^}}// B.h in Underlying
+// DIRECT: # 1 "{{.*(/|\\\\)Overlay(/|\\\\)}}C.h"
 // DIRECT: {{^}}// C.h in Overlay
 
-// 2) Underlying -> Middle -> Overlay (C.h found, B.h falling back to Underlying)
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}/Overlay@g" -e "s@OUT_DIR@%{/t:regex_replacement}/Middle@g" %S/Inputs/vfsoverlay-directory.yaml > %t/vfs.yaml
-// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}/Middle@g" -e "s@OUT_DIR@%{/t:regex_replacement}/Underlying@g" %S/Inputs/vfsoverlay-directory.yaml > %t/vfs2.yaml
-// RUN: %clang_cc1 -Werror -I %t/Underlying -ivfsoverlay %t/vfs.yaml -ivfsoverlay %t/vfs2.yaml -fsyntax-only -E -C %s 2>&1 | FileCheck --check-prefix=DIRECT %s
-// RUN: %clang_cc1 -Werror -I %t/Underlying -ivfsoverlay %t/vfs.yaml -ivfsoverlay %t/vfs2.yaml -DNESTED -fsyntax-only -E -C %s 2>&1 | FileCheck --check-prefix=DIRECT %s
-
-// Same as direct above
-
-// 3) Underlying -> Middle -> Overlay (C.h falling back to Middle, B.h falling back to Underlying)
-// RUN: rm -f %t/Overlay/C.h
-// RUN: %clang_cc1 -Werror -I %t/Underlying -ivfsoverlay %t/vfs.yaml -ivfsoverlay %t/vfs2.yaml -fsyntax-only -E -C %s 2>&1 | FileCheck --check-prefix=FALLBACK %s
-
-// FALLBACK: {{^}}// B.h in Underlying
-// FALLBACK: {{^}}// C.h in Middle
-
-// 3) Underlying -> Middle -> Overlay (C.h falling back to Underlying, B.h falling back to Underlying)
-// RUN: rm -f %t/Middle/C.h
-// RUN: %clang_cc1 -Werror -I %t/Underlying -ivfsoverlay %t/vfs.yaml -ivfsoverlay %t/vfs2.yaml -fsyntax-only -E -C %s 2>&1 | FileCheck --check-prefix=FALLBACK2 %s
-
-// FALLBACK2: {{^}}// B.h in Underlying
-// FALLBACK2: {{^}}// C.h in Underlying
-
 #include "B.h"
 #ifndef NESTED
 #include "C.h"
Index: clang/test/VFS/Inputs/vfsroot.yaml
===================================================================
--- clang/test/VFS/Inputs/vfsroot.yaml
+++ clang/test/VFS/Inputs/vfsroot.yaml
@@ -26,13 +26,6 @@
         }
       ]
     },
-    { 'name': '/indirect-vfs-root-files', 'type': 'directory',
-      'contents': [
-        { 'name': 'actual_header.h', 'type': 'file',
-          'external-contents': 'TEST_DIR/Inputs/actual_header.h'
-        }
-      ]
-    },
     { 'name': 'TEST_DIR/Inputs/Broken.framework', 'type': 'directory',
       'contents': [
         { 'name': 'Headers/A.h', 'type': 'file',
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -4693,28 +4693,22 @@
 clang::createVFSFromCompilerInvocation(
     const CompilerInvocation &CI, DiagnosticsEngine &Diags,
     IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {
-  if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
+  ArrayRef<std::string> OptFiles = CI.getHeaderSearchOpts().VFSOverlayFiles;
+  if (OptFiles.empty())
     return BaseFS;
 
-  IntrusiveRefCntPtr<llvm::vfs::FileSystem> Result = BaseFS;
-  // earlier vfs files are on the bottom
-  for (const auto &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
-    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
-        Result->getBufferForFile(File);
-    if (!Buffer) {
-      Diags.Report(diag::err_missing_vfs_overlay_file) << File;
-      continue;
-    }
-
-    IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getVFSFromYAML(
-        std::move(Buffer.get()), /*DiagHandler*/ nullptr, File,
-        /*DiagContext*/ nullptr, Result);
-    if (!FS) {
-      Diags.Report(diag::err_invalid_vfs_overlay) << File;
-      continue;
-    }
-
-    Result = FS;
+  SmallVector<StringRef> Files(OptFiles.begin(), OptFiles.end());
+  Expected<IntrusiveRefCntPtr<llvm::vfs::FileSystem>> OverlayFS =
+      llvm::vfs::getVFSFromYAMLs(Files, BaseFS);
+  if (auto Err = OverlayFS.takeError()) {
+    llvm::handleAllErrors(std::move(Err), [&](const llvm::FileError &FE) {
+      if (FE.convertToErrorCode() == std::errc::no_such_file_or_directory) {
+        Diags.Report(diag::err_missing_vfs_overlay_file) << FE.getFileName();
+      } else {
+        Diags.Report(diag::err_invalid_vfs_overlay) << FE.getFileName();
+      }
+    });
+    return BaseFS;
   }
-  return Result;
+  return *OverlayFS;
 }
Index: clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
===================================================================
--- clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -363,26 +363,22 @@
       std::move(OverrideOptions), std::move(FS));
 }
 
-llvm::IntrusiveRefCntPtr<vfs::FileSystem>
-getVfsFromFile(const std::string &OverlayFile,
-               llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS) {
-  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
-      BaseFS->getBufferForFile(OverlayFile);
-  if (!Buffer) {
-    llvm::errs() << "Can't load virtual filesystem overlay file '"
-                 << OverlayFile << "': " << Buffer.getError().message()
-                 << ".\n";
-    return nullptr;
-  }
-
-  IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getVFSFromYAML(
-      std::move(Buffer.get()), /*DiagHandler*/ nullptr, OverlayFile);
-  if (!FS) {
-    llvm::errs() << "Error: invalid virtual filesystem overlay file '"
-                 << OverlayFile << "'.\n";
+static IntrusiveRefCntPtr<vfs::OverlayFileSystem>
+getVFSFromFile(StringRef OverlayFile) {
+  auto OverlayFS = vfs::getVFSFromYAMLs(OverlayFile, vfs::getRealFileSystem());
+  if (auto Err = OverlayFS.takeError()) {
+    handleAllErrors(std::move(Err), [](const FileError &FE) {
+      if (FE.convertToErrorCode() == std::errc::no_such_file_or_directory) {
+        errs() << "Can't load virtual filesystem overlay file '"
+               << FE.getFileName() << "': " << FE.message() << ".\n";
+      } else {
+        errs() << "Error: invalid virtual filesystem overlay file '"
+               << FE.getFileName() << "'.\n";
+      }
+    });
     return nullptr;
   }
-  return FS;
+  return std::move(*OverlayFS);
 }
 
 int clangTidyMain(int argc, const char **argv) {
@@ -400,16 +396,10 @@
     return 1;
   }
 
-  llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> BaseFS(
-      new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
-
-  if (!VfsOverlay.empty()) {
-    IntrusiveRefCntPtr<vfs::FileSystem> VfsFromFile =
-        getVfsFromFile(VfsOverlay, BaseFS);
-    if (!VfsFromFile)
-      return 1;
-    BaseFS->pushOverlay(std::move(VfsFromFile));
-  }
+  llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> BaseFS =
+      getVFSFromFile(VfsOverlay);
+  if (!BaseFS)
+    return 1;
 
   auto OwningOptionsProvider = createOptionsProvider(BaseFS);
   auto *OptionsProvider = OwningOptionsProvider.get();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to