Skip to content

Commit 502f14d

Browse files
bnbarhamkeith
authored andcommitted
[VFS] Add a "redirecting-with" field to overlays
Extend "fallthrough" to allow a third option: "fallback". Fallthrough allows the original path to used if the redirected (or mapped) path fails. Fallback is the reverse of this, ie. use the original path and fallback to the mapped path otherwise. While this result *can* be achieved today using multiple overlays, this adds a much more intuitive option. As an example, take two directories "A" and "B". We would like files from "A" to be used, unless they don't exist, in which case the VFS should fallback to those in "B". With the current fallthrough option this is possible by adding two overlays: one mapping from A -> B and another mapping from B -> A. Since the frontend *nests* the two RedirectingFileSystems, the result will be that "A" is mapped to "B" and back to "A", unless it isn't in "A" in which case it fallsthrough to "B" (or fails if it exists in neither). Using "fallback" semantics allows a single overlay instead: one mapping from "A" to "B" but only using that mapping if the operation in "A" fails first. "redirect-only" is used to represent the current "fallthrough: false" case. Differential Revision: https://reviews.llvm.org/D117937
1 parent 95d609b commit 502f14d

File tree

7 files changed

+486
-86
lines changed

7 files changed

+486
-86
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
'redirecting-with': 'fallthrough',
3+
'fallthrough': true,
4+
'roots': [
5+
{
6+
'type': 'directory-remap',
7+
'name': '//root/a',
8+
'external-contents': '//root/b'
9+
}
10+
]
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
'redirecting-with': 'none',
3+
'roots': [
4+
{
5+
'type': 'directory-remap',
6+
'name': '//root/a',
7+
'external-contents': '//root/b'
8+
}
9+
]
10+
}

