summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Langmuir <blangmuir@apple.com>2014-02-25 18:23:47 +0000
committerBen Langmuir <blangmuir@apple.com>2014-02-25 18:23:47 +0000
commit89de580b52889e160a604bd735fc4e79147661cb (patch)
tree44fc8ba3a2075de87bb6d5a2e542543e8732820b
parentee8d6b96cec22857c609a0ff439e237a6c4fccc5 (diff)
downloadclang-89de580b52889e160a604bd735fc4e79147661cb.tar.gz
clang-89de580b52889e160a604bd735fc4e79147661cb.tar.bz2
clang-89de580b52889e160a604bd735fc4e79147661cb.tar.xz
Add a driver option -ivfsoverlay
Reads the description of a virtual filesystem from a file and overlays it over the real file system. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@202176 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td5
-rw-r--r--include/clang/Driver/Options.td2
-rw-r--r--include/clang/Lex/HeaderSearchOptions.h7
-rw-r--r--lib/Basic/VirtualFileSystem.cpp2
-rw-r--r--lib/Frontend/CompilerInvocation.cpp4
-rw-r--r--lib/Frontend/FrontendAction.cpp26
-rw-r--r--test/Driver/vfsoverlay.c5
-rw-r--r--test/VFS/Inputs/actual_header.h1
-rw-r--r--test/VFS/Inputs/actual_module.map4
-rw-r--r--test/VFS/Inputs/include_real.h1
-rw-r--r--test/VFS/Inputs/invalid-yaml.yaml4
-rw-r--r--test/VFS/Inputs/missing-key.yaml4
-rw-r--r--test/VFS/Inputs/public_header.h1
-rw-r--r--test/VFS/Inputs/unknown-key.yaml5
-rw-r--r--test/VFS/Inputs/unknown-value.yaml5
-rw-r--r--test/VFS/Inputs/vfsoverlay.yaml21
-rw-r--r--test/VFS/framework-import.m9
-rw-r--r--test/VFS/implicit-include.c7
-rw-r--r--test/VFS/include-mixed-real-and-virtual.c14
-rw-r--r--test/VFS/include-real-from-virtual.c12
-rw-r--r--test/VFS/include-virtual-from-real.c12
-rw-r--r--test/VFS/include.c9
-rw-r--r--test/VFS/module-import.m9
-rw-r--r--test/VFS/parse-errors.c14
24 files changed, 182 insertions, 1 deletions
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index 21809ad63f..2b36d38a3f 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -158,4 +158,9 @@ def warn_module_config_macro_undef : Warning<
InGroup<ConfigMacros>;
def note_module_def_undef_here : Note<
"macro was %select{defined|#undef'd}0 here">;
+
+def err_missing_vfs_overlay_file : Error<
+ "virtual filesystem overlay file '%0' not found">, DefaultFatal;
+def err_invalid_vfs_overlay : Error<
+ "invalid virtual filesystem overlay file '%0'">, DefaultFatal;
}
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index d2192586d9..019850be3d 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -966,6 +966,8 @@ def iwithsysroot : JoinedOrSeparate<["-"], "iwithsysroot">, Group<clang_i_Group>
HelpText<"Add directory to SYSTEM include search path, "
"absolute paths are relative to -isysroot">, MetaVarName<"<directory>">,
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 i : Joined<["-"], "i">, Group<i_Group>;
def keep__private__externs : Flag<["-"], "keep_private_externs">;
def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>;
diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h
index b471b8cafe..5abcdad2d5 100644
--- a/include/clang/Lex/HeaderSearchOptions.h
+++ b/include/clang/Lex/HeaderSearchOptions.h
@@ -129,6 +129,9 @@ public:
/// \brief The set of user-provided module-map-files.
llvm::SetVector<std::string> ModuleMapFiles;
+ /// \brief The set of user-provided virtual filesystem overlay files.
+ std::vector<std::string> VFSOverlayFiles;
+
/// Include the compiler builtin includes.
unsigned UseBuiltinIncludes : 1;
@@ -172,6 +175,10 @@ public:
void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
SystemHeaderPrefixes.push_back(SystemHeaderPrefix(Prefix, IsSystemHeader));
}
+
+ void AddVFSOverlayFile(StringRef Name) {
+ VFSOverlayFiles.push_back(Name);
+ }
};
} // end namespace clang
diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp
index 881e166395..539cbb7409 100644
--- a/lib/Basic/VirtualFileSystem.cpp
+++ b/lib/Basic/VirtualFileSystem.cpp
@@ -761,7 +761,7 @@ error_code VFSFromYAML::openFileForRead(const Twine &Path,
if (!F) // FIXME: errc::not_a_file?
return error_code(errc::invalid_argument, system_category());
- return ExternalFS->openFileForRead(Path, Result);
+ return ExternalFS->openFileForRead(F->getExternalContentsPath(), Result);
}
IntrusiveRefCntPtr<FileSystem>
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 4ef5cfef7c..ad2d37cc29 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1020,6 +1020,10 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
I != E; ++I)
Opts.AddSystemHeaderPrefix((*I)->getValue(),
(*I)->getOption().matches(OPT_isystem_prefix));
+
+ for (arg_iterator I = Args.filtered_begin(OPT_ivfsoverlay),
+ E = Args.filtered_end(); I != E; ++I)
+ Opts.AddVFSOverlayFile((*I)->getValue());
}
void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index 72377d8457..6cfa12168d 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -211,6 +211,32 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
return true;
}
+ if (!CI.getHeaderSearchOpts().VFSOverlayFiles.empty()) {
+ IntrusiveRefCntPtr<vfs::OverlayFileSystem>
+ Overlay(new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+ // earlier vfs files are on the bottom
+ const std::vector<std::string> &Files =
+ CI.getHeaderSearchOpts().VFSOverlayFiles;
+ for (std::vector<std::string>::const_iterator I = Files.begin(),
+ E = Files.end();
+ I != E; ++I) {
+ OwningPtr<llvm::MemoryBuffer> Buffer;
+ if (llvm::errc::success != llvm::MemoryBuffer::getFile(*I, Buffer)) {
+ CI.getDiagnostics().Report(diag::err_missing_vfs_overlay_file) << *I;
+ goto failure;
+ }
+
+ IntrusiveRefCntPtr<vfs::FileSystem> FS =
+ vfs::getVFSFromYAML(Buffer.take(), /*DiagHandler*/0);
+ if (!FS.getPtr()) {
+ CI.getDiagnostics().Report(diag::err_invalid_vfs_overlay) << *I;
+ goto failure;
+ }
+ Overlay->pushOverlay(FS);
+ }
+ CI.setVirtualFileSystem(Overlay);
+ }
+
// Set up the file and source managers, if needed.
if (!CI.hasFileManager())
CI.createFileManager();
diff --git a/test/Driver/vfsoverlay.c b/test/Driver/vfsoverlay.c
new file mode 100644
index 0000000000..6ae494544f
--- /dev/null
+++ b/test/Driver/vfsoverlay.c
@@ -0,0 +1,5 @@
+// RUN: %clang -ivfsoverlay foo.h -### %s 2>&1 | FileCheck %s
+// CHECK: "-ivfsoverlay" "foo.h"
+
+// RUN: not %clang -ivfsoverlay foo.h %s 2>&1 | FileCheck -check-prefix=CHECK-MISSING %s
+// CHECK-MISSING: virtual filesystem overlay file 'foo.h' not found
diff --git a/test/VFS/Inputs/actual_header.h b/test/VFS/Inputs/actual_header.h
new file mode 100644
index 0000000000..f61e58620c
--- /dev/null
+++ b/test/VFS/Inputs/actual_header.h
@@ -0,0 +1 @@
+void bar(void);
diff --git a/test/VFS/Inputs/actual_module.map b/test/VFS/Inputs/actual_module.map
new file mode 100644
index 0000000000..282dac37c7
--- /dev/null
+++ b/test/VFS/Inputs/actual_module.map
@@ -0,0 +1,4 @@
+module not_real {
+ header "not_real.h"
+ export *
+}
diff --git a/test/VFS/Inputs/include_real.h b/test/VFS/Inputs/include_real.h
new file mode 100644
index 0000000000..0750c65272
--- /dev/null
+++ b/test/VFS/Inputs/include_real.h
@@ -0,0 +1 @@
+#include "real.h"
diff --git a/test/VFS/Inputs/invalid-yaml.yaml b/test/VFS/Inputs/invalid-yaml.yaml
new file mode 100644
index 0000000000..2a6c6667ce
--- /dev/null
+++ b/test/VFS/Inputs/invalid-yaml.yaml
@@ -0,0 +1,4 @@
+{
+ 'version': 0,
+ 'roots': []
+]
diff --git a/test/VFS/Inputs/missing-key.yaml b/test/VFS/Inputs/missing-key.yaml
new file mode 100644
index 0000000000..5d18c244ee
--- /dev/null
+++ b/test/VFS/Inputs/missing-key.yaml
@@ -0,0 +1,4 @@
+{
+ 'version': 0,
+ 'roots': [ { 'name' : 'foo', 'external-contents': 'bar' } ]
+}
diff --git a/test/VFS/Inputs/public_header.h b/test/VFS/Inputs/public_header.h
new file mode 100644
index 0000000000..471107762b
--- /dev/null
+++ b/test/VFS/Inputs/public_header.h
@@ -0,0 +1 @@
+void from_framework(void);
diff --git a/test/VFS/Inputs/unknown-key.yaml b/test/VFS/Inputs/unknown-key.yaml
new file mode 100644
index 0000000000..ec7d8261d9
--- /dev/null
+++ b/test/VFS/Inputs/unknown-key.yaml
@@ -0,0 +1,5 @@
+{
+ 'version': 0,
+ 'unknown-key': 'value',
+ 'roots': []
+}
diff --git a/test/VFS/Inputs/unknown-value.yaml b/test/VFS/Inputs/unknown-value.yaml
new file mode 100644
index 0000000000..4e90b2134c
--- /dev/null
+++ b/test/VFS/Inputs/unknown-value.yaml
@@ -0,0 +1,5 @@
+{
+ 'version': 0,
+ 'case-sensitive': 'Maybe?',
+ 'roots': []
+}
diff --git a/test/VFS/Inputs/vfsoverlay.yaml b/test/VFS/Inputs/vfsoverlay.yaml
new file mode 100644
index 0000000000..331ed33316
--- /dev/null
+++ b/test/VFS/Inputs/vfsoverlay.yaml
@@ -0,0 +1,21 @@
+{
+ 'version': 0,
+ 'roots': [
+ { 'name': 'OUT_DIR', 'type': 'directory',
+ 'contents': [
+ { 'name': 'not_real.h', 'type': 'file',
+ 'external-contents': 'INPUT_DIR/actual_header.h'
+ },
+ { 'name': 'module.map', 'type': 'file',
+ 'external-contents': 'INPUT_DIR/actual_module.map'
+ },
+ { 'name': 'include_real.h', 'type': 'file',
+ 'external-contents': 'INPUT_DIR/include_real.h'
+ },
+ { 'name': 'SomeFramework.framework/Headers/public_header.h', 'type': 'file',
+ 'external-contents': 'INPUT_DIR/public_header.h'
+ }
+ ]
+ }
+ ]
+}
diff --git a/test/VFS/framework-import.m b/test/VFS/framework-import.m
new file mode 100644
index 0000000000..b40bc549c0
--- /dev/null
+++ b/test/VFS/framework-import.m
@@ -0,0 +1,9 @@
+// RUN: sed -e "s:INPUT_DIR:%S/Inputs:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsoverlay.yaml > %t.yaml
+// RUN: %clang_cc1 -Werror -F %t -ivfsoverlay %t.yaml -fsyntax-only %s
+// REQUIRES: shell
+
+#import <SomeFramework/public_header.h>
+
+void foo() {
+ from_framework();
+}
diff --git a/test/VFS/implicit-include.c b/test/VFS/implicit-include.c
new file mode 100644
index 0000000000..acf665bee2
--- /dev/null
+++ b/test/VFS/implicit-include.c
@@ -0,0 +1,7 @@
+// RUN: sed -e "s:INPUT_DIR:%S/Inputs:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsoverlay.yaml > %t.yaml
+// RUN: %clang_cc1 -Werror -ivfsoverlay %t.yaml -I %t -include "not_real.h" -fsyntax-only %s
+// REQUIRES: shell
+
+void foo() {
+ bar();
+}
diff --git a/test/VFS/include-mixed-real-and-virtual.c b/test/VFS/include-mixed-real-and-virtual.c
new file mode 100644
index 0000000000..e1f5f952cd
--- /dev/null
+++ b/test/VFS/include-mixed-real-and-virtual.c
@@ -0,0 +1,14 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: echo "void baz(void);" > %t/real.h
+// RUN: sed -e "s:INPUT_DIR:%S/Inputs:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsoverlay.yaml > %t.yaml
+// RUN: %clang_cc1 -Werror -ivfsoverlay %t.yaml -I %t -fsyntax-only %s
+// REQUIRES: shell
+
+#include "not_real.h"
+#include "real.h"
+
+void foo() {
+ bar();
+ baz();
+}
diff --git a/test/VFS/include-real-from-virtual.c b/test/VFS/include-real-from-virtual.c
new file mode 100644
index 0000000000..65707b5516
--- /dev/null
+++ b/test/VFS/include-real-from-virtual.c
@@ -0,0 +1,12 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: echo "void baz(void);" > %t/real.h
+// RUN: sed -e "s:INPUT_DIR:%S/Inputs:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsoverlay.yaml > %t.yaml
+// RUN: %clang_cc1 -Werror -ivfsoverlay %t.yaml -I %t -fsyntax-only %s
+// REQUIRES: shell
+
+#include "include_real.h"
+
+void foo() {
+ baz();
+}
diff --git a/test/VFS/include-virtual-from-real.c b/test/VFS/include-virtual-from-real.c
new file mode 100644
index 0000000000..c8f6059608
--- /dev/null
+++ b/test/VFS/include-virtual-from-real.c
@@ -0,0 +1,12 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: echo '#include "not_real.h"' > %t/include_not_real.h
+// RUN: sed -e "s:INPUT_DIR:%S/Inputs:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsoverlay.yaml > %t.yaml
+// RUN: %clang_cc1 -Werror -ivfsoverlay %t.yaml -I %t -fsyntax-only %s
+// REQUIRES: shell
+
+#include "include_not_real.h"
+
+void foo() {
+ bar();
+}
diff --git a/test/VFS/include.c b/test/VFS/include.c
new file mode 100644
index 0000000000..8cd04dd452
--- /dev/null
+++ b/test/VFS/include.c
@@ -0,0 +1,9 @@
+// RUN: sed -e "s:INPUT_DIR:%S/Inputs:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsoverlay.yaml > %t.yaml
+// RUN: %clang_cc1 -Werror -I %t -ivfsoverlay %t.yaml -fsyntax-only %s
+// REQUIRES: shell
+
+#include "not_real.h"
+
+void foo() {
+ bar();
+}
diff --git a/test/VFS/module-import.m b/test/VFS/module-import.m
new file mode 100644
index 0000000000..80f0ea58f1
--- /dev/null
+++ b/test/VFS/module-import.m
@@ -0,0 +1,9 @@
+// RUN: sed -e "s:INPUT_DIR:%S/Inputs:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsoverlay.yaml > %t.yaml
+// RUN: %clang_cc1 -Werror -fmodules -fmodules-cache-path=%t -ivfsoverlay %t.yaml -I %t -fsyntax-only %s
+// REQUIRES: shell
+
+@import not_real;
+
+void foo() {
+ bar();
+}
diff --git a/test/VFS/parse-errors.c b/test/VFS/parse-errors.c
new file mode 100644
index 0000000000..7194efc65a
--- /dev/null
+++ b/test/VFS/parse-errors.c
@@ -0,0 +1,14 @@
+// RUN: not %clang_cc1 -ivfsoverlay %S/Inputs/invalid-yaml.yaml -fsyntax-only %s 2>&1 | FileCheck %s
+// CHECK: invalid virtual filesystem overlay file
+
+// RUN: not %clang_cc1 -ivfsoverlay %S/Inputs/missing-key.yaml -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-MISSING-TYPE %s
+// CHECK-MISSING-TYPE: missing key 'type'
+// CHECK-MISSING-TYPE: invalid virtual filesystem overlay file
+
+// RUN: not %clang_cc1 -ivfsoverlay %S/Inputs/unknown-key.yaml -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-UNKNOWN-KEY %s
+// CHECK-UNKNOWN-KEY: unknown key
+// CHECK-UNKNOWN-KEY: invalid virtual filesystem overlay file
+
+// RUN: not %clang_cc1 -ivfsoverlay %S/Inputs/unknown-value.yaml -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-UNKNOWN-VALUE %s
+// CHECK-UNKNOWN-VALUE: expected boolean value
+// CHECK-UNKNOWN-VALUE: invalid virtual filesystem overlay file