diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp | 134 | 
1 files changed, 108 insertions, 26 deletions
diff --git a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp index 8ace2b3dc838..50fcb22faf53 100644 --- a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp @@ -47,7 +47,7 @@ Status::Status(const file_status &Status)        User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()),        Type(Status.type()), Perms(Status.permissions()), IsVFSMapped(false)  {} -Status::Status(StringRef Name, UniqueID UID, sys::TimeValue MTime, +Status::Status(StringRef Name, UniqueID UID, sys::TimePoint<> MTime,                 uint32_t User, uint32_t Group, uint64_t Size, file_type Type,                 perms Perms)      : Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size), @@ -494,8 +494,8 @@ public:  InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)      : Root(new detail::InMemoryDirectory( -          Status("", getNextVirtualUniqueID(), llvm::sys::TimeValue::MinTime(), -                 0, 0, 0, llvm::sys::fs::file_type::directory_file, +          Status("", getNextVirtualUniqueID(), llvm::sys::TimePoint<>(), 0, 0, +                 0, llvm::sys::fs::file_type::directory_file,                   llvm::sys::fs::perms::all_all))),        UseNormalizedPaths(UseNormalizedPaths) {} @@ -532,7 +532,7 @@ bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,          // End of the path, create a new file.          // FIXME: expose the status details in the interface.          Status Stat(P.str(), getNextVirtualUniqueID(), -                    llvm::sys::TimeValue(ModificationTime, 0), 0, 0, +                    llvm::sys::toTimePoint(ModificationTime), 0, 0,                      Buffer->getBufferSize(),                      llvm::sys::fs::file_type::regular_file,                      llvm::sys::fs::all_all); @@ -545,9 +545,9 @@ bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,        // FIXME: expose the status details in the interface.        Status Stat(            StringRef(Path.str().begin(), Name.end() - Path.str().begin()), -          getNextVirtualUniqueID(), llvm::sys::TimeValue(ModificationTime, 0), -          0, 0, Buffer->getBufferSize(), -          llvm::sys::fs::file_type::directory_file, llvm::sys::fs::all_all); +          getNextVirtualUniqueID(), llvm::sys::toTimePoint(ModificationTime), 0, +          0, Buffer->getBufferSize(), llvm::sys::fs::file_type::directory_file, +          llvm::sys::fs::all_all);        Dir = cast<detail::InMemoryDirectory>(Dir->addChild(            Name, llvm::make_unique<detail::InMemoryDirectory>(std::move(Stat))));        continue; @@ -801,6 +801,7 @@ public:  ///   'case-sensitive': <boolean, default=true>  ///   'use-external-names': <boolean, default=true>  ///   'overlay-relative': <boolean, default=false> +///   'ignore-non-existent-contents': <boolean, default=true>  ///  /// Virtual directories are represented as  /// \verbatim @@ -860,6 +861,14 @@ class RedirectingFileSystem : public vfs::FileSystem {    /// \brief Whether to use to use the value of 'external-contents' for the    /// names of files.  This global value is overridable on a per-file basis.    bool UseExternalNames = true; + +  /// \brief Whether an invalid path obtained via 'external-contents' should +  /// cause iteration on the VFS to stop. If 'true', the VFS should ignore +  /// the entry and continue with the next. Allows YAML files to be shared +  /// across multiple compiler invocations regardless of prior existent +  /// paths in 'external-contents'. This global value is overridable on a +  /// per-file basis. +  bool IgnoreNonExistentContents = true;    /// @}    /// Virtual file paths and external files could be canonicalized without "..", @@ -878,9 +887,6 @@ private:    RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS)        : ExternalFS(std::move(ExternalFS)) {} -  /// \brief Looks up \p Path in \c Roots. -  ErrorOr<Entry *> lookupPath(const Twine &Path); -    /// \brief Looks up the path <tt>[Start, End)</tt> in \p From, possibly    /// recursing into the contents of \p From if it is a directory.    ErrorOr<Entry *> lookupPath(sys::path::const_iterator Start, @@ -890,6 +896,9 @@ private:    ErrorOr<Status> status(const Twine &Path, Entry *E);  public: +  /// \brief Looks up \p Path in \c Roots. +  ErrorOr<Entry *> lookupPath(const Twine &Path); +    /// \brief Parses \p Buffer, which is expected to be in YAML format and    /// returns a virtual file system representing its contents.    static RedirectingFileSystem * @@ -937,6 +946,10 @@ public:      return ExternalContentsPrefixDir;    } +  bool ignoreNonExistentContents() const { +    return IgnoreNonExistentContents; +  } +  #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)  LLVM_DUMP_METHOD void dump() const {      for (const std::unique_ptr<Entry> &Root : Roots) @@ -1060,8 +1073,9 @@ class RedirectingFileSystemParser {      // ... or create a new one      std::unique_ptr<Entry> E = llvm::make_unique<RedirectingDirectoryEntry>( -        Name, Status("", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0, -                     0, file_type::directory_file, sys::fs::all_all)); +        Name, +        Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(), +               0, 0, 0, file_type::directory_file, sys::fs::all_all));      if (!ParentEntry) { // Add a new root to the overlay        FS->Roots.push_back(std::move(E)); @@ -1262,8 +1276,8 @@ class RedirectingFileSystemParser {      case EK_Directory:        Result = llvm::make_unique<RedirectingDirectoryEntry>(            LastComponent, std::move(EntryArrayContents), -          Status("", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0, 0, -                 file_type::directory_file, sys::fs::all_all)); +          Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(), +                 0, 0, 0, file_type::directory_file, sys::fs::all_all));        break;      } @@ -1279,8 +1293,8 @@ class RedirectingFileSystemParser {        Entries.push_back(std::move(Result));        Result = llvm::make_unique<RedirectingDirectoryEntry>(            *I, std::move(Entries), -          Status("", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0, 0, -                 file_type::directory_file, sys::fs::all_all)); +          Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(), +                 0, 0, 0, file_type::directory_file, sys::fs::all_all));      }      return Result;    } @@ -1301,6 +1315,7 @@ public:        KeyStatusPair("case-sensitive", false),        KeyStatusPair("use-external-names", false),        KeyStatusPair("overlay-relative", false), +      KeyStatusPair("ignore-non-existent-contents", false),        KeyStatusPair("roots", true),      }; @@ -1359,6 +1374,9 @@ public:        } else if (Key == "use-external-names") {          if (!parseScalarBool(I->getValue(), FS->UseExternalNames))            return false; +      } else if (Key == "ignore-non-existent-contents") { +        if (!parseScalarBool(I->getValue(), FS->IgnoreNonExistentContents)) +          return false;        } else {          llvm_unreachable("key missing from Keys");        } @@ -1588,6 +1606,47 @@ vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,                                         std::move(ExternalFS));  } +static void getVFSEntries(Entry *SrcE, SmallVectorImpl<StringRef> &Path, +                          SmallVectorImpl<YAMLVFSEntry> &Entries) { +  auto Kind = SrcE->getKind(); +  if (Kind == EK_Directory) { +    auto *DE = dyn_cast<RedirectingDirectoryEntry>(SrcE); +    assert(DE && "Must be a directory"); +    for (std::unique_ptr<Entry> &SubEntry : +         llvm::make_range(DE->contents_begin(), DE->contents_end())) { +      Path.push_back(SubEntry->getName()); +      getVFSEntries(SubEntry.get(), Path, Entries); +      Path.pop_back(); +    } +    return; +  } + +  assert(Kind == EK_File && "Must be a EK_File"); +  auto *FE = dyn_cast<RedirectingFileEntry>(SrcE); +  assert(FE && "Must be a file"); +  SmallString<128> VPath; +  for (auto &Comp : Path) +    llvm::sys::path::append(VPath, Comp); +  Entries.push_back(YAMLVFSEntry(VPath.c_str(), FE->getExternalContentsPath())); +} + +void vfs::collectVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer, +                             SourceMgr::DiagHandlerTy DiagHandler, +                             StringRef YAMLFilePath, +                             SmallVectorImpl<YAMLVFSEntry> &CollectedEntries, +                             void *DiagContext, +                             IntrusiveRefCntPtr<FileSystem> ExternalFS) { +  RedirectingFileSystem *VFS = RedirectingFileSystem::create( +      std::move(Buffer), DiagHandler, YAMLFilePath, DiagContext, +      std::move(ExternalFS)); +  ErrorOr<Entry *> RootE = VFS->lookupPath("/"); +  if (!RootE) +    return; +  SmallVector<StringRef, 8> Components; +  Components.push_back("/"); +  getVFSEntries(*RootE, Components, CollectedEntries); +} +  UniqueID vfs::getNextVirtualUniqueID() {    static std::atomic<unsigned> UID;    unsigned ID = ++UID; @@ -1619,7 +1678,7 @@ public:    JSONWriter(llvm::raw_ostream &OS) : OS(OS) {}    void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames,               Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative, -             StringRef OverlayDir); +             Optional<bool> IgnoreNonExistentContents, StringRef OverlayDir);  };  } @@ -1675,6 +1734,7 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,                         Optional<bool> UseExternalNames,                         Optional<bool> IsCaseSensitive,                         Optional<bool> IsOverlayRelative, +                       Optional<bool> IgnoreNonExistentContents,                         StringRef OverlayDir) {    using namespace llvm::sys; @@ -1692,6 +1752,9 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,      OS << "  'overlay-relative': '"         << (UseOverlayRelative ? "true" : "false") << "',\n";    } +  if (IgnoreNonExistentContents.hasValue()) +    OS << "  'ignore-non-existent-contents': '" +       << (IgnoreNonExistentContents.getValue() ? "true" : "false") << "',\n";    OS << "  'roots': [\n";    if (!Entries.empty()) { @@ -1748,7 +1811,8 @@ void YAMLVFSWriter::write(llvm::raw_ostream &OS) {    });    JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive, -                       IsOverlayRelative, OverlayDir); +                       IsOverlayRelative, IgnoreNonExistentContents, +                       OverlayDir);  }  VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl( @@ -1756,29 +1820,47 @@ VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(      RedirectingDirectoryEntry::iterator Begin,      RedirectingDirectoryEntry::iterator End, std::error_code &EC)      : Dir(_Path.str()), FS(FS), Current(Begin), End(End) { -  if (Current != End) { +  while (Current != End) {      SmallString<128> PathStr(Dir);      llvm::sys::path::append(PathStr, (*Current)->getName());      llvm::ErrorOr<vfs::Status> S = FS.status(PathStr); -    if (S) +    if (S) {        CurrentEntry = *S; -    else +      return; +    } +    // Skip entries which do not map to a reliable external content. +    if (FS.ignoreNonExistentContents() && +        S.getError() == llvm::errc::no_such_file_or_directory) { +      ++Current; +      continue; +    } else {        EC = S.getError(); +      break; +    }    }  }  std::error_code VFSFromYamlDirIterImpl::increment() {    assert(Current != End && "cannot iterate past end"); -  if (++Current != End) { +  while (++Current != End) {      SmallString<128> PathStr(Dir);      llvm::sys::path::append(PathStr, (*Current)->getName());      llvm::ErrorOr<vfs::Status> S = FS.status(PathStr); -    if (!S) -      return S.getError(); +    if (!S) { +      // Skip entries which do not map to a reliable external content. +      if (FS.ignoreNonExistentContents() && +          S.getError() == llvm::errc::no_such_file_or_directory) { +        continue; +      } else { +        return S.getError(); +      } +    }      CurrentEntry = *S; -  } else { -    CurrentEntry = Status(); +    break;    } + +  if (Current == End) +    CurrentEntry = Status();    return std::error_code();  }  | 
