[clang-tools-extra] r189984 - modularize - Fix of header dependencies - this time with the source.
John Thompson
John.Thompson.JTSoftware at gmail.com
Wed Sep 4 13:46:24 PDT 2013
Author: jtsoftware
Date: Wed Sep 4 15:46:24 2013
New Revision: 189984
URL: http://llvm.org/viewvc/llvm-project?rev=189984&view=rev
Log:
modularize - Fix of header dependencies - this time with the source.
Modified:
clang-tools-extra/trunk/modularize/Modularize.cpp
Modified: clang-tools-extra/trunk/modularize/Modularize.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/modularize/Modularize.cpp?rev=189984&r1=189983&r2=189984&view=diff
==============================================================================
--- clang-tools-extra/trunk/modularize/Modularize.cpp (original)
+++ clang-tools-extra/trunk/modularize/Modularize.cpp Wed Sep 4 15:46:24 2013
@@ -18,6 +18,11 @@
// Modularize takes as argument a file name for a file containing the
// newline-separated list of headers to check with respect to each other.
// Lines beginning with '#' and empty lines are ignored.
+// Header file names followed by a colon and other space-separated
+// file names will include those extra files as dependencies.
+// The file names can be relative or full paths, but must be on the
+// same line.
+//
// Modularize also accepts regular front-end arguments.
//
// Usage: modularize [-prefix (optional header path prefix)]
@@ -112,6 +117,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Driver/Options.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/Preprocessor.h"
@@ -119,7 +125,12 @@
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/Config/config.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -131,9 +142,12 @@
#include <vector>
#include "PreprocessorTracker.h"
-using namespace clang::tooling;
using namespace clang;
+using namespace clang::driver;
+using namespace clang::driver::options;
+using namespace clang::tooling;
using namespace llvm;
+using namespace llvm::opt;
using namespace Modularize;
// Option to specify a file name for a list of header files to check.
@@ -154,13 +168,19 @@ cl::opt<std::string> HeaderPrefix(
" If not specified,"
" the files are considered to be relative to the header list file."));
-// Read the header list file and collect the header file names.
+typedef SmallVector<std::string, 4> DependentsVector;
+typedef StringMap<DependentsVector> DependencyMap;
+
+// Read the header list file and collect the header file names and
+// optional dependencies.
error_code getHeaderFileNames(SmallVectorImpl<std::string> &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)
@@ -180,25 +200,94 @@ error_code getHeaderFileNames(SmallVecto
for (SmallVectorImpl<StringRef>::iterator I = Strings.begin(),
E = Strings.end();
I != E; ++I) {
- StringRef Line = (*I).trim();
+ StringRef Line = I->trim();
// Ignore comments and empty lines.
if (Line.empty() || (Line[0] == '#'))
continue;
+ std::pair<StringRef, StringRef> TargetAndDependents = Line.split(':');
SmallString<256> HeaderFileName;
// Prepend header file name prefix if it's not absolute.
- if (sys::path::is_absolute(Line))
- HeaderFileName = Line;
+ if (sys::path::is_absolute(TargetAndDependents.first))
+ llvm::sys::path::native(TargetAndDependents.first, HeaderFileName);
else {
- HeaderFileName = HeaderDirectory;
- sys::path::append(HeaderFileName, Line);
+ if (HeaderDirectory.size() != 0)
+ HeaderFileName = HeaderDirectory;
+ else
+ HeaderFileName = CurrentDirectory;
+ sys::path::append(HeaderFileName, TargetAndDependents.first);
+ llvm::sys::path::native(HeaderFileName.str(), HeaderFileName);
+ }
+ // Handle optional dependencies.
+ DependentsVector Dependents;
+ SmallVector<StringRef, 4> 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]);
+ }
+ llvm::sys::path::native(Dependent.str(), Dependent);
+ Dependents.push_back(Dependent.str());
}
- // Save the resulting header file path.
+ // Save the resulting header file path and dependencies.
HeaderFileNames.push_back(HeaderFileName.str());
+ Dependencies[HeaderFileName.str()] = Dependents;
}
return error_code::success();
}
+// Helper function for finding the input file in an arguments list.
+std::string findInputFile(const CommandLineArguments &CLArgs) {
+ OwningPtr<OptTable> Opts(createDriverOptTable());
+ const unsigned IncludedFlagsBitmask = options::CC1Option;
+ unsigned MissingArgIndex, MissingArgCount;
+ SmallVector<const char *, 256> Argv;
+ for (CommandLineArguments::const_iterator I = CLArgs.begin(),
+ E = CLArgs.end();
+ I != E; ++I)
+ Argv.push_back(I->c_str());
+ OwningPtr<InputArgList> Args(
+ Opts->ParseArgs(Argv.data(), Argv.data() + Argv.size(), MissingArgIndex,
+ MissingArgCount, IncludedFlagsBitmask));
+ std::vector<std::string> Inputs = Args->getAllArgValues(OPT_INPUT);
+ return Inputs.back();
+}
+
+// We provide this derivation to add in "-include (file)" arguments for header
+// dependencies.
+class AddDependenciesAdjuster : public ArgumentsAdjuster {
+public:
+ AddDependenciesAdjuster(DependencyMap &Dependencies)
+ : Dependencies(Dependencies) {}
+
+private:
+ // Callback for adjusting commandline arguments.
+ CommandLineArguments Adjust(const CommandLineArguments &Args) {
+ std::string InputFile = findInputFile(Args);
+ DependentsVector &FileDependents = Dependencies[InputFile];
+ int Count = FileDependents.size();
+ if (Count == 0)
+ return Args;
+ CommandLineArguments NewArgs(Args);
+ for (int Index = 0; Index < Count; ++Index) {
+ NewArgs.push_back("-include");
+ std::string File(std::string("\"") + FileDependents[Index] +
+ std::string("\""));
+ NewArgs.push_back(FileDependents[Index]);
+ }
+ return NewArgs;
+ }
+ DependencyMap &Dependencies;
+};
+
// FIXME: The Location class seems to be something that we might
// want to design to be applicable to a wider range of tools, and stick it
// somewhere into Tooling/ in mainline
@@ -513,9 +602,11 @@ int main(int Argc, const char **Argv) {
return 1;
}
- // Get header file names.
+ // Get header file names and dependencies.
SmallVector<std::string, 32> Headers;
- if (error_code EC = getHeaderFileNames(Headers, ListFileName, HeaderPrefix)) {
+ DependencyMap Dependencies;
+ if (error_code EC = getHeaderFileNames(Headers, Dependencies, ListFileName,
+ HeaderPrefix)) {
errs() << Argv[0] << ": error: Unable to get header list '" << ListFileName
<< "': " << EC.message() << '\n';
return 1;
@@ -534,6 +625,7 @@ int main(int Argc, const char **Argv) {
// Parse all of the headers, detecting duplicates.
EntityMap Entities;
ClangTool Tool(*Compilations, Headers);
+ Tool.appendArgumentsAdjuster(new AddDependenciesAdjuster(Dependencies));
int HadErrors =
Tool.run(new ModularizeFrontendActionFactory(Entities, *PPTracker));
More information about the cfe-commits
mailing list