From d845baecb47f4e74e2cd7ec94dc8d91c15660425 Mon Sep 17 00:00:00 2001 From: John Thompson Date: Fri, 13 Feb 2015 14:29:22 +0000 Subject: [PATCH] Moved header list loading to new class. This is staging for adding module map loading and checking support. llvm-svn: 229108 --- clang-tools-extra/modularize/CMakeLists.txt | 1 + clang-tools-extra/modularize/Modularize.cpp | 112 +++------------- .../modularize/ModularizeUtilities.cpp | 124 ++++++++++++++++++ .../modularize/ModularizeUtilities.h | 74 +++++++++++ 4 files changed, 218 insertions(+), 93 deletions(-) create mode 100644 clang-tools-extra/modularize/ModularizeUtilities.cpp create mode 100644 clang-tools-extra/modularize/ModularizeUtilities.h diff --git a/clang-tools-extra/modularize/CMakeLists.txt b/clang-tools-extra/modularize/CMakeLists.txt index eaf220884c86..64994fcd70f0 100644 --- a/clang-tools-extra/modularize/CMakeLists.txt +++ b/clang-tools-extra/modularize/CMakeLists.txt @@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS add_clang_executable(modularize Modularize.cpp ModuleAssistant.cpp + ModularizeUtilities.cpp PreprocessorTracker.cpp ) diff --git a/clang-tools-extra/modularize/Modularize.cpp b/clang-tools-extra/modularize/Modularize.cpp index 078cc5437d3f..9d91557fb0d3 100644 --- a/clang-tools-extra/modularize/Modularize.cpp +++ b/clang-tools-extra/modularize/Modularize.cpp @@ -144,6 +144,7 @@ //===----------------------------------------------------------------------===// #include "Modularize.h" +#include "ModularizeUtilities.h" #include "PreprocessorTracker.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" @@ -178,10 +179,10 @@ using namespace llvm::opt; using namespace Modularize; // Option to specify a file name for a list of header files to check. -cl::list -ListFileNames(cl::Positional, cl::value_desc("list"), - cl::desc(""), - cl::CommaSeparated); +cl::list +ListFileNames(cl::Positional, cl::value_desc("list"), + cl::desc(""), + cl::CommaSeparated); // Collect all other arguments, which will be passed to the front end. cl::list @@ -224,80 +225,6 @@ const char *Argv0; // Save the command line for comments. std::string CommandLine; -// Read the header list file and collect the header file names and -// optional dependencies. -std::error_code -getHeaderFileNames(SmallVectorImpl &HeaderFileNames, - DependencyMap &Dependencies, StringRef ListFileName, - StringRef HeaderPrefix) { - // By default, use the path component of the list file name. - SmallString<256> HeaderDirectory(ListFileName); - sys::path::remove_filename(HeaderDirectory); - SmallString<256> CurrentDirectory; - sys::fs::current_path(CurrentDirectory); - - // Get the prefix if we have one. - if (HeaderPrefix.size() != 0) - HeaderDirectory = HeaderPrefix; - - // Read the header list file into a buffer. - ErrorOr> listBuffer = - MemoryBuffer::getFile(ListFileName); - if (std::error_code EC = listBuffer.getError()) - return EC; - - // Parse the header list into strings. - SmallVector Strings; - listBuffer.get()->getBuffer().split(Strings, "\n", -1, false); - - // Collect the header file names from the string list. - for (SmallVectorImpl::iterator I = Strings.begin(), - E = Strings.end(); - I != E; ++I) { - StringRef Line = I->trim(); - // Ignore comments and empty lines. - if (Line.empty() || (Line[0] == '#')) - continue; - std::pair TargetAndDependents = Line.split(':'); - SmallString<256> HeaderFileName; - // Prepend header file name prefix if it's not absolute. - if (sys::path::is_absolute(TargetAndDependents.first)) - llvm::sys::path::native(TargetAndDependents.first, HeaderFileName); - else { - if (HeaderDirectory.size() != 0) - HeaderFileName = HeaderDirectory; - else - HeaderFileName = CurrentDirectory; - sys::path::append(HeaderFileName, TargetAndDependents.first); - sys::path::native(HeaderFileName); - } - // Handle optional dependencies. - DependentsVector Dependents; - SmallVector DependentsList; - TargetAndDependents.second.split(DependentsList, " ", -1, false); - int Count = DependentsList.size(); - for (int Index = 0; Index < Count; ++Index) { - SmallString<256> Dependent; - if (sys::path::is_absolute(DependentsList[Index])) - Dependent = DependentsList[Index]; - else { - if (HeaderDirectory.size() != 0) - Dependent = HeaderDirectory; - else - Dependent = CurrentDirectory; - sys::path::append(Dependent, DependentsList[Index]); - } - sys::path::native(Dependent); - Dependents.push_back(Dependent.str()); - } - // Save the resulting header file path and dependencies. - HeaderFileNames.push_back(HeaderFileName.str()); - Dependencies[HeaderFileName.str()] = Dependents; - } - - return std::error_code(); -} - // Helper function for finding the input file in an arguments list. std::string findInputFile(const CommandLineArguments &CLArgs) { std::unique_ptr Opts(createDriverOptTable()); @@ -706,22 +633,20 @@ int main(int Argc, const char **Argv) { return 1; } + std::unique_ptr ModUtil; + + ModUtil.reset( + ModularizeUtilities::createModularizeUtilities( + ListFileNames, HeaderPrefix)); + // Get header file names and dependencies. - SmallVector Headers; - DependencyMap Dependencies; - for (auto I : ListFileNames) { - if (std::error_code EC = - getHeaderFileNames(Headers, Dependencies, I, HeaderPrefix)) { - errs() << Argv[0] << ": error: Unable to get header list '" << I - << "': " << EC.message() << '\n'; - return 1; - } - } + ModUtil->loadAllHeaderListsAndDependencies(); + // If we are in assistant mode, output the module map and quit. if (ModuleMapPath.length() != 0) { - if (!createModuleMap(ModuleMapPath, Headers, Dependencies, HeaderPrefix, - RootModule)) + if (!createModuleMap(ModuleMapPath, ModUtil->HeaderFileNames, + ModUtil->Dependencies, HeaderPrefix, RootModule)) return 1; // Failed. return 0; // Success - Skip checks in assistant mode. } @@ -735,12 +660,13 @@ int main(int Argc, const char **Argv) { // Create preprocessor tracker, to watch for macro and conditional problems. std::unique_ptr PPTracker( - PreprocessorTracker::create(Headers, BlockCheckHeaderListOnly)); + PreprocessorTracker::create(ModUtil->HeaderFileNames, + BlockCheckHeaderListOnly)); // Parse all of the headers, detecting duplicates. EntityMap Entities; - ClangTool Tool(*Compilations, Headers); - Tool.appendArgumentsAdjuster(getAddDependenciesAdjuster(Dependencies)); + ClangTool Tool(*Compilations, ModUtil->HeaderFileNames); + Tool.appendArgumentsAdjuster(getAddDependenciesAdjuster(ModUtil->Dependencies)); int HadErrors = 0; ModularizeFrontendActionFactory Factory(Entities, *PPTracker, HadErrors); HadErrors |= Tool.run(&Factory); diff --git a/clang-tools-extra/modularize/ModularizeUtilities.cpp b/clang-tools-extra/modularize/ModularizeUtilities.cpp new file mode 100644 index 000000000000..14c9f5d27561 --- /dev/null +++ b/clang-tools-extra/modularize/ModularizeUtilities.cpp @@ -0,0 +1,124 @@ +//===--- extra/modularize/ModularizeUtilities.cpp -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a class for loading and validating a module map or +// header list by checking that all headers in the corresponding directories +// are accounted for. +// +//===----------------------------------------------------------------------===// + +#include "ModularizeUtilities.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; +using namespace Modularize; + +// ModularizeUtilities class implementation. + +// Constructor. +ModularizeUtilities::ModularizeUtilities(std::vector &InputPaths, + llvm::StringRef Prefix) + : InputFilePaths(InputPaths), + HeaderPrefix(Prefix) {} + +// Create instance of ModularizeUtilities, to simplify setting up +// subordinate objects. +ModularizeUtilities *ModularizeUtilities::createModularizeUtilities( + std::vector &InputPaths, llvm::StringRef Prefix) { + + return new ModularizeUtilities(InputPaths, Prefix); +} + +// Load all header lists and dependencies. +std::error_code ModularizeUtilities::loadAllHeaderListsAndDependencies() { + typedef std::vector::iterator Iter; + for (Iter I = InputFilePaths.begin(), E = InputFilePaths.end(); I != E; ++I) { + if (std::error_code EC = loadSingleHeaderListsAndDependencies(*I)) { + errs() << "modularize: error: Unable to get header list '" << *I + << "': " << EC.message() << '\n'; + return EC; + } + } + return std::error_code(); +} + +// Load single header list and dependencies. +std::error_code ModularizeUtilities::loadSingleHeaderListsAndDependencies( + llvm::StringRef InputPath) { + + // By default, use the path component of the list file name. + SmallString<256> HeaderDirectory(InputPath); + llvm::sys::path::remove_filename(HeaderDirectory); + SmallString<256> CurrentDirectory; + llvm::sys::fs::current_path(CurrentDirectory); + + // Get the prefix if we have one. + if (HeaderPrefix.size() != 0) + HeaderDirectory = HeaderPrefix; + + // Read the header list file into a buffer. + ErrorOr> listBuffer = + MemoryBuffer::getFile(InputPath); + if (std::error_code EC = listBuffer.getError()) + return EC; + + // Parse the header list into strings. + SmallVector Strings; + listBuffer.get()->getBuffer().split(Strings, "\n", -1, false); + + // Collect the header file names from the string list. + for (SmallVectorImpl::iterator I = Strings.begin(), + E = Strings.end(); + I != E; ++I) { + StringRef Line = I->trim(); + // Ignore comments and empty lines. + if (Line.empty() || (Line[0] == '#')) + continue; + std::pair TargetAndDependents = Line.split(':'); + SmallString<256> HeaderFileName; + // Prepend header file name prefix if it's not absolute. + if (llvm::sys::path::is_absolute(TargetAndDependents.first)) + llvm::sys::path::native(TargetAndDependents.first, HeaderFileName); + else { + if (HeaderDirectory.size() != 0) + HeaderFileName = HeaderDirectory; + else + HeaderFileName = CurrentDirectory; + llvm::sys::path::append(HeaderFileName, TargetAndDependents.first); + llvm::sys::path::native(HeaderFileName); + } + // Handle optional dependencies. + DependentsVector Dependents; + SmallVector DependentsList; + TargetAndDependents.second.split(DependentsList, " ", -1, false); + int Count = DependentsList.size(); + for (int Index = 0; Index < Count; ++Index) { + SmallString<256> Dependent; + if (llvm::sys::path::is_absolute(DependentsList[Index])) + Dependent = DependentsList[Index]; + else { + if (HeaderDirectory.size() != 0) + Dependent = HeaderDirectory; + else + Dependent = CurrentDirectory; + llvm::sys::path::append(Dependent, DependentsList[Index]); + } + llvm::sys::path::native(Dependent); + Dependents.push_back(Dependent.str()); + } + // Save the resulting header file path and dependencies. + HeaderFileNames.push_back(HeaderFileName.str()); + Dependencies[HeaderFileName.str()] = Dependents; + } + return std::error_code(); +} diff --git a/clang-tools-extra/modularize/ModularizeUtilities.h b/clang-tools-extra/modularize/ModularizeUtilities.h new file mode 100644 index 000000000000..3cf24fd13858 --- /dev/null +++ b/clang-tools-extra/modularize/ModularizeUtilities.h @@ -0,0 +1,74 @@ +//=====-- ModularizeUtilities.h - Utilities for modularize -*- C++ -*-======// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--------------------------------------------------------------------===// +/// +/// \file +/// \brief ModularizeUtilities class definition. +/// +//===--------------------------------------------------------------------===// + +#ifndef MODULARIZEUTILITIES_H +#define MODULARIZEUTILITIES_H + +#include "Modularize.h" +#include +#include + +namespace Modularize { + +/// Modularize utilities class. +/// Support functions and data for modularize. +class ModularizeUtilities { +public: + // Input arguments. + + /// The input file paths. + std::vector InputFilePaths; + /// The header prefix. + llvm::StringRef HeaderPrefix; + + // Output data. + + // List of top-level header files. + llvm::SmallVector HeaderFileNames; + // Map of top-level header file dependencies. + DependencyMap Dependencies; + + // Functions. + + /// Constructor. + /// You can use the static createModularizeUtilities to create an instance + /// of this object. + /// \param InputPaths The input file paths. + /// \param Prefix The headear path prefix. + ModularizeUtilities(std::vector &InputPaths, + llvm::StringRef Prefix); + + /// Create instance of ModularizeUtilities. + /// \param InputPaths The input file paths. + /// \param Prefix The headear path prefix. + /// \returns Initialized ModularizeUtilities object. + static ModularizeUtilities *createModularizeUtilities( + std::vector &InputPaths, + llvm::StringRef Prefix); + + /// Load header list and dependencies. + /// \returns std::error_code. + std::error_code loadAllHeaderListsAndDependencies(); + +protected: + /// Load single header list and dependencies. + /// \param InputPath The input file path. + /// \returns std::error_code. + std::error_code loadSingleHeaderListsAndDependencies( + llvm::StringRef InputPath); +}; + +} // end namespace Modularize + +#endif // MODULARIZEUTILITIES_H