summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/modularize/Modularize.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/modularize/Modularize.cpp')
-rw-r--r--clang-tools-extra/modularize/Modularize.cpp144
1 files changed, 139 insertions, 5 deletions
diff --git a/clang-tools-extra/modularize/Modularize.cpp b/clang-tools-extra/modularize/Modularize.cpp
index 462add52e12..2a917949972 100644
--- a/clang-tools-extra/modularize/Modularize.cpp
+++ b/clang-tools-extra/modularize/Modularize.cpp
@@ -58,6 +58,11 @@
// module to be created in the generated module.map file. Note that
// you will likely need to edit this file to suit the needs of your
// headers.
+// -problem-files-list=(problem files list file name)
+// For use only with module map assistant. Input list of files that
+// have problems with respect to modules. These will still be
+// included in the generated module map, but will be marked as
+// "excluded" headers.
// -root-module=(root module name)
// Specifies a root module to be created in the generated module.map
// file.
@@ -68,6 +73,14 @@
// Don't do the coverage check.
// -coverage-check-only
// Only do the coverage check.
+// -display-file-lists
+// Display lists of good files (no compile errors), problem files,
+// and a combined list with problem files preceded by a '#'.
+// This can be used to quickly determine which files have problems.
+// The latter combined list might be useful in starting to modularize
+// a set of headers. You can start with a full list of headers,
+// use -display-file-lists option, and then use the combined list as
+// your intermediate list, uncommenting-out headers as you fix them.
//
// Note that by default, the modularize assumes .h files contain C++ source.
// If your .h files in the file list contain another language, you should
@@ -274,8 +287,15 @@ static cl::opt<std::string> ModuleMapPath(
" If no path is specified and if prefix option is specified,"
" use prefix for file path."));
-// Option for assistant mode, telling modularize to output a module map
-// based on the headers list, and where to put it.
+// Option to specify list of problem files for assistant.
+// This will cause assistant to exclude these files.
+static cl::opt<std::string> ProblemFilesList(
+ "problem-files-list", cl::init(""),
+ cl::desc(
+ "List of files with compilation or modularization problems for"
+ " assistant mode. This will be excluded."));
+
+// Option for assistant mode, telling modularize the name of the root module.
static cl::opt<std::string>
RootModule("root-module", cl::init(""),
cl::desc("Specify the name of the root module."));
@@ -304,6 +324,12 @@ static cl::opt<bool>
CoverageCheckOnly("coverage-check-only", cl::init(false),
cl::desc("Only do the coverage check."));
+// Option for displaying lists of good, bad, and mixed files.
+static cl::opt<bool>
+DisplayFileLists("display-file-lists", cl::init(false),
+cl::desc("Display lists of good files (no compile errors), problem files,"
+ " and a combined list with problem files preceded by a '#'."));
+
// Save the program name for error messages.
const char *Argv0;
// Save the command line for comments.
@@ -704,6 +730,78 @@ private:
int &HadErrors;
};
+class CompileCheckVisitor
+ : public RecursiveASTVisitor<CompileCheckVisitor> {
+public:
+ CompileCheckVisitor() {}
+
+ bool TraverseStmt(Stmt *S) { return true; }
+ bool TraverseType(QualType T) { return true; }
+ bool TraverseTypeLoc(TypeLoc TL) { return true; }
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { return true; }
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+ return true;
+ }
+ bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo) {
+ return true;
+ }
+ bool TraverseTemplateName(TemplateName Template) { return true; }
+ bool TraverseTemplateArgument(const TemplateArgument &Arg) { return true; }
+ bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
+ return true;
+ }
+ bool TraverseTemplateArguments(const TemplateArgument *Args,
+ unsigned NumArgs) {
+ return true;
+ }
+ bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { return true; }
+ bool TraverseLambdaCapture(LambdaCapture C) { return true; }
+
+ // Check 'extern "*" {}' block for #include directives.
+ bool VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+ return true;
+ }
+
+ // Check 'namespace (name) {}' block for #include directives.
+ bool VisitNamespaceDecl(const NamespaceDecl *D) {
+ return true;
+ }
+
+ // Collect definition entities.
+ bool VisitNamedDecl(NamedDecl *ND) {
+ return true;
+ }
+};
+
+class CompileCheckConsumer : public ASTConsumer {
+public:
+ CompileCheckConsumer() {}
+
+ void HandleTranslationUnit(ASTContext &Ctx) override {
+ CompileCheckVisitor().TraverseDecl(Ctx.getTranslationUnitDecl());
+ }
+};
+
+class CompileCheckAction : public SyntaxOnlyAction {
+public:
+ CompileCheckAction() {}
+
+protected:
+ std::unique_ptr<clang::ASTConsumer>
+ CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
+ return llvm::make_unique<CompileCheckConsumer>();
+ }
+};
+
+class CompileCheckFrontendActionFactory : public FrontendActionFactory {
+public:
+ CompileCheckFrontendActionFactory() {}
+
+ CompileCheckAction *create() override {
+ return new CompileCheckAction();
+ }
+};
+
int main(int Argc, const char **Argv) {
// Save program name for error messages.
@@ -730,7 +828,7 @@ int main(int Argc, const char **Argv) {
ModUtil.reset(
ModularizeUtilities::createModularizeUtilities(
- ListFileNames, HeaderPrefix));
+ ListFileNames, HeaderPrefix, ProblemFilesList));
// Get header file names and dependencies.
if (ModUtil->loadAllHeaderListsAndDependencies())
@@ -739,6 +837,7 @@ int main(int Argc, const char **Argv) {
// If we are in assistant mode, output the module map and quit.
if (ModuleMapPath.length() != 0) {
if (!createModuleMap(ModuleMapPath, ModUtil->HeaderFileNames,
+ ModUtil->ProblemFileNames,
ModUtil->Dependencies, HeaderPrefix, RootModule))
return 1; // Failed.
return 0; // Success - Skip checks in assistant mode.
@@ -767,9 +866,36 @@ int main(int Argc, const char **Argv) {
PreprocessorTracker::create(ModUtil->HeaderFileNames,
BlockCheckHeaderListOnly));
- // Parse all of the headers, detecting duplicates.
+ // Coolect entities here.
EntityMap Entities;
- ClangTool Tool(*Compilations, ModUtil->HeaderFileNames);
+
+ // Because we can't easily determine which files failed
+ // during the tool run, if we're collecting the file lists
+ // for display, we do a first compile pass on individual
+ // files to find which ones don't compile stand-alone.
+ if (DisplayFileLists) {
+ // First, make a pass to just get compile errors.
+ for (auto &CompileCheckFile : ModUtil->HeaderFileNames) {
+ llvm::SmallVector<std::string, 32> CompileCheckFileArray;
+ CompileCheckFileArray.push_back(CompileCheckFile);
+ ClangTool CompileCheckTool(*Compilations, CompileCheckFileArray);
+ CompileCheckTool.appendArgumentsAdjuster(
+ getModularizeArgumentsAdjuster(ModUtil->Dependencies));
+ int CompileCheckFileErrors = 0;
+ CompileCheckFrontendActionFactory CompileCheckFactory;
+ CompileCheckFileErrors |= CompileCheckTool.run(&CompileCheckFactory);
+ if (CompileCheckFileErrors != 0) {
+ ModUtil->addUniqueProblemFile(CompileCheckFile); // Save problem file.
+ HadErrors |= 1;
+ }
+ else
+ ModUtil->addNoCompileErrorsFile(CompileCheckFile); // Save good file.
+ }
+ }
+
+ // Then we make another pass on the good files to do the rest of the work.
+ ClangTool Tool(*Compilations,
+ (DisplayFileLists ? ModUtil->GoodFileNames : ModUtil->HeaderFileNames));
Tool.appendArgumentsAdjuster(
getModularizeArgumentsAdjuster(ModUtil->Dependencies));
ModularizeFrontendActionFactory Factory(Entities, *PPTracker, HadErrors);
@@ -816,6 +942,7 @@ int main(int Argc, const char **Argv) {
for (LocationArray::iterator FE = DI->end(); FI != FE; ++FI) {
errs() << " " << FI->File->getName() << ":" << FI->Line << ":"
<< FI->Column << "\n";
+ ModUtil->addUniqueProblemFile(FI->File->getName());
}
HadErrors = 1;
}
@@ -845,6 +972,7 @@ int main(int Argc, const char **Argv) {
}
HadErrors = 1;
+ ModUtil->addUniqueProblemFile(H->first->getName());
errs() << "error: header '" << H->first->getName()
<< "' has different contents depending on how it was included.\n";
for (unsigned I = 0, N = H->second.size(); I != N; ++I) {
@@ -855,5 +983,11 @@ int main(int Argc, const char **Argv) {
}
}
+ if (DisplayFileLists) {
+ ModUtil->displayProblemFiles();
+ ModUtil->displayGoodFiles();
+ ModUtil->displayCombinedFiles();
+ }
+
return HadErrors;
}
OpenPOWER on IntegriCloud