Skip to content

Commit

Permalink
[VFS] Add property 'fallthrough' that controls fallback to real file …
Browse files Browse the repository at this point in the history
…system.

Default property value 'true' preserves current behavior. Value 'false' can be
used to create VFS "root", file system that gives better control over which
files compiler can use during compilation as there are no unpredictable
accesses to real file system.

Non-fallthrough use case changes how we treat multiple VFS overlay
files. Instead of all of them being at the same level just above a real
file system, now they are nested and subsequent overlays can refer to
files in previous overlays.

Change is done both in LLVM and Clang, corresponding LLVM commit is r345431.

rdar://problem/39465552

Reviewers: bruno, benlangmuir

Reviewed By: bruno

Subscribers: dexonsmith, cfe-commits, hiraditya

Differential Revision: https://reviews.llvm.org/D50539

llvm-svn: 345432
  • Loading branch information
vsapsai committed Oct 26, 2018
1 parent 91e1316 commit f239a44
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 8 deletions.
18 changes: 10 additions & 8 deletions clang/lib/Frontend/CompilerInvocation.cpp
Expand Up @@ -3297,25 +3297,27 @@ IntrusiveRefCntPtr<llvm::vfs::FileSystem> createVFSFromCompilerInvocation(
if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
return BaseFS;

IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> Overlay(
new llvm::vfs::OverlayFileSystem(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 =
BaseFS->getBufferForFile(File);
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);
if (FS)
Overlay->pushOverlay(FS);
else
std::move(Buffer.get()), /*DiagHandler*/ nullptr, File,
/*DiagContext*/ nullptr, Result);
if (!FS) {
Diags.Report(diag::err_invalid_vfs_overlay) << File;
continue;
}

Result = FS;
}
return Overlay;
return Result;
}

} // namespace clang
3 changes: 3 additions & 0 deletions clang/test/VFS/Inputs/Broken.framework/Headers/Error.h
@@ -0,0 +1,3 @@
// Error.h

#error Should not include this header in a module
@@ -0,0 +1,6 @@
framework module Broken [extern_c] {
umbrella "Headers"
export *
module * { export * }
}

1 change: 1 addition & 0 deletions clang/test/VFS/Inputs/Broken.framework/VFSHeaders/A.h
@@ -0,0 +1 @@
// A.h
55 changes: 55 additions & 0 deletions clang/test/VFS/Inputs/vfsroot.yaml
@@ -0,0 +1,55 @@
{
'version': 0,
'use-external-names': false,
'fallthrough': false,
'roots': [
{ 'name': '/tests', 'type': 'directory',
'contents': [
{ 'name': 'vfsroot-include.c', 'type': 'file',
'external-contents': 'TEST_DIR/vfsroot-include.c'
},
{ 'name': 'vfsroot-with-overlay.c', 'type': 'file',
'external-contents': 'TEST_DIR/vfsroot-with-overlay.c'
},
{ 'name': 'vfsroot-module.m', 'type': 'file',
'external-contents': 'TEST_DIR/vfsroot-module.m'
}
]
},
{ 'name': '/direct-vfs-root-files', 'type': 'directory',
'contents': [
{ 'name': 'not_real.h', 'type': 'file',
'external-contents': 'TEST_DIR/Inputs/actual_header.h'
},
{ 'name': 'vfsoverlay.yaml', 'type': 'file',
'external-contents': 'OUT_DIR/vfsoverlay.yaml'
}
]
},
{ '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',
'external-contents': 'TEST_DIR/Inputs/Broken.framework/VFSHeaders/A.h'
},
{ 'name': 'Modules/module.modulemap', 'type': 'file',
'external-contents': 'TEST_DIR/Inputs/Broken.framework/Modules/module.modulemap'
}
]
},
# Locations for modules.
{ 'name': 'OUT_DIR/cache', 'type': 'directory',
'contents': [
{ 'name': 'Broken.pcm', 'type': 'file',
'external-contents': 'OUT_DIR/cache/Broken.pcm'
}
]
}
]
}
17 changes: 17 additions & 0 deletions clang/test/VFS/vfsroot-include.c
@@ -0,0 +1,17 @@
// REQUIRES: shell
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: sed -e "s:TEST_DIR:%S:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsroot.yaml > %t.yaml
// RUN: not %clang_cc1 -Werror -ivfsoverlay %t.yaml -I %S/Inputs -I /direct-vfs-root-files -fsyntax-only /tests/vfsroot-include.c 2>&1 | FileCheck %s
// The line above tests that the compiler input file is looked up through VFS.

// Test successful include through the VFS.
#include "not_real.h"

// Test that a file missing from the VFS root is not found, even if it is
// discoverable through the real file system. Fatal error should be the last
// in the file as it hides other errors.
#include "actual_header.h"
// CHECK: fatal error: 'actual_header.h' file not found
// CHECK: 1 error generated.
// CHECK-NOT: error
10 changes: 10 additions & 0 deletions clang/test/VFS/vfsroot-module.m
@@ -0,0 +1,10 @@
// REQUIRES: shell
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: sed -e "s:TEST_DIR:%S:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsroot.yaml > %t.yaml
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/cache -ivfsoverlay %t.yaml -F %S/Inputs -fsyntax-only /tests/vfsroot-module.m

// Test that a file missing from the VFS root is not found, even if it is
// discoverable through the real file system at location that is a part of
// the framework.
@import Broken;
12 changes: 12 additions & 0 deletions clang/test/VFS/vfsroot-with-overlay.c
@@ -0,0 +1,12 @@
// REQUIRES: shell
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: sed -e "s:TEST_DIR:%S:g" -e "s:OUT_DIR:%t: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: %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"

void foo() {
bar();
}

0 comments on commit f239a44

Please sign in to comment.