Update Clang for rebase to r212749.
This also fixes a small issue with arm_neon.h not being generated always.
Includes a cherry-pick of:
r213450 - fixes mac-specific header issue
r213126 - removes a default -Bsymbolic on Android
Change-Id: I2a790a0f5d3b2aab11de596fc3a74e7cbc99081d
diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp
index a469c9a..1f2a856 100644
--- a/lib/Basic/VirtualFileSystem.cpp
+++ b/lib/Basic/VirtualFileSystem.cpp
@@ -14,6 +14,8 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Errc.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/YAMLParser.h"
@@ -65,17 +67,15 @@
FileSystem::~FileSystem() {}
-error_code FileSystem::getBufferForFile(const llvm::Twine &Name,
- std::unique_ptr<MemoryBuffer> &Result,
- int64_t FileSize,
- bool RequiresNullTerminator,
- bool IsVolatile) {
+std::error_code FileSystem::getBufferForFile(
+ const llvm::Twine &Name, std::unique_ptr<MemoryBuffer> &Result,
+ int64_t FileSize, bool RequiresNullTerminator, bool IsVolatile) {
std::unique_ptr<File> F;
- if (error_code EC = openFileForRead(Name, F))
+ if (std::error_code EC = openFileForRead(Name, F))
return EC;
- error_code EC = F->getBuffer(Name, Result, FileSize, RequiresNullTerminator,
- IsVolatile);
+ std::error_code EC =
+ F->getBuffer(Name, Result, FileSize, RequiresNullTerminator, IsVolatile);
return EC;
}
@@ -96,11 +96,12 @@
public:
~RealFile();
ErrorOr<Status> status() override;
- error_code getBuffer(const Twine &Name, std::unique_ptr<MemoryBuffer> &Result,
- int64_t FileSize = -1,
- bool RequiresNullTerminator = true,
- bool IsVolatile = false) override;
- error_code close() override;
+ std::error_code getBuffer(const Twine &Name,
+ std::unique_ptr<MemoryBuffer> &Result,
+ int64_t FileSize = -1,
+ bool RequiresNullTerminator = true,
+ bool IsVolatile = false) override;
+ std::error_code close() override;
void setName(StringRef Name) override;
};
} // end anonymous namespace
@@ -110,7 +111,7 @@
assert(FD != -1 && "cannot stat closed file");
if (!S.isStatusKnown()) {
file_status RealStatus;
- if (error_code EC = sys::fs::status(FD, RealStatus))
+ if (std::error_code EC = sys::fs::status(FD, RealStatus))
return EC;
Status NewS(RealStatus);
NewS.setName(S.getName());
@@ -119,13 +120,19 @@
return S;
}
-error_code RealFile::getBuffer(const Twine &Name,
- std::unique_ptr<MemoryBuffer> &Result,
- int64_t FileSize, bool RequiresNullTerminator,
- bool IsVolatile) {
+std::error_code RealFile::getBuffer(const Twine &Name,
+ std::unique_ptr<MemoryBuffer> &Result,
+ int64_t FileSize,
+ bool RequiresNullTerminator,
+ bool IsVolatile) {
assert(FD != -1 && "cannot get buffer for closed file");
- return MemoryBuffer::getOpenFile(FD, Name.str().c_str(), Result, FileSize,
- RequiresNullTerminator, IsVolatile);
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
+ MemoryBuffer::getOpenFile(FD, Name.str().c_str(), FileSize,
+ RequiresNullTerminator, IsVolatile);
+ if (std::error_code EC = BufferOrErr.getError())
+ return EC;
+ Result = std::move(BufferOrErr.get());
+ return std::error_code();
}
// FIXME: This is terrible, we need this for ::close.
@@ -138,11 +145,11 @@
#define S_ISFIFO(x) (0)
#endif
#endif
-error_code RealFile::close() {
+std::error_code RealFile::close() {
if (::close(FD))
- return error_code(errno, system_category());
+ return std::error_code(errno, std::generic_category());
FD = -1;
- return error_code::success();
+ return std::error_code();
}
void RealFile::setName(StringRef Name) {
@@ -154,28 +161,29 @@
class RealFileSystem : public FileSystem {
public:
ErrorOr<Status> status(const Twine &Path) override;
- error_code openFileForRead(const Twine &Path,
- std::unique_ptr<File> &Result) override;
+ std::error_code openFileForRead(const Twine &Path,
+ std::unique_ptr<File> &Result) override;
+ directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
};
} // end anonymous namespace
ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
sys::fs::file_status RealStatus;
- if (error_code EC = sys::fs::status(Path, RealStatus))
+ if (std::error_code EC = sys::fs::status(Path, RealStatus))
return EC;
Status Result(RealStatus);
Result.setName(Path.str());
return Result;
}
-error_code RealFileSystem::openFileForRead(const Twine &Name,
- std::unique_ptr<File> &Result) {
+std::error_code RealFileSystem::openFileForRead(const Twine &Name,
+ std::unique_ptr<File> &Result) {
int FD;
- if (error_code EC = sys::fs::openFileForRead(Name, FD))
+ if (std::error_code EC = sys::fs::openFileForRead(Name, FD))
return EC;
Result.reset(new RealFile(FD));
Result->setName(Name.str());
- return error_code::success();
+ return std::error_code();
}
IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
@@ -183,6 +191,46 @@
return FS;
}
+namespace {
+class RealFSDirIter : public clang::vfs::detail::DirIterImpl {
+ std::string Path;
+ llvm::sys::fs::directory_iterator Iter;
+public:
+ RealFSDirIter(const Twine &_Path, std::error_code &EC)
+ : Path(_Path.str()), Iter(Path, EC) {
+ if (!EC && Iter != llvm::sys::fs::directory_iterator()) {
+ llvm::sys::fs::file_status S;
+ EC = Iter->status(S);
+ if (!EC) {
+ CurrentEntry = Status(S);
+ CurrentEntry.setName(Iter->path());
+ }
+ }
+ }
+
+ std::error_code increment() override {
+ std::error_code EC;
+ Iter.increment(EC);
+ if (EC) {
+ return EC;
+ } else if (Iter == llvm::sys::fs::directory_iterator()) {
+ CurrentEntry = Status();
+ } else {
+ llvm::sys::fs::file_status S;
+ EC = Iter->status(S);
+ CurrentEntry = Status(S);
+ CurrentEntry.setName(Iter->path());
+ }
+ return EC;
+ }
+};
+}
+
+directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
+ std::error_code &EC) {
+ return directory_iterator(std::make_shared<RealFSDirIter>(Dir, EC));
+}
+
//===-----------------------------------------------------------------------===/
// OverlayFileSystem implementation
//===-----------------------------------------------------------------------===/
@@ -198,21 +246,90 @@
// FIXME: handle symlinks that cross file systems
for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
ErrorOr<Status> Status = (*I)->status(Path);
- if (Status || Status.getError() != errc::no_such_file_or_directory)
+ if (Status || Status.getError() != llvm::errc::no_such_file_or_directory)
return Status;
}
- return error_code(errc::no_such_file_or_directory, system_category());
+ return make_error_code(llvm::errc::no_such_file_or_directory);
}
-error_code OverlayFileSystem::openFileForRead(const llvm::Twine &Path,
- std::unique_ptr<File> &Result) {
+std::error_code
+OverlayFileSystem::openFileForRead(const llvm::Twine &Path,
+ std::unique_ptr<File> &Result) {
// FIXME: handle symlinks that cross file systems
for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
- error_code EC = (*I)->openFileForRead(Path, Result);
- if (!EC || EC != errc::no_such_file_or_directory)
+ std::error_code EC = (*I)->openFileForRead(Path, Result);
+ if (!EC || EC != llvm::errc::no_such_file_or_directory)
return EC;
}
- return error_code(errc::no_such_file_or_directory, system_category());
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+clang::vfs::detail::DirIterImpl::~DirIterImpl() { }
+
+namespace {
+class OverlayFSDirIterImpl : public clang::vfs::detail::DirIterImpl {
+ OverlayFileSystem &Overlays;
+ std::string Path;
+ OverlayFileSystem::iterator CurrentFS;
+ directory_iterator CurrentDirIter;
+ llvm::StringSet<> SeenNames;
+
+ std::error_code incrementFS() {
+ assert(CurrentFS != Overlays.overlays_end() && "incrementing past end");
+ ++CurrentFS;
+ for (auto E = Overlays.overlays_end(); CurrentFS != E; ++CurrentFS) {
+ std::error_code EC;
+ CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC);
+ if (EC && EC != errc::no_such_file_or_directory)
+ return EC;
+ if (CurrentDirIter != directory_iterator())
+ break; // found
+ }
+ return std::error_code();
+ }
+
+ std::error_code incrementDirIter(bool IsFirstTime) {
+ assert((IsFirstTime || CurrentDirIter != directory_iterator()) &&
+ "incrementing past end");
+ std::error_code EC;
+ if (!IsFirstTime)
+ CurrentDirIter.increment(EC);
+ if (!EC && CurrentDirIter == directory_iterator())
+ EC = incrementFS();
+ return EC;
+ }
+
+ std::error_code incrementImpl(bool IsFirstTime) {
+ while (true) {
+ std::error_code EC = incrementDirIter(IsFirstTime);
+ if (EC || CurrentDirIter == directory_iterator()) {
+ CurrentEntry = Status();
+ return EC;
+ }
+ CurrentEntry = *CurrentDirIter;
+ StringRef Name = llvm::sys::path::filename(CurrentEntry.getName());
+ if (SeenNames.insert(Name))
+ return EC; // name not seen before
+ }
+ llvm_unreachable("returned above");
+ }
+
+public:
+ OverlayFSDirIterImpl(const Twine &Path, OverlayFileSystem &FS,
+ std::error_code &EC)
+ : Overlays(FS), Path(Path.str()), CurrentFS(Overlays.overlays_begin()) {
+ CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC);
+ EC = incrementImpl(true);
+ }
+
+ std::error_code increment() override { return incrementImpl(false); }
+};
+} // end anonymous namespace
+
+directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir,
+ std::error_code &EC) {
+ return directory_iterator(
+ std::make_shared<OverlayFSDirIterImpl>(Dir, *this, EC));
}
//===-----------------------------------------------------------------------===/
@@ -291,6 +408,19 @@
static bool classof(const Entry *E) { return E->getKind() == EK_File; }
};
+class VFSFromYAML;
+
+class VFSFromYamlDirIterImpl : public clang::vfs::detail::DirIterImpl {
+ std::string Dir;
+ VFSFromYAML &FS;
+ DirectoryEntry::iterator Current, End;
+public:
+ VFSFromYamlDirIterImpl(const Twine &Path, VFSFromYAML &FS,
+ DirectoryEntry::iterator Begin,
+ DirectoryEntry::iterator End, std::error_code &EC);
+ std::error_code increment() override;
+};
+
/// \brief A virtual file system parsed from a YAML file.
///
/// Currently, this class allows creating virtual directories and mapping
@@ -376,6 +506,9 @@
ErrorOr<Entry *> lookupPath(sys::path::const_iterator Start,
sys::path::const_iterator End, Entry *From);
+ /// \brief Get the status of a given an \c Entry.
+ ErrorOr<Status> status(const Twine &Path, Entry *E);
+
public:
~VFSFromYAML();
@@ -389,8 +522,30 @@
IntrusiveRefCntPtr<FileSystem> ExternalFS);
ErrorOr<Status> status(const Twine &Path) override;
- error_code openFileForRead(const Twine &Path,
- std::unique_ptr<File> &Result) override;
+ std::error_code openFileForRead(const Twine &Path,
+ std::unique_ptr<File> &Result) override;
+
+ directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override{
+ ErrorOr<Entry *> E = lookupPath(Dir);
+ if (!E) {
+ EC = E.getError();
+ return directory_iterator();
+ }
+ ErrorOr<Status> S = status(Dir, *E);
+ if (!S) {
+ EC = S.getError();
+ return directory_iterator();
+ }
+ if (!S->isDirectory()) {
+ EC = std::error_code(static_cast<int>(errc::not_a_directory),
+ std::system_category());
+ return directory_iterator();
+ }
+
+ DirectoryEntry *D = cast<DirectoryEntry>(*E);
+ return directory_iterator(std::make_shared<VFSFromYamlDirIterImpl>(Dir,
+ *this, D->contents_begin(), D->contents_end(), EC));
+ }
};
/// \brief A helper class to hold the common YAML parsing state.
@@ -740,21 +895,21 @@
Path_.toVector(Path);
// Handle relative paths
- if (error_code EC = sys::fs::make_absolute(Path))
+ if (std::error_code EC = sys::fs::make_absolute(Path))
return EC;
if (Path.empty())
- return error_code(errc::invalid_argument, system_category());
+ return make_error_code(llvm::errc::invalid_argument);
sys::path::const_iterator Start = sys::path::begin(Path);
sys::path::const_iterator End = sys::path::end(Path);
for (std::vector<Entry *>::iterator I = Roots.begin(), E = Roots.end();
I != E; ++I) {
ErrorOr<Entry *> Result = lookupPath(Start, End, *I);
- if (Result || Result.getError() != errc::no_such_file_or_directory)
+ if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
return Result;
}
- return error_code(errc::no_such_file_or_directory, system_category());
+ return make_error_code(llvm::errc::no_such_file_or_directory);
}
ErrorOr<Entry *> VFSFromYAML::lookupPath(sys::path::const_iterator Start,
@@ -767,7 +922,7 @@
if (CaseSensitive ? !Start->equals(From->getName())
: !Start->equals_lower(From->getName()))
// failure to match
- return error_code(errc::no_such_file_or_directory, system_category());
+ return make_error_code(llvm::errc::no_such_file_or_directory);
++Start;
@@ -778,25 +933,22 @@
DirectoryEntry *DE = dyn_cast<DirectoryEntry>(From);
if (!DE)
- return error_code(errc::not_a_directory, system_category());
+ return make_error_code(llvm::errc::not_a_directory);
for (DirectoryEntry::iterator I = DE->contents_begin(),
E = DE->contents_end();
I != E; ++I) {
ErrorOr<Entry *> Result = lookupPath(Start, End, *I);
- if (Result || Result.getError() != errc::no_such_file_or_directory)
+ if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
return Result;
}
- return error_code(errc::no_such_file_or_directory, system_category());
+ return make_error_code(llvm::errc::no_such_file_or_directory);
}
-ErrorOr<Status> VFSFromYAML::status(const Twine &Path) {
- ErrorOr<Entry *> Result = lookupPath(Path);
- if (!Result)
- return Result.getError();
-
+ErrorOr<Status> VFSFromYAML::status(const Twine &Path, Entry *E) {
+ assert(E != nullptr);
std::string PathStr(Path.str());
- if (FileEntry *F = dyn_cast<FileEntry>(*Result)) {
+ if (FileEntry *F = dyn_cast<FileEntry>(E)) {
ErrorOr<Status> S = ExternalFS->status(F->getExternalContentsPath());
assert(!S || S->getName() == F->getExternalContentsPath());
if (S && !F->useExternalName(UseExternalNames))
@@ -805,31 +957,39 @@
S->IsVFSMapped = true;
return S;
} else { // directory
- DirectoryEntry *DE = cast<DirectoryEntry>(*Result);
+ DirectoryEntry *DE = cast<DirectoryEntry>(E);
Status S = DE->getStatus();
S.setName(PathStr);
return S;
}
}
-error_code VFSFromYAML::openFileForRead(const Twine &Path,
- std::unique_ptr<vfs::File> &Result) {
+ErrorOr<Status> VFSFromYAML::status(const Twine &Path) {
+ ErrorOr<Entry *> Result = lookupPath(Path);
+ if (!Result)
+ return Result.getError();
+ return status(Path, *Result);
+}
+
+std::error_code
+VFSFromYAML::openFileForRead(const Twine &Path,
+ std::unique_ptr<vfs::File> &Result) {
ErrorOr<Entry *> E = lookupPath(Path);
if (!E)
return E.getError();
FileEntry *F = dyn_cast<FileEntry>(*E);
if (!F) // FIXME: errc::not_a_file?
- return error_code(errc::invalid_argument, system_category());
+ return make_error_code(llvm::errc::invalid_argument);
- if (error_code EC = ExternalFS->openFileForRead(F->getExternalContentsPath(),
- Result))
+ if (std::error_code EC =
+ ExternalFS->openFileForRead(F->getExternalContentsPath(), Result))
return EC;
if (!F->useExternalName(UseExternalNames))
Result->setName(Path.str());
- return error_code::success();
+ return std::error_code();
}
IntrusiveRefCntPtr<FileSystem>
@@ -981,3 +1141,70 @@
JSONWriter(OS).write(Mappings, IsCaseSensitive);
}
+
+VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(const Twine &_Path,
+ VFSFromYAML &FS,
+ DirectoryEntry::iterator Begin,
+ DirectoryEntry::iterator End,
+ std::error_code &EC)
+ : Dir(_Path.str()), FS(FS), Current(Begin), End(End) {
+ if (Current != End) {
+ SmallString<128> PathStr(Dir);
+ llvm::sys::path::append(PathStr, (*Current)->getName());
+ llvm::ErrorOr<vfs::Status> S = FS.status(PathStr.str());
+ if (S)
+ CurrentEntry = *S;
+ else
+ EC = S.getError();
+ }
+}
+
+std::error_code VFSFromYamlDirIterImpl::increment() {
+ assert(Current != End && "cannot iterate past end");
+ if (++Current != End) {
+ SmallString<128> PathStr(Dir);
+ llvm::sys::path::append(PathStr, (*Current)->getName());
+ llvm::ErrorOr<vfs::Status> S = FS.status(PathStr.str());
+ if (!S)
+ return S.getError();
+ CurrentEntry = *S;
+ } else {
+ CurrentEntry = Status();
+ }
+ return std::error_code();
+}
+
+vfs::recursive_directory_iterator::recursive_directory_iterator(FileSystem &FS_,
+ const Twine &Path,
+ std::error_code &EC)
+ : FS(&FS_) {
+ directory_iterator I = FS->dir_begin(Path, EC);
+ if (!EC && I != directory_iterator()) {
+ State = std::make_shared<IterState>();
+ State->push(I);
+ }
+}
+
+vfs::recursive_directory_iterator &
+recursive_directory_iterator::increment(std::error_code &EC) {
+ assert(FS && State && !State->empty() && "incrementing past end");
+ assert(State->top()->isStatusKnown() && "non-canonical end iterator");
+ vfs::directory_iterator End;
+ if (State->top()->isDirectory()) {
+ vfs::directory_iterator I = FS->dir_begin(State->top()->getName(), EC);
+ if (EC)
+ return *this;
+ if (I != End) {
+ State->push(I);
+ return *this;
+ }
+ }
+
+ while (!State->empty() && State->top().increment(EC) == End)
+ State->pop();
+
+ if (State->empty())
+ State.reset(); // end iterator
+
+ return *this;
+}