Update prebuilt Clang to match Android kernel.
Bug: 132428451
Change-Id: I8f6e2cb23f381fc0c02ddea99b867e58e925e5be
diff --git a/linux-x64/clang/include/llvm/Support/VirtualFileSystem.h b/linux-x64/clang/include/llvm/Support/VirtualFileSystem.h
index f2f8ffa..7b7c9f8 100644
--- a/linux-x64/clang/include/llvm/Support/VirtualFileSystem.h
+++ b/linux-x64/clang/include/llvm/Support/VirtualFileSystem.h
@@ -1,9 +1,8 @@
//===- VirtualFileSystem.h - Virtual File System Layer ----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -24,6 +23,7 @@
#include "llvm/Support/Chrono.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/SourceMgr.h"
#include <cassert>
#include <cstdint>
@@ -193,14 +193,22 @@
class FileSystem;
+namespace detail {
+
+/// Keeps state for the recursive_directory_iterator.
+struct RecDirIterState {
+ std::stack<directory_iterator, std::vector<directory_iterator>> Stack;
+ bool HasNoPushRequest = false;
+};
+
+} // end namespace detail
+
/// An input iterator over the recursive contents of a virtual path,
/// similar to llvm::sys::fs::recursive_directory_iterator.
class recursive_directory_iterator {
- using IterState =
- std::stack<directory_iterator, std::vector<directory_iterator>>;
-
FileSystem *FS;
- std::shared_ptr<IterState> State; // Input iterator semantics on copy.
+ std::shared_ptr<detail::RecDirIterState>
+ State; // Input iterator semantics on copy.
public:
recursive_directory_iterator(FileSystem &FS, const Twine &Path,
@@ -212,8 +220,8 @@
/// Equivalent to operator++, with an error code.
recursive_directory_iterator &increment(std::error_code &EC);
- const directory_entry &operator*() const { return *State->top(); }
- const directory_entry *operator->() const { return &*State->top(); }
+ const directory_entry &operator*() const { return *State->Stack.top(); }
+ const directory_entry *operator->() const { return &*State->Stack.top(); }
bool operator==(const recursive_directory_iterator &Other) const {
return State == Other.State; // identity
@@ -224,9 +232,12 @@
/// Gets the current level. Starting path is at level 0.
int level() const {
- assert(!State->empty() && "Cannot get level without any iteration state");
- return State->size() - 1;
+ assert(!State->Stack.empty() &&
+ "Cannot get level without any iteration state");
+ return State->Stack.size() - 1;
}
+
+ void no_push() { State->HasNoPushRequest = true; }
};
/// The virtual file system interface.
@@ -268,6 +279,9 @@
/// Check whether a file exists. Provided for convenience.
bool exists(const Twine &Path);
+ /// Is the file mounted on a local filesystem?
+ virtual std::error_code isLocal(const Twine &Path, bool &Result);
+
/// Make \a Path an absolute path.
///
/// Makes \a Path absolute using the current directory if it is not already.
@@ -315,6 +329,7 @@
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
+ std::error_code isLocal(const Twine &Path, bool &Result) override;
std::error_code getRealPath(const Twine &Path,
SmallVectorImpl<char> &Output) const override;
@@ -359,12 +374,17 @@
SmallVectorImpl<char> &Output) const override {
return FS->getRealPath(Path, Output);
}
+ std::error_code isLocal(const Twine &Path, bool &Result) override {
+ return FS->isLocal(Path, Result);
+ }
protected:
FileSystem &getUnderlyingFS() { return *FS; }
private:
IntrusiveRefCntPtr<FileSystem> FS;
+
+ virtual void anchor();
};
namespace detail {
@@ -452,7 +472,7 @@
/// system.
std::error_code getRealPath(const Twine &Path,
SmallVectorImpl<char> &Output) const override;
-
+ std::error_code isLocal(const Twine &Path, bool &Result) override;
std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
};
@@ -475,6 +495,230 @@
std::string RPath;
};
+class VFSFromYamlDirIterImpl;
+class RedirectingFileSystemParser;
+
+/// A virtual file system parsed from a YAML file.
+///
+/// Currently, this class allows creating virtual directories and mapping
+/// virtual file paths to existing external files, available in \c ExternalFS.
+///
+/// The basic structure of the parsed file is:
+/// \verbatim
+/// {
+/// 'version': <version number>,
+/// <optional configuration>
+/// 'roots': [
+/// <directory entries>
+/// ]
+/// }
+/// \endverbatim
+///
+/// All configuration options are optional.
+/// 'case-sensitive': <boolean, default=true>
+/// 'use-external-names': <boolean, default=true>
+/// 'overlay-relative': <boolean, default=false>
+/// 'fallthrough': <boolean, default=true>
+///
+/// Virtual directories are represented as
+/// \verbatim
+/// {
+/// 'type': 'directory',
+/// 'name': <string>,
+/// 'contents': [ <file or directory entries> ]
+/// }
+/// \endverbatim
+///
+/// The default attributes for virtual directories are:
+/// \verbatim
+/// MTime = now() when created
+/// Perms = 0777
+/// User = Group = 0
+/// Size = 0
+/// UniqueID = unspecified unique value
+/// \endverbatim
+///
+/// Re-mapped files are represented as
+/// \verbatim
+/// {
+/// 'type': 'file',
+/// 'name': <string>,
+/// 'use-external-name': <boolean> # Optional
+/// 'external-contents': <path to external file>
+/// }
+/// \endverbatim
+///
+/// and inherit their attributes from the external contents.
+///
+/// In both cases, the 'name' field may contain multiple path components (e.g.
+/// /path/to/file). However, any directory that contains more than one child
+/// must be uniquely represented by a directory entry.
+class RedirectingFileSystem : public vfs::FileSystem {
+public:
+ enum EntryKind { EK_Directory, EK_File };
+
+ /// A single file or directory in the VFS.
+ class Entry {
+ EntryKind Kind;
+ std::string Name;
+
+ public:
+ Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
+ virtual ~Entry() = default;
+
+ StringRef getName() const { return Name; }
+ EntryKind getKind() const { return Kind; }
+ };
+
+ class RedirectingDirectoryEntry : public Entry {
+ std::vector<std::unique_ptr<Entry>> Contents;
+ Status S;
+
+ public:
+ RedirectingDirectoryEntry(StringRef Name,
+ std::vector<std::unique_ptr<Entry>> Contents,
+ Status S)
+ : Entry(EK_Directory, Name), Contents(std::move(Contents)),
+ S(std::move(S)) {}
+ RedirectingDirectoryEntry(StringRef Name, Status S)
+ : Entry(EK_Directory, Name), S(std::move(S)) {}
+
+ Status getStatus() { return S; }
+
+ void addContent(std::unique_ptr<Entry> Content) {
+ Contents.push_back(std::move(Content));
+ }
+
+ Entry *getLastContent() const { return Contents.back().get(); }
+
+ using iterator = decltype(Contents)::iterator;
+
+ iterator contents_begin() { return Contents.begin(); }
+ iterator contents_end() { return Contents.end(); }
+
+ static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
+ };
+
+ class RedirectingFileEntry : public Entry {
+ public:
+ enum NameKind { NK_NotSet, NK_External, NK_Virtual };
+
+ private:
+ std::string ExternalContentsPath;
+ NameKind UseName;
+
+ public:
+ RedirectingFileEntry(StringRef Name, StringRef ExternalContentsPath,
+ NameKind UseName)
+ : Entry(EK_File, Name), ExternalContentsPath(ExternalContentsPath),
+ UseName(UseName) {}
+
+ StringRef getExternalContentsPath() const { return ExternalContentsPath; }
+
+ /// whether to use the external path as the name for this file.
+ bool useExternalName(bool GlobalUseExternalName) const {
+ return UseName == NK_NotSet ? GlobalUseExternalName
+ : (UseName == NK_External);
+ }
+
+ NameKind getUseName() const { return UseName; }
+
+ static bool classof(const Entry *E) { return E->getKind() == EK_File; }
+ };
+
+private:
+ friend class VFSFromYamlDirIterImpl;
+ friend class RedirectingFileSystemParser;
+
+ /// The root(s) of the virtual file system.
+ std::vector<std::unique_ptr<Entry>> Roots;
+
+ /// 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;
+
+ /// @name Configuration
+ /// @{
+
+ /// Whether to perform case-sensitive comparisons.
+ ///
+ /// Currently, case-insensitive matching only works correctly with ASCII.
+ bool CaseSensitive = true;
+
+ /// IsRelativeOverlay marks whether a ExternalContentsPrefixDir path must
+ /// be prefixed in every 'external-contents' when reading from YAML files.
+ bool IsRelativeOverlay = false;
+
+ /// 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;
+
+ /// Whether to attempt a file lookup in external file system after it wasn't
+ /// found in VFS.
+ bool IsFallthrough = true;
+ /// @}
+
+ /// Virtual file paths and external files could be canonicalized without "..",
+ /// "." and "./" in their paths. FIXME: some unittests currently fail on
+ /// win32 when using remove_dots and remove_leading_dotslash on paths.
+ bool UseCanonicalizedPaths =
+#ifdef _WIN32
+ false;
+#else
+ true;
+#endif
+
+ RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS)
+ : ExternalFS(std::move(ExternalFS)) {}
+
+ /// 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(llvm::sys::path::const_iterator Start,
+ llvm::sys::path::const_iterator End,
+ Entry *From) const;
+
+ /// Get the status of a given an \c Entry.
+ ErrorOr<Status> status(const Twine &Path, Entry *E);
+
+public:
+ /// Looks up \p Path in \c Roots.
+ ErrorOr<Entry *> lookupPath(const Twine &Path) const;
+
+ /// Parses \p Buffer, which is expected to be in YAML format and
+ /// returns a virtual file system representing its contents.
+ static RedirectingFileSystem *
+ create(std::unique_ptr<MemoryBuffer> Buffer,
+ SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
+ void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
+
+ ErrorOr<Status> status(const Twine &Path) override;
+ ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
+
+ std::error_code getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const override;
+
+ llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
+
+ std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
+
+ std::error_code isLocal(const Twine &Path, bool &Result) override;
+
+ directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
+
+ void setExternalContentsPrefixDir(StringRef PrefixDir);
+
+ StringRef getExternalContentsPrefixDir() const;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump() const;
+ LLVM_DUMP_METHOD void dumpEntry(Entry *E, int NumSpaces = 0) const;
+#endif
+};
+
/// Collect all pairs of <virtual path, real path> entries from the
/// \p YAMLFilePath. This is used by the module dependency collector to forward
/// the entries into the reproducer output VFS YAML file.
@@ -490,7 +734,6 @@
Optional<bool> IsCaseSensitive;
Optional<bool> IsOverlayRelative;
Optional<bool> UseExternalNames;
- Optional<bool> IgnoreNonExistentContents;
std::string OverlayDir;
public:
@@ -504,15 +747,13 @@
void setUseExternalNames(bool UseExtNames) { UseExternalNames = UseExtNames; }
- void setIgnoreNonExistentContents(bool IgnoreContents) {
- IgnoreNonExistentContents = IgnoreContents;
- }
-
void setOverlayDir(StringRef OverlayDirectory) {
IsOverlayRelative = true;
OverlayDir.assign(OverlayDirectory.str());
}
+ const std::vector<YAMLVFSEntry> &getMappings() const { return Mappings; }
+
void write(llvm::raw_ostream &OS);
};