diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp b/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp new file mode 100644 index 0000000..d30f921 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp @@ -0,0 +1,116 @@ +//===--- ModuleDependencyCollector.cpp - Collect module dependencies ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect the dependencies of a set of modules. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/Utils.h" +#include "clang/Serialization/ASTReader.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" + +using namespace clang; + +namespace { +/// Private implementation for ModuleDependencyCollector +class ModuleDependencyListener : public ASTReaderListener { + ModuleDependencyCollector &Collector; + + std::error_code copyToRoot(StringRef Src); +public: + ModuleDependencyListener(ModuleDependencyCollector &Collector) + : Collector(Collector) {} + bool needsInputFileVisitation() override { return true; } + bool needsSystemInputFileVisitation() override { return true; } + bool visitInputFile(StringRef Filename, bool IsSystem, + bool IsOverridden) override; +}; +} + +void ModuleDependencyCollector::attachToASTReader(ASTReader &R) { + R.addListener(new ModuleDependencyListener(*this)); +} + +void ModuleDependencyCollector::writeFileMap() { + if (Seen.empty()) + return; + + SmallString<256> Dest = getDest(); + llvm::sys::path::append(Dest, "vfs.yaml"); + + std::string ErrorInfo; + llvm::raw_fd_ostream OS(Dest.c_str(), ErrorInfo, llvm::sys::fs::F_Text); + if (!ErrorInfo.empty()) { + setHasErrors(); + return; + } + VFSWriter.write(OS); +} + +/// Remove traversal (ie, . or ..) from the given absolute path. +static void removePathTraversal(SmallVectorImpl<char> &Path) { + using namespace llvm::sys; + SmallVector<StringRef, 16> ComponentStack; + StringRef P(Path.data(), Path.size()); + + // Skip the root path, then look for traversal in the components. + StringRef Rel = path::relative_path(P); + for (StringRef C : llvm::make_range(path::begin(Rel), path::end(Rel))) { + if (C == ".") + continue; + if (C == "..") { + assert(ComponentStack.size() && "Path traverses out of parent"); + ComponentStack.pop_back(); + } else + ComponentStack.push_back(C); + } + + // The stack is now the path without any directory traversal. + SmallString<256> Buffer = path::root_path(P); + for (StringRef C : ComponentStack) + path::append(Buffer, C); + + // Put the result in Path. + Path.swap(Buffer); +} + +std::error_code ModuleDependencyListener::copyToRoot(StringRef Src) { + using namespace llvm::sys; + + // We need an absolute path to append to the root. + SmallString<256> AbsoluteSrc = Src; + fs::make_absolute(AbsoluteSrc); + removePathTraversal(AbsoluteSrc); + + // Build the destination path. + SmallString<256> Dest = Collector.getDest(); + path::append(Dest, path::relative_path(AbsoluteSrc)); + + // Copy the file into place. + if (std::error_code EC = fs::create_directories(path::parent_path(Dest), + /*IgnoreExisting=*/true)) + return EC; + if (std::error_code EC = fs::copy_file(AbsoluteSrc.str(), Dest.str())) + return EC; + // Use the absolute path under the root for the file mapping. + Collector.addFileMapping(AbsoluteSrc.str(), Dest.str()); + return std::error_code(); +} + +bool ModuleDependencyListener::visitInputFile(StringRef Filename, bool IsSystem, + bool IsOverridden) { + if (Collector.insertSeen(Filename)) + if (copyToRoot(Filename)) + Collector.setHasErrors(); + return true; +} |