clang/test/VFS/fallback.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
4+
// Test fallback directory remapping, ie. a directory "Base" which is used as
5+
// a fallback if files are missing from "UseFirst"
6+
7+
// RUN: sed -e "s@EXTERNAL_DIR@%{/t:regex_replacement}/Both/Base@g" -e "s@NAME_DIR@%{/t:regex_replacement}/Both/UseFirst@g" %t/vfs/base.yaml > %t/vfs/both.yaml
8+
9+
// RUN: cp -R %t/Both %t/UseFirstOnly
10+
// RUN: rm -rf %t/UseFirstOnly/Base
11+
// RUN: sed -e "s@EXTERNAL_DIR@%{/t:regex_replacement}/UseFirstOnly/Base@g" -e "s@NAME_DIR@%{/t:regex_replacement}/UseFirstOnly/UseFirst@g" %t/vfs/base.yaml > %t/vfs/use-first-only.yaml
12+
13+
// RUN: cp -R %t/Both %t/BaseOnly
14+
// RUN: rm -rf %t/BaseOnly/UseFirst
15+
// RUN: sed -e "s@EXTERNAL_DIR@%{/t:regex_replacement}/BaseOnly/Base@g" -e "s@NAME_DIR@%{/t:regex_replacement}/BaseOnly/UseFirst@g" %t/vfs/base.yaml > %t/vfs/base-only.yaml
16+
17+
// RUN: cp -R %t/Both %t/BFallback
18+
// RUN: rm %t/BFallback/UseFirst/B.h
19+
// RUN: sed -e "s@EXTERNAL_DIR@%{/t:regex_replacement}/BFallback/Base@g" -e "s@NAME_DIR@%{/t:regex_replacement}/BFallback/UseFirst@g" %t/vfs/base.yaml > %t/vfs/b-fallback.yaml
20+
21+
// RUN: cp -R %t/Both %t/CFallback
22+
// RUN: rm %t/CFallback/UseFirst/C.h
23+
// RUN: sed -e "s@EXTERNAL_DIR@%{/t:regex_replacement}/CFallback/Base@g" -e "s@NAME_DIR@%{/t:regex_replacement}/CFallback/UseFirst@g" %t/vfs/base.yaml > %t/vfs/c-fallback.yaml
24+
25+
// Both B.h and C.h are in both folders
26+
// RUN: %clang_cc1 -Werror -I %t/Both/UseFirst -ivfsoverlay %t/vfs/both.yaml -fsyntax-only -E -C %t/main.c 2>&1 | FileCheck --check-prefix=IN_UF %s
27+
28+
// IN_UF: # 1 "{{.*(/|\\\\)UseFirst(/|\\\\)}}B.h"
29+
// IN_UF-NEXT: // B.h in UseFirst
30+
// IN_UF: # 1 "{{.*(/|\\\\)UseFirst(/|\\\\)}}C.h"
31+
// IN_UF-NEXT: // C.h in UseFirst
32+
33+
// Base missing, so now they are only in UseFirst
34+
// RUN: %clang_cc1 -Werror -I %t/UseFirstOnly/UseFirst -ivfsoverlay %t/vfs/use-first-only.yaml -fsyntax-only -E -C %t/main.c 2>&1 | FileCheck --check-prefix=IN_UF %s
35+
36+
// UseFirst missing, fallback to Base
37+
// RUN: %clang_cc1 -Werror -I %t/BaseOnly/UseFirst -ivfsoverlay %t/vfs/base-only.yaml -fsyntax-only -E -C %t/main.c 2>&1 | FileCheck --check-prefix=IN_BASE %s
38+
39+
// IN_BASE: # 1 "{{.*(/|\\\\)Base(/|\\\\)}}B.h"
40+
// IN_BASE-NEXT: // B.h in Base
41+
// IN_BASE: # 1 "{{.*(/|\\\\)Base(/|\\\\)}}C.h"
42+
// IN_BASE-NEXT: // C.h in Base
43+
44+
// B.h missing from UseFirst
45+
// RUN: %clang_cc1 -Werror -I %t/BFallback/UseFirst -ivfsoverlay %t/vfs/b-fallback.yaml -fsyntax-only -E -C %t/main.c 2>&1 | FileCheck --check-prefix=B_FALLBACK %s
46+
47+
// B_FALLBACK: # 1 "{{.*(/|\\\\)Base(/|\\\\)}}B.h"
48+
// B_FALLBACK-NEXT: // B.h in Base
49+
// B_FALLBACK: # 1 "{{.*(/|\\\\)UseFirst(/|\\\\)}}C.h"
50+
// B_FALLBACK-NEXT: // C.h in UseFirst
51+
52+
// C.h missing from UseFirst
53+
// RUN: %clang_cc1 -Werror -I %t/CFallback/UseFirst -ivfsoverlay %t/vfs/c-fallback.yaml -fsyntax-only -E -C %t/main.c 2>&1 | FileCheck --check-prefix=C_FALLBACK %s
54+
55+
// C_FALLBACK: # 1 "{{.*(/|\\\\)UseFirst(/|\\\\)}}B.h"
56+
// C_FALLBACK-NEXT: // B.h in UseFirst
57+
// C_FALLBACK: # 1 "{{.*(/|\\\\)Base(/|\\\\)}}C.h"
58+
// C_FALLBACK-NEXT: // C.h in Base
59+
60+
//--- main.c
61+
#include "B.h"
62+
63+
//--- Both/UseFirst/B.h
64+
// B.h in UseFirst
65+
#include "C.h"
66+
67+
//--- Both/UseFirst/C.h
68+
// C.h in UseFirst
69+
70+
//--- Both/Base/B.h
71+
// B.h in Base
72+
#include "C.h"
73+
74+
//--- Both/Base/C.h
75+
// C.h in Base
76+
77+
//--- vfs/base.yaml
78+
{
79+
'version' : 0,
80+
'redirecting-with' : 'fallback',
81+
'roots' : [
82+
{'name' : 'NAME_DIR',
83+
'type' : 'directory-remap',
84+
'external-contents' : 'EXTERNAL_DIR'}
85+
]
86+
}

