asavonic updated this revision to Diff 147974.
asavonic added a comment.

Add license header.


https://reviews.llvm.org/D47190

Files:
  include/clang/Driver/Options.td
  include/clang/Lex/HeaderSearchOptions.h
  lib/Frontend/CompilerInvocation.cpp
  unittests/Frontend/CMakeLists.txt
  unittests/Frontend/CompilerInstanceTest.cpp
  unittests/Frontend/VfsTestLib.cpp

Index: unittests/Frontend/VfsTestLib.cpp
===================================================================
--- /dev/null
+++ unittests/Frontend/VfsTestLib.cpp
@@ -0,0 +1,31 @@
+//===- unittests/Frontend/VfsTestLib.cpp - CI tests -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/VirtualFileSystem.h"
+#include "llvm/ADT/SmallString.h"
+
+#ifdef _WIN32
+#define EXPORT __declspec(dllexport)
+#else
+#define EXPORT
+#endif
+
+extern "C" EXPORT clang::vfs::FileSystem *__clang_create_vfs() {
+  auto *FS = new clang::vfs::InMemoryFileSystem();
+
+  llvm::SmallString<128> FileName("virtual.file");
+  std::error_code EC = llvm::sys::fs::make_absolute(FileName);
+  if (EC) {
+    return nullptr;
+  }
+
+  FS->addFile(FileName, (time_t)0, llvm::MemoryBuffer::getMemBuffer("foobar"));
+
+  return FS;
+}
Index: unittests/Frontend/CompilerInstanceTest.cpp
===================================================================
--- unittests/Frontend/CompilerInstanceTest.cpp
+++ unittests/Frontend/CompilerInstanceTest.cpp
@@ -9,8 +9,10 @@
 
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/CompilerInvocation.h"
+#include "llvm/Config/config.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/ToolOutputFile.h"
 #include "gtest/gtest.h"
 
@@ -71,4 +73,37 @@
   ASSERT_TRUE(Instance.getFileManager().getFile("vfs-virtual.file"));
 }
 
+static std::string LibPath(const std::string Name = "VfsTestLib") {
+  const std::vector<testing::internal::string> &Argvs =
+      testing::internal::GetArgvs();
+  const char *Argv0 = Argvs.size() > 0 ? Argvs[0].c_str() : "FrontendTests";
+  llvm::SmallString<256> Buf(llvm::sys::path::parent_path(Argv0));
+  llvm::sys::path::append(Buf, (Name + LTDL_SHLIB_EXT).c_str());
+  return Buf.str();
+}
+
+TEST(CompilerInstance, VFSOverlayLibrary) {
+  // Create a CompilerInvocation that uses this overlay library.
+  const std::string VFSArg = "-ivfsoverlay-lib" + LibPath();
+  const char *Args[] = {"clang", VFSArg.c_str(), "-xc", "-"};
+
+  IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
+      CompilerInstance::createDiagnostics(new DiagnosticOptions());
+
+  std::shared_ptr<CompilerInvocation> CInvok =
+      createInvocationFromCommandLine(Args, Diags);
+
+  if (!CInvok)
+    FAIL() << "could not create compiler invocation";
+
+  CompilerInstance Instance;
+  Instance.setDiagnostics(Diags.get());
+  Instance.setInvocation(CInvok);
+  Instance.createFileManager();
+
+  // Check if the virtual file exists which means that our VFS is used by the
+  // CompilerInstance.
+  ASSERT_TRUE(Instance.getFileManager().getFile("virtual.file"));
+}
+
 } // anonymous namespace
Index: unittests/Frontend/CMakeLists.txt
===================================================================
--- unittests/Frontend/CMakeLists.txt
+++ unittests/Frontend/CMakeLists.txt
@@ -1,6 +1,7 @@
 set(LLVM_LINK_COMPONENTS
   Support
   )
+list(APPEND LLVM_OPTIONAL_SOURCES VfsTestLib.cpp)
 
 add_clang_unittest(FrontendTests
   ASTUnitTest.cpp
@@ -21,3 +22,15 @@
   clangCodeGen
   clangFrontendTool
   )
+
+add_library(VfsTestLib SHARED VfsTestLib.cpp)
+target_link_libraries(VfsTestLib clangBasic)
+set_target_properties(VfsTestLib
+  PROPERTIES PREFIX ""
+  SUFFIX ${LTDL_SHLIB_EXT}
+  )
+set(outdir ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR})
+set_output_directory(VfsTestLib BINARY_DIR ${outdir} LIBRARY_DIR ${outdir})
+get_target_property(test_suite_folder FrontendTests FOLDER)
+set_property(TARGET VfsTestLib PROPERTY FOLDER "${test_suite_folder}")
+add_dependencies(FrontendTests VfsTestLib)
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -66,6 +66,7 @@
 #include "llvm/ProfileData/InstrProfReader.h"
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ErrorOr.h"
@@ -1841,6 +1842,9 @@
 
   for (const auto *A : Args.filtered(OPT_ivfsoverlay))
     Opts.AddVFSOverlayFile(A->getValue());
+
+  for (const Arg *A : Args.filtered(OPT_ivfsoverlay_lib))
+    Opts.AddVFSOverlayLib(A->getValue());
 }
 
 void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
@@ -3180,11 +3184,14 @@
   return createVFSFromCompilerInvocation(CI, Diags, vfs::getRealFileSystem());
 }
 
+typedef vfs::FileSystem *(*CreateLibraryFileSystem)(void);
+
 IntrusiveRefCntPtr<vfs::FileSystem>
 createVFSFromCompilerInvocation(const CompilerInvocation &CI,
                                 DiagnosticsEngine &Diags,
                                 IntrusiveRefCntPtr<vfs::FileSystem> BaseFS) {
-  if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
+  if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty() &&
+      CI.getHeaderSearchOpts().VFSOverlayLibs.empty())
     return BaseFS;
 
   IntrusiveRefCntPtr<vfs::OverlayFileSystem> Overlay(
@@ -3205,6 +3212,32 @@
     else
       Diags.Report(diag::err_invalid_vfs_overlay) << File;
   }
+
+  // Load shared libraries that provide a VFS.
+  for (const std::string &LibFile : CI.getHeaderSearchOpts().VFSOverlayLibs) {
+    std::string Error;
+    auto Lib = llvm::sys::DynamicLibrary::getPermanentLibrary(
+        LibFile.c_str(), &Error);
+    if (!Lib.isValid()) {
+      Diags.Report(diag::err_invalid_vfs_overlay) << LibFile;
+      continue;
+    }
+
+    auto *CreateFS =
+        (CreateLibraryFileSystem)Lib.getAddressOfSymbol("__clang_create_vfs");
+    if (!CreateFS) {
+      Diags.Report(diag::err_invalid_vfs_overlay) << LibFile;
+      continue;
+    }
+
+    IntrusiveRefCntPtr<vfs::FileSystem> FS = CreateFS();
+    if (!FS.get()) {
+      Diags.Report(diag::err_invalid_vfs_overlay) << LibFile;
+      continue;
+    }
+
+    Overlay->pushOverlay(FS);
+  }
   return Overlay;
 }
 
Index: include/clang/Lex/HeaderSearchOptions.h
===================================================================
--- include/clang/Lex/HeaderSearchOptions.h
+++ include/clang/Lex/HeaderSearchOptions.h
@@ -173,6 +173,9 @@
   /// The set of user-provided virtual filesystem overlay files.
   std::vector<std::string> VFSOverlayFiles;
 
+  /// \brief The set of libraries with user-provided virtual filesystem.
+  std::vector<std::string> VFSOverlayLibs;
+
   /// Include the compiler builtin includes.
   unsigned UseBuiltinIncludes : 1;
 
@@ -229,6 +232,10 @@
     VFSOverlayFiles.push_back(Name);
   }
 
+  void AddVFSOverlayLib(StringRef Name) {
+    VFSOverlayLibs.push_back(Name);
+  }
+
   void AddPrebuiltModulePath(StringRef Name) {
     PrebuiltModulePaths.push_back(Name);
   }
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1828,6 +1828,8 @@
   Flags<[CC1Option]>;
 def ivfsoverlay : JoinedOrSeparate<["-"], "ivfsoverlay">, Group<clang_i_Group>, Flags<[CC1Option]>,
   HelpText<"Overlay the virtual filesystem described by file over the real file system">;
+def ivfsoverlay_lib : JoinedOrSeparate<["-"], "ivfsoverlay-lib">, Group<clang_i_Group>, Flags<[CC1Option]>,
+  HelpText<"Load the virtual filesystem from shared library">;
 def imultilib : Separate<["-"], "imultilib">, Group<gfortran_Group>;
 def keep__private__externs : Flag<["-"], "keep_private_externs">;
 def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to