Add a driver option -ivfsoverlay

Reads the description of a virtual filesystem from a file and overlays
it over the real file system.

llvm-svn: 202176
This commit is contained in:
Ben Langmuir 2014-02-25 18:23:47 +00:00
parent db673ca26a
commit 801272a98c
24 changed files with 182 additions and 1 deletions

View File

@ -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;
}

View File

@ -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]>;

View File

@ -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

View File

@ -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>

View File

@ -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,

View File

@ -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();

View File

@ -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

View File

@ -0,0 +1 @@
void bar(void);

View File

@ -0,0 +1,4 @@
module not_real {
header "not_real.h"
export *
}

View File

@ -0,0 +1 @@
#include "real.h"

View File

@ -0,0 +1,4 @@
{
'version': 0,
'roots': []
]

View File

@ -0,0 +1,4 @@
{
'version': 0,
'roots': [ { 'name' : 'foo', 'external-contents': 'bar' } ]
}

View File

@ -0,0 +1 @@
void from_framework(void);

View File

@ -0,0 +1,5 @@
{
'version': 0,
'unknown-key': 'value',
'roots': []
}

View File

@ -0,0 +1,5 @@
{
'version': 0,
'case-sensitive': 'Maybe?',
'roots': []
}

View File

@ -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'
}
]
}
]
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

9
clang/test/VFS/include.c Normal file
View File

@ -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();
}

View File

@ -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();
}

View File

@ -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