haowei updated this revision to Diff 474391.
haowei added a comment.
Add additional unit test.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D137473/new/
https://reviews.llvm.org/D137473
Files:
clang/test/VFS/Inputs/root-relative-overlay.yaml
clang/test/VFS/relative-path.c
llvm/include/llvm/Support/VirtualFileSystem.h
llvm/lib/Support/VirtualFileSystem.cpp
llvm/unittests/Support/VirtualFileSystemTest.cpp
Index: llvm/unittests/Support/VirtualFileSystemTest.cpp
===================================================================
--- llvm/unittests/Support/VirtualFileSystemTest.cpp
+++ llvm/unittests/Support/VirtualFileSystemTest.cpp
@@ -1452,18 +1452,20 @@
std::unique_ptr<vfs::FileSystem>
getFromYAMLRawString(StringRef Content,
- IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) {
+ IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS,
+ StringRef YAMLFilePath = "") {
std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(Content);
- return getVFSFromYAML(std::move(Buffer), CountingDiagHandler, "", this,
- ExternalFS);
+ return getVFSFromYAML(std::move(Buffer), CountingDiagHandler, YAMLFilePath,
+ this, ExternalFS);
}
std::unique_ptr<vfs::FileSystem> getFromYAMLString(
StringRef Content,
- IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) {
+ IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem(),
+ StringRef YAMLFilePath = "") {
std::string VersionPlusContent("{\n 'version':0,\n");
VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos);
- return getFromYAMLRawString(VersionPlusContent, ExternalFS);
+ return getFromYAMLRawString(VersionPlusContent, ExternalFS, YAMLFilePath);
}
// This is intended as a "XFAIL" for windows hosts.
@@ -1849,6 +1851,45 @@
EXPECT_EQ(0, NumDiagnostics);
}
+TEST_F(VFSFromYAMLTest, RootRelativeTest) {
+ IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+ Lower->addDirectory("//root/foo/bar");
+ Lower->addRegularFile("//root/foo/bar/a");
+ IntrusiveRefCntPtr<vfs::FileSystem> FS =
+ getFromYAMLString("{\n"
+ " 'case-sensitive': false,\n"
+ " 'root-relative': 'overlay-dir',\n"
+ " 'roots': [\n"
+ " { 'name': 'b', 'type': 'file',\n"
+ " 'external-contents': '//root/foo/bar/a'\n"
+ " }\n"
+ " ]\n"
+ "}",
+ Lower, "//root/foo/bar/overlay");
+
+ ASSERT_NE(FS.get(), nullptr);
+ ErrorOr<vfs::Status> S = FS->status("//root/foo/bar/b");
+ ASSERT_FALSE(S.getError());
+ EXPECT_EQ("//root/foo/bar/a", S->getName());
+
+ IntrusiveRefCntPtr<vfs::FileSystem> FSOverlayRelative =
+ getFromYAMLString("{\n"
+ " 'case-sensitive': false,\n"
+ " 'overlay-relative': true,\n"
+ " 'root-relative': 'overlay-dir',\n"
+ " 'roots': [\n"
+ " { 'name': 'b', 'type': 'file',\n"
+ " 'external-contents': 'a'\n"
+ " }\n"
+ " ]\n"
+ "}",
+ Lower, "//root/foo/bar/overlay");
+ ASSERT_NE(FSOverlayRelative.get(), nullptr);
+ ErrorOr<vfs::Status> SOverlayRelative = FS->status("//root/foo/bar/b");
+ ASSERT_FALSE(SOverlayRelative.getError());
+ EXPECT_EQ("//root/foo/bar/a", SOverlayRelative->getName());
+}
+
TEST_F(VFSFromYAMLTest, ReturnsInternalPathVFSHit) {
IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS(
new vfs::InMemoryFileSystem);
Index: llvm/lib/Support/VirtualFileSystem.cpp
===================================================================
--- llvm/lib/Support/VirtualFileSystem.cpp
+++ llvm/lib/Support/VirtualFileSystem.cpp
@@ -1482,12 +1482,12 @@
return Combined;
}
-void RedirectingFileSystem::setExternalContentsPrefixDir(StringRef PrefixDir) {
- ExternalContentsPrefixDir = PrefixDir.str();
+void RedirectingFileSystem::setOverlayFileDir(StringRef Dir) {
+ OverlayFileDir = Dir.str();
}
-StringRef RedirectingFileSystem::getExternalContentsPrefixDir() const {
- return ExternalContentsPrefixDir;
+StringRef RedirectingFileSystem::getOverlayFileDir() const {
+ return OverlayFileDir;
}
void RedirectingFileSystem::setFallthrough(bool Fallthrough) {
@@ -1621,6 +1621,20 @@
return None;
}
+ Optional<RedirectingFileSystem::RootRelativeKind>
+ parseRootRelativeKind(yaml::Node *N) {
+ SmallString<12> Storage;
+ StringRef Value;
+ if (!parseScalarString(N, Value, Storage))
+ return None;
+ if (Value.equals_insensitive("cwd")) {
+ return RedirectingFileSystem::RootRelativeKind::CWD;
+ } else if (Value.equals_insensitive("overlay-dir")) {
+ return RedirectingFileSystem::RootRelativeKind::OverlayDir;
+ }
+ return None;
+ }
+
struct KeyStatus {
bool Required;
bool Seen = false;
@@ -1828,7 +1842,7 @@
SmallString<256> FullPath;
if (FS->IsRelativeOverlay) {
- FullPath = FS->getExternalContentsPrefixDir();
+ FullPath = FS->getOverlayFileDir();
assert(!FullPath.empty() &&
"External contents prefix directory must exist");
llvm::sys::path::append(FullPath, Value);
@@ -1884,6 +1898,15 @@
} else if (sys::path::is_absolute(Name,
sys::path::Style::windows_backslash)) {
path_style = sys::path::Style::windows_backslash;
+ } else if (FS->RootRelative ==
+ RedirectingFileSystem::RootRelativeKind::OverlayDir) {
+ SmallString<256> FullPath = FS->getOverlayFileDir();
+ assert(!FullPath.empty() && "Overlay file directory must exist");
+ sys::fs::make_absolute(FS->getOverlayFileDir(), Name);
+ Name = canonicalize(Name);
+ path_style = sys::path::is_absolute(Name, sys::path::Style::posix)
+ ? sys::path::Style::posix
+ : sys::path::Style::windows_backslash;
} else {
// Relative VFS root entries are made absolute to the current working
// directory, then we can determine the path style from that.
@@ -1962,6 +1985,7 @@
KeyStatusPair("version", true),
KeyStatusPair("case-sensitive", false),
KeyStatusPair("use-external-names", false),
+ KeyStatusPair("root-relative", false),
KeyStatusPair("overlay-relative", false),
KeyStatusPair("fallthrough", false),
KeyStatusPair("redirecting-with", false),
@@ -2051,6 +2075,13 @@
error(I.getValue(), "expected valid redirect kind");
return false;
}
+ } else if (Key == "root-relative") {
+ if (auto Kind = parseRootRelativeKind(I.getValue())) {
+ FS->RootRelative = *Kind;
+ } else {
+ error(I.getValue(), "expected valid root-relative kind");
+ return false;
+ }
} else {
llvm_unreachable("key missing from Keys");
}
@@ -2100,13 +2131,13 @@
// Example:
// -ivfsoverlay dummy.cache/vfs/vfs.yaml
// yields:
- // FS->ExternalContentsPrefixDir => /<absolute_path_to>/dummy.cache/vfs
+ // FS->OverlayFileDir => /<absolute_path_to>/dummy.cache/vfs
//
SmallString<256> OverlayAbsDir = sys::path::parent_path(YAMLFilePath);
std::error_code EC = llvm::sys::fs::make_absolute(OverlayAbsDir);
assert(!EC && "Overlay dir final path must be absolute");
(void)EC;
- FS->setExternalContentsPrefixDir(OverlayAbsDir);
+ FS->setOverlayFileDir(OverlayAbsDir);
}
if (!P.parse(Root, FS.get()))
Index: llvm/include/llvm/Support/VirtualFileSystem.h
===================================================================
--- llvm/include/llvm/Support/VirtualFileSystem.h
+++ llvm/include/llvm/Support/VirtualFileSystem.h
@@ -651,17 +651,28 @@
/// \endverbatim
///
/// The roots may be absolute or relative. If relative they will be made
-/// absolute against the current working directory.
+/// absolute against either current working directory or the directory where
+/// the Overlay YAML file is located, depending on the 'root-relative'
+/// configuration.
///
/// All configuration options are optional.
/// 'case-sensitive': <boolean, default=(true for Posix, false for Windows)>
/// 'use-external-names': <boolean, default=true>
+/// 'root-relative': <string, one of 'cwd' or 'overlay-dir', default='cwd'>
/// 'overlay-relative': <boolean, default=false>
/// 'fallthrough': <boolean, default=true, deprecated - use 'redirecting-with'
/// instead>
/// 'redirecting-with': <string, one of 'fallthrough', 'fallback', or
/// 'redirect-only', default='fallthrough'>
///
+/// To clarify, 'root-relative' option will prepend the current working
+/// directory, or the overlay directory to the 'roots->name' field only if
+/// 'roots->name' is a relative path. On the other hand, when 'overlay-relative'
+/// is set to 'true', external paths will always be prepended with the overlay
+/// directory, even if external paths are not relative paths. The
+/// 'root-relative' option has no interaction with the 'overlay-relative'
+/// option.
+///
/// Virtual directories that list their contents are represented as
/// \verbatim
/// {
@@ -745,6 +756,15 @@
RedirectOnly
};
+ /// The type of relative path used by Roots.
+ enum class RootRelativeKind {
+ /// The roots are relative to the current working directory.
+ CWD,
+ /// The roots are relative to the directory where the Overlay YAML file
+ // locates.
+ OverlayDir
+ };
+
/// A single file or directory in the VFS.
class Entry {
EntryKind Kind;
@@ -910,10 +930,11 @@
/// The file system to use for external references.
IntrusiveRefCntPtr<FileSystem> ExternalFS;
- /// If IsRelativeOverlay is set, this represents the directory
- /// path that should be prefixed to each 'external-contents' entry
- /// when reading from YAML files.
- std::string ExternalContentsPrefixDir;
+ /// This represents the directory path that the YAML file is located.
+ /// This will be prefixed to each 'external-contents' if IsRelativeOverlay
+ /// is set. This will also be prefixed to each 'roots->name' if RootRelative
+ /// is set to RootRelativeKind::OverlayDir and the path is relative.
+ std::string OverlayFileDir;
/// @name Configuration
/// @{
@@ -923,7 +944,7 @@
/// Currently, case-insensitive matching only works correctly with ASCII.
bool CaseSensitive = is_style_posix(sys::path::Style::native);
- /// IsRelativeOverlay marks whether a ExternalContentsPrefixDir path must
+ /// IsRelativeOverlay marks whether a OverlayFileDir path must
/// be prefixed in every 'external-contents' when reading from YAML files.
bool IsRelativeOverlay = false;
@@ -934,6 +955,10 @@
/// Determines the lookups to perform, as well as their order. See
/// \c RedirectKind for details.
RedirectKind Redirection = RedirectKind::Fallthrough;
+
+ /// Determine the prefix directory if the roots are relative paths. See
+ /// \c RootRelativeKind for details.
+ RootRelativeKind RootRelative = RootRelativeKind::CWD;
/// @}
RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS);
@@ -984,9 +1009,9 @@
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
- void setExternalContentsPrefixDir(StringRef PrefixDir);
+ void setOverlayFileDir(StringRef PrefixDir);
- StringRef getExternalContentsPrefixDir() const;
+ StringRef getOverlayFileDir() const;
/// Sets the redirection kind to \c Fallthrough if true or \c RedirectOnly
/// otherwise. Will removed in the future, use \c setRedirection instead.
Index: clang/test/VFS/relative-path.c
===================================================================
--- clang/test/VFS/relative-path.c
+++ clang/test/VFS/relative-path.c
@@ -3,6 +3,13 @@
// RUN: sed -e "s@INPUT_DIR@%{/S:regex_replacement}/Inputs@g" -e "s@OUT_DIR@%{/t:regex_replacement}@g" %S/Inputs/vfsoverlay.yaml > %t.yaml
// RUN: %clang_cc1 -Werror -I . -ivfsoverlay %t.yaml -fsyntax-only %s
+// RUN: cp %S/Inputs/actual_header.h %t/actual_header.h
+// RUN: sed -e "s@OVERLAY_DIR@true@g" -e "s@EXTERNAL_DIR@.@g" %S/Inputs/root-relative-overlay.yaml > %t/root-relative-overlay.yaml
+// RUN: %clang_cc1 -Werror -I %t -ivfsoverlay %t/root-relative-overlay.yaml -fsyntax-only %s
+
+// RUN: sed -e "s@OVERLAY_DIR@false@g" -e "s@EXTERNAL_DIR@%{/t:regex_replacement}@g" %S/Inputs/root-relative-overlay.yaml > %t/root-relative-overlay2.yaml
+// RUN: %clang_cc1 -Werror -I %t -ivfsoverlay %t/root-relative-overlay2.yaml -fsyntax-only %s
+
#include "not_real.h"
void foo(void) {
Index: clang/test/VFS/Inputs/root-relative-overlay.yaml
===================================================================
--- /dev/null
+++ clang/test/VFS/Inputs/root-relative-overlay.yaml
@@ -0,0 +1,11 @@
+{
+ 'version': 0,
+ 'case-sensitive': false,
+ 'overlay-relative': OVERLAY_DIR,
+ 'root-relative': 'overlay-dir',
+ 'roots': [
+ { 'name': 'not_real.h', 'type': 'file',
+ 'external-contents': 'EXTERNAL_DIR/actual_header.h'
+ },
+ ]
+}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits