forked from OSchip/llvm-project
[VFS] Emit an error when entry at root level uses a relative path.
Entries with only a filename prevent us from building a file system tree and cause the assertion > Assertion failed: (NewParentE && "Parent entry must exist"), function uniqueOverlayTree, file clang/lib/Basic/VirtualFileSystem.cpp, line 1303. Entries with a relative path are simply not discoverable during header search. rdar://problem/28990865 Reviewers: bruno, benlangmuir Reviewed By: bruno Subscribers: dexonsmith, cfe-commits Differential Revision: https://reviews.llvm.org/D49518 llvm-svn: 339164
This commit is contained in:
parent
98dbbfd851
commit
3b2f6a4b29
|
@ -1281,7 +1281,8 @@ class RedirectingFileSystemParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Entry> parseEntry(yaml::Node *N, RedirectingFileSystem *FS) {
|
std::unique_ptr<Entry> parseEntry(yaml::Node *N, RedirectingFileSystem *FS,
|
||||||
|
bool IsRootEntry) {
|
||||||
auto *M = dyn_cast<yaml::MappingNode>(N);
|
auto *M = dyn_cast<yaml::MappingNode>(N);
|
||||||
if (!M) {
|
if (!M) {
|
||||||
error(N, "expected mapping node for file or directory entry");
|
error(N, "expected mapping node for file or directory entry");
|
||||||
|
@ -1302,6 +1303,7 @@ class RedirectingFileSystemParser {
|
||||||
std::vector<std::unique_ptr<Entry>> EntryArrayContents;
|
std::vector<std::unique_ptr<Entry>> EntryArrayContents;
|
||||||
std::string ExternalContentsPath;
|
std::string ExternalContentsPath;
|
||||||
std::string Name;
|
std::string Name;
|
||||||
|
yaml::Node *NameValueNode;
|
||||||
auto UseExternalName = RedirectingFileEntry::NK_NotSet;
|
auto UseExternalName = RedirectingFileEntry::NK_NotSet;
|
||||||
EntryKind Kind;
|
EntryKind Kind;
|
||||||
|
|
||||||
|
@ -1321,6 +1323,7 @@ class RedirectingFileSystemParser {
|
||||||
if (!parseScalarString(I.getValue(), Value, Buffer))
|
if (!parseScalarString(I.getValue(), Value, Buffer))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
NameValueNode = I.getValue();
|
||||||
if (FS->UseCanonicalizedPaths) {
|
if (FS->UseCanonicalizedPaths) {
|
||||||
SmallString<256> Path(Value);
|
SmallString<256> Path(Value);
|
||||||
// Guarantee that old YAML files containing paths with ".." and "."
|
// Guarantee that old YAML files containing paths with ".." and "."
|
||||||
|
@ -1357,7 +1360,8 @@ class RedirectingFileSystemParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &I : *Contents) {
|
for (auto &I : *Contents) {
|
||||||
if (std::unique_ptr<Entry> E = parseEntry(&I, FS))
|
if (std::unique_ptr<Entry> E =
|
||||||
|
parseEntry(&I, FS, /*IsRootEntry*/ false))
|
||||||
EntryArrayContents.push_back(std::move(E));
|
EntryArrayContents.push_back(std::move(E));
|
||||||
else
|
else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1418,6 +1422,13 @@ class RedirectingFileSystemParser {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsRootEntry && !sys::path::is_absolute(Name)) {
|
||||||
|
assert(NameValueNode && "Name presence should be checked earlier");
|
||||||
|
error(NameValueNode,
|
||||||
|
"entry with relative path at the root level is not discoverable");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove trailing slash(es), being careful not to remove the root path
|
// Remove trailing slash(es), being careful not to remove the root path
|
||||||
StringRef Trimmed(Name);
|
StringRef Trimmed(Name);
|
||||||
size_t RootPathLen = sys::path::root_path(Trimmed).size();
|
size_t RootPathLen = sys::path::root_path(Trimmed).size();
|
||||||
|
@ -1500,7 +1511,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &I : *Roots) {
|
for (auto &I : *Roots) {
|
||||||
if (std::unique_ptr<Entry> E = parseEntry(&I, FS))
|
if (std::unique_ptr<Entry> E =
|
||||||
|
parseEntry(&I, FS, /*IsRootEntry*/ true))
|
||||||
RootEntries.push_back(std::move(E));
|
RootEntries.push_back(std::move(E));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1468,3 +1468,35 @@ TEST_F(VFSFromYAMLTest, RecursiveDirectoryIterationLevel) {
|
||||||
}
|
}
|
||||||
EXPECT_EQ(I, E);
|
EXPECT_EQ(I, E);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(VFSFromYAMLTest, RelativePaths) {
|
||||||
|
IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
|
||||||
|
// Filename at root level without a parent directory.
|
||||||
|
IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
|
||||||
|
"{ 'roots': [\n"
|
||||||
|
" { 'type': 'file', 'name': 'file-not-in-directory.h',\n"
|
||||||
|
" 'external-contents': '//root/external/file'\n"
|
||||||
|
" }\n"
|
||||||
|
"] }", Lower);
|
||||||
|
EXPECT_EQ(nullptr, FS.get());
|
||||||
|
|
||||||
|
// Relative file path.
|
||||||
|
FS = getFromYAMLString(
|
||||||
|
"{ 'roots': [\n"
|
||||||
|
" { 'type': 'file', 'name': 'relative/file/path.h',\n"
|
||||||
|
" 'external-contents': '//root/external/file'\n"
|
||||||
|
" }\n"
|
||||||
|
"] }", Lower);
|
||||||
|
EXPECT_EQ(nullptr, FS.get());
|
||||||
|
|
||||||
|
// Relative directory path.
|
||||||
|
FS = getFromYAMLString(
|
||||||
|
"{ 'roots': [\n"
|
||||||
|
" { 'type': 'directory', 'name': 'relative/directory/path.h',\n"
|
||||||
|
" 'contents': []\n"
|
||||||
|
" }\n"
|
||||||
|
"] }", Lower);
|
||||||
|
EXPECT_EQ(nullptr, FS.get());
|
||||||
|
|
||||||
|
EXPECT_EQ(3, NumDiagnostics);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue