Skip to content

Commit f359cef

Browse files
committed
[ClangImporter] Merge Swift & Clang VFS
The clang importer has to deal with two virtual file systems, one coming from clang, and one coming from swift. Currently, if both are set, we emit a diagnostic that we'll pick the swift one. This commit changes that, by merging the two virtual file systems into a single overlay file system, and using that. To make this possible, we always initialize the file manager with an overlay file system. In the clang importer, we then create a new overlay file system, starting with the one coming from clang, and adding overlays from swift on top. The motivation for this change is the reproducer infrastructure in LLDB, which adds a third virtual file system to the mix.
1 parent 6bf46b9 commit f359cef

File tree

10 files changed

+76
-37
lines changed

10 files changed

+76
-37
lines changed

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,6 @@ WARNING(implicit_bridging_header_imported_from_module,none,
9191
"is deprecated and will be removed in a later version of Swift",
9292
(StringRef, Identifier))
9393

94-
WARNING(clang_vfs_overlay_is_ignored,none,
95-
"ignoring '-ivfsoverlay' options provided to '-Xcc' in favor of "
96-
"'-vfsoverlay'", ())
97-
9894
#ifndef DIAG_NO_UNDEF
9995
# if defined(DIAG)
10096
# undef DIAG

include/swift/Basic/SourceManager.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,16 @@
2323

2424
namespace swift {
2525

26+
static inline llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>
27+
getRealOverlayFileSystem() {
28+
return llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>(
29+
new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
30+
}
31+
2632
/// This class manages and owns source buffers.
2733
class SourceManager {
2834
llvm::SourceMgr LLVMSourceMgr;
29-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem;
35+
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> FileSystem;
3036
unsigned CodeCompletionBufferID = 0U;
3137
unsigned CodeCompletionOffset;
3238

@@ -49,9 +55,9 @@ class SourceManager {
4955
mutable std::pair<const char *, const VirtualFile*> CachedVFile = {nullptr, nullptr};
5056

5157
public:
52-
SourceManager(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
53-
llvm::vfs::getRealFileSystem())
54-
: FileSystem(FS) {}
58+
SourceManager(llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> FS =
59+
getRealOverlayFileSystem())
60+
: FileSystem(FS) {}
5561

5662
llvm::SourceMgr &getLLVMSourceMgr() {
5763
return LLVMSourceMgr;
@@ -60,11 +66,12 @@ class SourceManager {
6066
return LLVMSourceMgr;
6167
}
6268

63-
void setFileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
69+
void
70+
setFileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> FS) {
6471
FileSystem = FS;
6572
}
6673

67-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> getFileSystem() {
74+
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> getFileSystem() {
6875
return FileSystem;
6976
}
7077

@@ -254,4 +261,3 @@ class SourceManager {
254261
} // end namespace swift
255262

256263
#endif // SWIFT_BASIC_SOURCEMANAGER_H
257-

lib/ClangImporter/ClangImporter.cpp

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,14 +1012,35 @@ ClangImporter::create(ASTContext &ctx,
10121012

10131013
// Set up the file manager.
10141014
{
1015-
if (!ctx.SearchPathOpts.VFSOverlayFiles.empty()) {
1016-
// If the clang instance has overlays it means the user has provided
1017-
// -ivfsoverlay options and swift -vfsoverlay options. We're going to
1018-
// clobber their file system with our own, so warn about it.
1019-
if (!instance.getHeaderSearchOpts().VFSOverlayFiles.empty()) {
1020-
ctx.Diags.diagnose(SourceLoc(), diag::clang_vfs_overlay_is_ignored);
1021-
}
1015+
if (instance.getHeaderSearchOpts().VFSOverlayFiles.empty()) {
10221016
instance.setVirtualFileSystem(ctx.SourceMgr.getFileSystem());
1017+
} else {
1018+
// Initialize the clang VFS from its compiler invocation.
1019+
instance.createFileManager();
1020+
1021+
// Create a new overlay file system for the clang importer with the clang
1022+
// VFS as its root.
1023+
auto ClangImporterFS =
1024+
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>(
1025+
new llvm::vfs::OverlayFileSystem(
1026+
&instance.getVirtualFileSystem()));
1027+
1028+
auto SwiftFS = ctx.SourceMgr.getFileSystem();
1029+
auto it = SwiftFS->overlays_rbegin();
1030+
auto end = SwiftFS->overlays_rend();
1031+
1032+
// The Swift file system is an overlay file system with the real file
1033+
// system as its root. Skip the root so we query the other overlays
1034+
// before falling back to the real file system.
1035+
it++;
1036+
1037+
// Add all remaining Swift overlay file systems to the new file system.
1038+
while (it != end) {
1039+
ClangImporterFS->pushOverlay(*it);
1040+
it++;
1041+
}
1042+
1043+
instance.setVirtualFileSystem(ClangImporterFS);
10231044
}
10241045
instance.createFileManager();
10251046
}

lib/Frontend/Frontend.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,6 @@ static bool loadAndValidateVFSOverlay(
235235
const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &BaseFS,
236236
const llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> &OverlayFS,
237237
DiagnosticEngine &Diag) {
238-
// FIXME: It should be possible to allow chained lookup of later VFS overlays
239-
// through the mapping defined by earlier overlays.
240-
// See rdar://problem/39440687
241238
auto Buffer = BaseFS->getBufferForFile(File);
242239
if (!Buffer) {
243240
Diag.diagnose(SourceLoc(), diag::cannot_open_file, File,
@@ -264,14 +261,7 @@ bool CompilerInstance::setUpVirtualFileSystemOverlays() {
264261
hadAnyFailure |=
265262
loadAndValidateVFSOverlay(File, BaseFS, OverlayFS, Diagnostics);
266263
}
267-
268-
// If we successfully loaded all the overlays, let the source manager and
269-
// diagnostic engine take advantage of the overlay file system.
270-
if (!hadAnyFailure &&
271-
(OverlayFS->overlays_begin() != OverlayFS->overlays_end())) {
272-
SourceMgr.setFileSystem(OverlayFS);
273-
}
274-
264+
SourceMgr.setFileSystem(OverlayFS);
275265
return hadAnyFailure;
276266
}
277267

lib/Frontend/ParseableInterfaceModuleLoader.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ static Optional<StringRef> getRelativeDepPath(StringRef DepPath,
273273
/// output path.
274274
/// \note Needs to be in the swift namespace so CompilerInvocation can see it.
275275
class swift::ParseableInterfaceBuilder {
276-
llvm::vfs::FileSystem &fs;
276+
llvm::vfs::OverlayFileSystem &fs;
277277
DiagnosticEngine &diags;
278278
const StringRef interfacePath;
279279
const StringRef moduleName;
@@ -765,7 +765,7 @@ class ParseableInterfaceModuleLoaderImpl {
765765
using AccessPathElem = std::pair<Identifier, SourceLoc>;
766766
friend class swift::ParseableInterfaceModuleLoader;
767767
ASTContext &ctx;
768-
llvm::vfs::FileSystem &fs;
768+
llvm::vfs::OverlayFileSystem &fs;
769769
DiagnosticEngine &diags;
770770
ModuleRebuildInfo rebuildInfo;
771771
const StringRef modulePath;

test/Frontend/Inputs/vfs/a-modulemap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
module VFSMappedModule {
22
header "VFSMappedModule.h"
33
}
4+
5+
module YetAnotherVFSMappedModule {
6+
header "YetAnotherVFSMappedModule.h"
7+
}

test/Frontend/Inputs/vfs/b-header

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#define MAJOR_SUCCESS 1
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
'version': 0,
3+
'use-external-names': false,
4+
'roots': [
5+
{
6+
'name': 'OUT_DIR', 'type': 'directory',
7+
'contents': [
8+
{ 'name': 'YetAnotherVFSMappedModule.h', 'type': 'file',
9+
'external-contents': 'INPUT_DIR/vfs/b-header'
10+
},
11+
{ 'name': 'YetAnotherVFSMappedModule.framework/Headers/VFSMappedModule.h', 'type': 'file',
12+
'external-contents': 'INPUT_DIR/vfs/b-header'
13+
},
14+
]
15+
},
16+
]
17+
}

test/Frontend/vfs.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// RUN: sed -e "s|INPUT_DIR|%/S/Inputs|g" -e "s|OUT_DIR|%/t|g" %S/Inputs/vfs/vfsoverlay.yaml > %t/overlay.yaml
33
// RUN: sed -e "s|INPUT_DIR|%/S/Inputs|g" -e "s|OUT_DIR|%/t|g" %S/Inputs/vfs/secondary-vfsoverlay.yaml > %t/secondary-overlay.yaml
44
// RUN: sed -e "s|INPUT_DIR|%/S/Inputs|g" -e "s|OUT_DIR|%/t|g" %S/Inputs/vfs/tertiary-vfsoverlay.yaml > %t/tertiary-overlay.yaml
5+
// RUN: sed -e "s|INPUT_DIR|%/S/Inputs|g" -e "s|OUT_DIR|%/t|g" %S/Inputs/vfs/quaternary-vfsoverlay.yaml > %t/quaternary-vfsoverlay.yaml
56

67
// RUN: not %target-swift-frontend -vfsoverlay %/t/overlay.yaml -typecheck %s %/t/mapped-file.swift -serialize-diagnostics-path %/t/basic.dia 2>&1 | %FileCheck -check-prefix=BASIC_MAPPING_ERROR %s
78
// RUN: c-index-test -read-diagnostics %/t/basic.dia 2>&1 | %FileCheck -check-prefix=BASIC_MAPPING_ERROR %s
@@ -20,10 +21,11 @@
2021
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %/t -DTEST_VFS_CLANG_IMPORTER -Xcc -ivfsoverlay -Xcc %/t/overlay.yaml -typecheck %/s
2122

2223
// If we see -ivfsoverlay and -vfsoverlay, we'll clobber Clang's VFS with our own.
23-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %/t -DTEST_VFS_CLANG_IMPORTER -vfsoverlay %/t/overlay.yaml -Xcc -ivfsoverlay -Xcc %/t/overlay.yaml -typecheck %/s 2>&1 | %FileCheck -check-prefix=WARN_VFS_CLOBBERED %s
24-
25-
// WARN_VFS_CLOBBERED: warning: ignoring '-ivfsoverlay' options provided to '-Xcc' in favor of '-vfsoverlay'
24+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %/t -DTEST_VFS_CLANG_IMPORTER -DTEST_VFS_CLANG_IMPORTER_MERGE -vfsoverlay %/t/overlay.yaml -Xcc -ivfsoverlay -Xcc %/t/quaternary-vfsoverlay.yaml -typecheck %/s 2>&1
2625

2726
#if TEST_VFS_CLANG_IMPORTER
2827
import VFSMappedModule
28+
#if TEST_VFS_CLANG_IMPORTER_MERGE
29+
import YetAnotherVFSMappedModule
30+
#endif
2931
#endif

unittests/FrontendTool/ModuleLoadingTests.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ class ParseableInterfaceModuleLoaderTest : public testing::Test {
8787
SourceManager sourceMgr;
8888

8989
// Create a file system that tracks how many times a file has been opened.
90-
llvm::IntrusiveRefCntPtr<OpenTrackingFileSystem> fs(
91-
new OpenTrackingFileSystem(sourceMgr.getFileSystem()));
90+
llvm::IntrusiveRefCntPtr<OpenTrackingFileSystem> baseFS(
91+
new OpenTrackingFileSystem(sourceMgr.getFileSystem()));
92+
auto fs = llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>(
93+
new llvm::vfs::OverlayFileSystem(baseFS));
9294

9395
sourceMgr.setFileSystem(fs);
9496
PrintingDiagnosticConsumer printingConsumer;
@@ -126,7 +128,7 @@ class ParseableInterfaceModuleLoaderTest : public testing::Test {
126128
ASSERT_TRUE(fs->exists(cachedModulePath));
127129

128130
// Assert that we've only opened this file once, to write it.
129-
ASSERT_EQ((unsigned)1, fs->numberOfOpens(cachedModulePath));
131+
ASSERT_EQ((unsigned)1, baseFS->numberOfOpens(cachedModulePath));
130132

131133
auto bufOrErr = fs->getBufferForFile(cachedModulePath);
132134
ASSERT_TRUE(bufOrErr);

0 commit comments

Comments
 (0)