clang/test/VFS/parse-errors.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,11 @@
1212
// RUN: not %clang_cc1 -ivfsoverlay %S/Inputs/unknown-value.yaml -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-UNKNOWN-VALUE %s
1313
// CHECK-UNKNOWN-VALUE: expected boolean value
1414
// CHECK-UNKNOWN-VALUE: invalid virtual filesystem overlay file
15+
16+
// RUN: not %clang_cc1 -ivfsoverlay %S/Inputs/unknown-redirect.yaml -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-REDIRECT %s
17+
// CHECK-REDIRECT: expected valid redirect kind
18+
// CHECK-REDIRECT: invalid virtual filesystem overlay file
19+
20+
// RUN: not %clang_cc1 -ivfsoverlay %S/Inputs/redirect-and-fallthrough.yaml -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-EXCLUSIVE-KEYS %s
21+
// CHECK-EXCLUSIVE-KEYS: 'fallthrough' and 'redirecting-with' are mutually exclusive
22+
// CHECK-EXCLUSIVE-KEYS: invalid virtual filesystem overlay file

llvm/include/llvm/Support/VirtualFileSystem.h

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,10 @@ class RedirectingFileSystemParser;
571571
/// 'case-sensitive': <boolean, default=(true for Posix, false for Windows)>
572572
/// 'use-external-names': <boolean, default=true>
573573
/// 'overlay-relative': <boolean, default=false>
574-
/// 'fallthrough': <boolean, default=true>
574+
/// 'fallthrough': <boolean, default=true, deprecated - use 'redirecting-with'
575+
/// instead>
576+
/// 'redirecting-with': <string, one of 'fallthrough', 'fallback', or
577+
/// 'redirect-only', default='fallthrough'>
575578
///
576579
/// Virtual directories that list their contents are represented as
577580
/// \verbatim
@@ -642,6 +645,20 @@ class RedirectingFileSystem : public vfs::FileSystem {
642645
enum EntryKind { EK_Directory, EK_DirectoryRemap, EK_File };
643646
enum NameKind { NK_NotSet, NK_External, NK_Virtual };
644647

648+
/// The type of redirection to perform.
649+
enum class RedirectKind {
650+
/// Lookup the redirected path first (ie. the one specified in
651+
/// 'external-contents') and if that fails "fallthrough" to a lookup of the
652+
/// originally provided path.
653+
Fallthrough,
654+
/// Lookup the provided path first and if that fails, "fallback" to a
655+
/// lookup of the redirected path.
656+
Fallback,
657+
/// Only lookup the redirected path, do not lookup the originally provided
658+
/// path.
659+
RedirectOnly
660+
};
661+
645662
/// A single file or directory in the VFS.
646663
class Entry {
647664
EntryKind Kind;
@@ -776,17 +793,11 @@ class RedirectingFileSystem : public vfs::FileSystem {
776793
friend class RedirectingFSDirIterImpl;
777794
friend class RedirectingFileSystemParser;
778795

779-
bool shouldUseExternalFS() const { return IsFallthrough; }
780-
781796
/// Canonicalize path by removing ".", "..", "./", components. This is
782797
/// a VFS request, do not bother about symlinks in the path components
783798
/// but canonicalize in order to perform the correct entry search.
784799
std::error_code makeCanonical(SmallVectorImpl<char> &Path) const;
785800

786-
/// Whether to fall back to the external file system when an operation fails
787-
/// with the given error code on a path associated with the provided Entry.
788-
bool shouldFallBackToExternalFS(std::error_code EC, Entry *E = nullptr) const;
789-
790801
/// Get the File status, or error, from the underlying external file system.
791802
/// This returns the status with the originally requested name, while looking
792803
/// up the entry using the canonical path.
@@ -834,9 +845,9 @@ class RedirectingFileSystem : public vfs::FileSystem {
834845
/// names of files. This global value is overridable on a per-file basis.
835846
bool UseExternalNames = true;
836847

837-
/// Whether to attempt a file lookup in external file system after it wasn't
838-
/// found in VFS.
839-
bool IsFallthrough = true;
848+
/// Determines the lookups to perform, as well as their order. See
849+
/// \c RedirectKind for details.
850+
RedirectKind Redirection = RedirectKind::Fallthrough;
840851
/// @}
841852

842853
RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS);
@@ -891,7 +902,7 @@ class RedirectingFileSystem : public vfs::FileSystem {
891902

892903
StringRef getExternalContentsPrefixDir() const;
893904

894-
void setFallthrough(bool Fallthrough);
905+
void setRedirection(RedirectingFileSystem::RedirectKind Kind);
895906

896907
std::vector<llvm::StringRef> getRoots() const;
897908

0 commit comments

Comments
 (0)