[clang-tools-extra] r241880 - Added mechanism to modularize for doing a compilation precheck

John Thompson John.Thompson.JTSoftware at gmail.com
Thu Jul 9 17:37:25 PDT 2015


Author: jtsoftware
Date: Thu Jul  9 19:37:25 2015
New Revision: 241880

URL: http://llvm.org/viewvc/llvm-project?rev=241880&view=rev
Log:
Added mechanism to modularize for doing a compilation precheck
to determine files that have comnpilation or dependency problems.
A new -display-file-lists option use this to display lists of good files
(no compile errors), problem files, and a combined list with
problem files preceded by a '#'.  The problem files list can be
used in the module map generation assistant mode to exclude
problem files.  The combined files list can be used during module
map development.  See added docs.

Added:
    clang-tools-extra/trunk/test/modularize/Inputs/CompileError/
    clang-tools-extra/trunk/test/modularize/Inputs/CompileError/HasError.h
    clang-tools-extra/trunk/test/modularize/Inputs/CompileError/Level1A.h
    clang-tools-extra/trunk/test/modularize/Inputs/CompileError/module.modulemap
    clang-tools-extra/trunk/test/modularize/ProblemsCompileError.modularize
    clang-tools-extra/trunk/test/modularize/ProblemsDisplayLists.modularize
Modified:
    clang-tools-extra/trunk/docs/ModularizeUsage.rst
    clang-tools-extra/trunk/docs/modularize.rst
    clang-tools-extra/trunk/modularize/Modularize.cpp
    clang-tools-extra/trunk/modularize/Modularize.h
    clang-tools-extra/trunk/modularize/ModularizeUtilities.cpp
    clang-tools-extra/trunk/modularize/ModularizeUtilities.h
    clang-tools-extra/trunk/modularize/ModuleAssistant.cpp

Modified: clang-tools-extra/trunk/docs/ModularizeUsage.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ModularizeUsage.rst?rev=241880&r1=241879&r2=241880&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ModularizeUsage.rst (original)
+++ clang-tools-extra/trunk/docs/ModularizeUsage.rst Thu Jul  9 19:37:25 2015
@@ -59,6 +59,13 @@ Modularize Command Line Options
 
   Generate a module map and output it to the given file.  See the description
   in :ref:`module-map-generation`.
+  
+.. option:: -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.
 
 .. option:: -root-module=<root-name>
 
@@ -79,3 +86,13 @@ Modularize Command Line Options
 .. option:: -coverage-check-only
 
   Only do the coverage check for a module map.
+
+.. option:: -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.

Modified: clang-tools-extra/trunk/docs/modularize.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/modularize.rst?rev=241880&r1=241879&r2=241880&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/modularize.rst (original)
+++ clang-tools-extra/trunk/docs/modularize.rst Thu Jul  9 19:37:25 2015
@@ -210,6 +210,10 @@ The following module map will be generat
 An optional ``-root-module=<root-name>`` option can be used to cause a root module
 to be created which encloses all the modules.
 
+An optional ``-problem-files-list=<problem-file-name> can be used to input
+a list of files to be excluded, perhaps as a temporary stop-gap measure until
+problem headers can be fixed.
+
 For example, with the same header list from above::
 
   // Output/NoProblemsAssistant.txt

Modified: clang-tools-extra/trunk/modularize/Modularize.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/modularize/Modularize.cpp?rev=241880&r1=241879&r2=241880&view=diff
==============================================================================
--- clang-tools-extra/trunk/modularize/Modularize.cpp (original)
+++ clang-tools-extra/trunk/modularize/Modularize.cpp Thu Jul  9 19:37:25 2015
@@ -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> ModuleMapPat
              " 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;
 }

Modified: clang-tools-extra/trunk/modularize/Modularize.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/modularize/Modularize.h?rev=241880&r1=241879&r2=241880&view=diff
==============================================================================
--- clang-tools-extra/trunk/modularize/Modularize.h (original)
+++ clang-tools-extra/trunk/modularize/Modularize.h Thu Jul  9 19:37:25 2015
@@ -37,6 +37,7 @@ typedef llvm::StringMap<DependentsVector
 /// Create the module map file.
 /// \param ModuleMapPath The path to the module map file to be generated.
 /// \param HeaderFileNames The list of header files, absolute native paths.
+/// \param ProblemFileNames The list of problem header files.
 /// \param Dependencies Map of headers that depend on other headers.
 /// \param HeaderPrefix Tells the code where the headers are, if they
 ///   aren's in the current directory, allowing the generator to strip
@@ -46,6 +47,7 @@ typedef llvm::StringMap<DependentsVector
 /// \returns True if successful.
 bool createModuleMap(llvm::StringRef ModuleMapPath,
                      llvm::ArrayRef<std::string> HeaderFileNames,
+                     llvm::ArrayRef<std::string> ProblemFileNames,
                      DependencyMap &Dependencies, llvm::StringRef HeaderPrefix,
                      llvm::StringRef RootModuleName);
 

Modified: clang-tools-extra/trunk/modularize/ModularizeUtilities.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/modularize/ModularizeUtilities.cpp?rev=241880&r1=241879&r2=241880&view=diff
==============================================================================
--- clang-tools-extra/trunk/modularize/ModularizeUtilities.cpp (original)
+++ clang-tools-extra/trunk/modularize/ModularizeUtilities.cpp Thu Jul  9 19:37:25 2015
@@ -42,9 +42,11 @@ public:
 
 // Constructor.
 ModularizeUtilities::ModularizeUtilities(std::vector<std::string> &InputPaths,
-                                         llvm::StringRef Prefix)
+                                         llvm::StringRef Prefix,
+                                         llvm::StringRef ProblemFilesListPath)
   : InputFilePaths(InputPaths),
     HeaderPrefix(Prefix),
+    ProblemFilesPath(ProblemFilesListPath),
     HasModuleMap(false),
     MissingHeaderCount(0),
     // Init clang stuff needed for loading the module map and preprocessing.
@@ -65,9 +67,10 @@ ModularizeUtilities::ModularizeUtilities
 // Create instance of ModularizeUtilities, to simplify setting up
 // subordinate objects.
 ModularizeUtilities *ModularizeUtilities::createModularizeUtilities(
-    std::vector<std::string> &InputPaths, llvm::StringRef Prefix) {
+    std::vector<std::string> &InputPaths, llvm::StringRef Prefix,
+    llvm::StringRef ProblemFilesListPath) {
 
-  return new ModularizeUtilities(InputPaths, Prefix);
+  return new ModularizeUtilities(InputPaths, Prefix, ProblemFilesListPath);
 }
 
 // Load all header lists and dependencies.
@@ -91,6 +94,15 @@ std::error_code ModularizeUtilities::loa
       }
     }
   }
+  // If we have a problem files list.
+  if (ProblemFilesPath.size() != 0) {
+    // Load problem files list.
+    if (std::error_code EC = loadProblemHeaderList(ProblemFilesPath)) {
+      errs() << "modularize: error: Unable to get problem header list '" << ProblemFilesPath
+        << "': " << EC.message() << '\n';
+      return EC;
+    }
+  }
   return std::error_code();
 }
 
@@ -194,6 +206,58 @@ std::error_code ModularizeUtilities::loa
   return std::error_code();
 }
 
+// Load problem header list.
+std::error_code ModularizeUtilities::loadProblemHeaderList(
+  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<std::unique_ptr<MemoryBuffer>> listBuffer =
+    MemoryBuffer::getFile(InputPath);
+  if (std::error_code EC = listBuffer.getError())
+    return EC;
+
+  // Parse the header list into strings.
+  SmallVector<StringRef, 32> Strings;
+  listBuffer.get()->getBuffer().split(Strings, "\n", -1, false);
+
+  // Collect the header file names from the string list.
+  for (SmallVectorImpl<StringRef>::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;
+    SmallString<256> HeaderFileName;
+    // Prepend header file name prefix if it's not absolute.
+    if (llvm::sys::path::is_absolute(Line))
+      llvm::sys::path::native(Line, HeaderFileName);
+    else {
+      if (HeaderDirectory.size() != 0)
+        HeaderFileName = HeaderDirectory;
+      else
+        HeaderFileName = CurrentDirectory;
+      llvm::sys::path::append(HeaderFileName, Line);
+      llvm::sys::path::native(HeaderFileName);
+    }
+    // Get canonical form.
+    HeaderFileName = getCanonicalPath(HeaderFileName);
+    // Save the resulting header file path.
+    ProblemFileNames.push_back(HeaderFileName.str());
+  }
+  return std::error_code();
+}
+
 // Load single module map and extract header file list.
 std::error_code ModularizeUtilities::loadModuleMap(
     llvm::StringRef InputPath) {
@@ -364,24 +428,24 @@ bool ModularizeUtilities::collectUmbrell
 }
 
 // Replace .. embedded in path for purposes of having
-// a canonical path.
+// a canonical path.
 static std::string replaceDotDot(StringRef Path) {
-  SmallString<128> Buffer;
-  llvm::sys::path::const_iterator B = llvm::sys::path::begin(Path),
-    E = llvm::sys::path::end(Path);
-  while (B != E) {
-    if (B->compare(".") == 0) {
-    }
-    else if (B->compare("..") == 0)
-      llvm::sys::path::remove_filename(Buffer);
-    else
-      llvm::sys::path::append(Buffer, *B);
-    ++B;
-  }
-  if (Path.endswith("/") || Path.endswith("\\"))
-    Buffer.append(1, Path.back());
-  return Buffer.c_str();
-}
+  SmallString<128> Buffer;
+  llvm::sys::path::const_iterator B = llvm::sys::path::begin(Path),
+    E = llvm::sys::path::end(Path);
+  while (B != E) {
+    if (B->compare(".") == 0) {
+    }
+    else if (B->compare("..") == 0)
+      llvm::sys::path::remove_filename(Buffer);
+    else
+      llvm::sys::path::append(Buffer, *B);
+    ++B;
+  }
+  if (Path.endswith("/") || Path.endswith("\\"))
+    Buffer.append(1, Path.back());
+  return Buffer.c_str();
+}
 
 // Convert header path to canonical form.
 // The canonical form is basically just use forward slashes, and remove "./".
@@ -424,3 +488,62 @@ std::string ModularizeUtilities::getDire
     return ".";
   return Directory.str();
 }
+
+// Add unique problem file.
+// Also standardizes the path.
+void ModularizeUtilities::addUniqueProblemFile(std::string FilePath) {
+  FilePath = getCanonicalPath(FilePath);
+  // Don't add if already present.
+  for(auto &TestFilePath : ProblemFileNames) {
+    if (TestFilePath == FilePath)
+      return;
+  }
+  ProblemFileNames.push_back(FilePath);
+}
+
+// Add file with no compile errors.
+// Also standardizes the path.
+void ModularizeUtilities::addNoCompileErrorsFile(std::string FilePath) {
+  FilePath = getCanonicalPath(FilePath);
+  GoodFileNames.push_back(FilePath);
+}
+
+// List problem files.
+void ModularizeUtilities::displayProblemFiles() {
+  errs() << "\nThese are the files with possible errors:\n\n";
+  for (auto &ProblemFile : ProblemFileNames) {
+    errs() << ProblemFile << "\n";
+  }
+}
+
+// List files with no problems.
+void ModularizeUtilities::displayGoodFiles() {
+  errs() << "\nThese are the files with no detected errors:\n\n";
+  for (auto &GoodFile : HeaderFileNames) {
+    bool Good = true;
+    for (auto &ProblemFile : ProblemFileNames) {
+      if (ProblemFile == GoodFile) {
+        Good = false;
+        break;
+      }
+    }
+    if (Good)
+      errs() << GoodFile << "\n";
+  }
+}
+
+// List files with problem files commented out.
+void ModularizeUtilities::displayCombinedFiles() {
+  errs() <<
+    "\nThese are the combined files, with problem files preceded by #:\n\n";
+  for (auto &File : HeaderFileNames) {
+    bool Good = true;
+    for (auto &ProblemFile : ProblemFileNames) {
+      if (ProblemFile == File) {
+        Good = false;
+        break;
+      }
+    }
+    errs() << (Good ? "" : "#") << File << "\n";
+  }
+}

Modified: clang-tools-extra/trunk/modularize/ModularizeUtilities.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/modularize/ModularizeUtilities.h?rev=241880&r1=241879&r2=241880&view=diff
==============================================================================
--- clang-tools-extra/trunk/modularize/ModularizeUtilities.h (original)
+++ clang-tools-extra/trunk/modularize/ModularizeUtilities.h Thu Jul  9 19:37:25 2015
@@ -43,6 +43,8 @@ public:
   std::vector<std::string> InputFilePaths;
   /// The header prefix.
   llvm::StringRef HeaderPrefix;
+  /// The path of problem files list file.
+  llvm::StringRef ProblemFilesPath;
 
   // Output data.
 
@@ -54,6 +56,11 @@ public:
   bool HasModuleMap;
   /// Missing header count.
   int MissingHeaderCount;
+  /// List of header files with no problems during the first pass,
+  /// that is, no compile errors.
+  llvm::SmallVector<std::string, 32> GoodFileNames;
+  /// List of header files with problems.
+  llvm::SmallVector<std::string, 32> ProblemFileNames;
 
   // Functions.
 
@@ -62,16 +69,20 @@ public:
   /// of this object.
   /// \param InputPaths The input file paths.
   /// \param Prefix The headear path prefix.
+  /// \param ProblemFilesListPath The problem header list path.
   ModularizeUtilities(std::vector<std::string> &InputPaths,
-                      llvm::StringRef Prefix);
+                      llvm::StringRef Prefix,
+                      llvm::StringRef ProblemFilesListPath);
 
   /// Create instance of ModularizeUtilities.
   /// \param InputPaths The input file paths.
   /// \param Prefix The headear path prefix.
+  /// \param ProblemFilesListPath The problem header list path.
   /// \returns Initialized ModularizeUtilities object.
   static ModularizeUtilities *createModularizeUtilities(
       std::vector<std::string> &InputPaths,
-      llvm::StringRef Prefix);
+      llvm::StringRef Prefix,
+      llvm::StringRef ProblemFilesListPath);
 
   /// Load header list and dependencies.
   /// \returns std::error_code.
@@ -95,6 +106,25 @@ public:
   std::error_code doCoverageCheck(std::vector<std::string> &IncludePaths,
                                   llvm::ArrayRef<std::string> CommandLine);
 
+  /// Add unique problem file.
+  /// Also standardizes the path.
+  /// \param FilePath Problem file path.
+  void addUniqueProblemFile(std::string FilePath);
+
+  /// Add file with no compile errors.
+  /// Also standardizes the path.
+  /// \param FilePath Problem file path.
+  void addNoCompileErrorsFile(std::string FilePath);
+
+  /// List problem files.
+  void displayProblemFiles();
+
+  /// List files with no problems.
+  void displayGoodFiles();
+
+  /// List files with problem files commented out.
+  void displayCombinedFiles();
+
   // Internal.
 
 protected:
@@ -105,6 +135,12 @@ protected:
   std::error_code loadSingleHeaderListsAndDependencies(
       llvm::StringRef InputPath);
 
+  /// Load problem header list.
+  /// \param InputPath The input file path.
+  /// \returns std::error_code.
+  std::error_code loadProblemHeaderList(
+    llvm::StringRef InputPath);
+
   /// Load single module map and extract header file list.
   /// \param InputPath The input file path.
   /// \returns std::error_code.

Modified: clang-tools-extra/trunk/modularize/ModuleAssistant.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/modularize/ModuleAssistant.cpp?rev=241880&r1=241879&r2=241880&view=diff
==============================================================================
--- clang-tools-extra/trunk/modularize/ModuleAssistant.cpp (original)
+++ clang-tools-extra/trunk/modularize/ModuleAssistant.cpp Thu Jul  9 19:37:25 2015
@@ -45,7 +45,7 @@ namespace {
 // Represents a module.
 class Module {
 public:
-  Module(llvm::StringRef Name);
+  Module(llvm::StringRef Name, bool Problem);
   Module();
   ~Module();
   bool output(llvm::raw_fd_ostream &OS, int Indent);
@@ -55,6 +55,7 @@ public:
   std::string Name;
   std::vector<std::string> HeaderFileNames;
   std::vector<Module *> SubModules;
+  bool IsProblem;
 };
 
 } // end anonymous namespace.
@@ -62,8 +63,9 @@ public:
 // Module functions:
 
 // Constructors.
-Module::Module(llvm::StringRef Name) : Name(Name) {}
-Module::Module() {}
+Module::Module(llvm::StringRef Name, bool Problem)
+  : Name(Name), IsProblem(Problem) {}
+Module::Module() : IsProblem(false) {}
 
 // Destructor.
 Module::~Module() {
@@ -97,7 +99,10 @@ bool Module::output(llvm::raw_fd_ostream
                                           E = HeaderFileNames.end();
        I != E; ++I) {
     OS.indent(Indent);
-    OS << "header \"" << *I << "\"\n";
+    if (IsProblem)
+      OS << "exclude header \"" << *I << "\"\n";
+    else
+      OS << "header \"" << *I << "\"\n";
   }
 
   // If this module has header files, output export directive.
@@ -156,7 +161,8 @@ ensureNoCollisionWithReservedName(llvm::
 static bool addModuleDescription(Module *RootModule,
                                  llvm::StringRef HeaderFilePath,
                                  llvm::StringRef HeaderPrefix,
-                                 DependencyMap &Dependencies) {
+                                 DependencyMap &Dependencies,
+                                 bool IsProblemFile) {
   Module *CurrentModule = RootModule;
   DependentsVector &FileDependents = Dependencies[HeaderFilePath];
   std::string FilePath;
@@ -191,7 +197,7 @@ static bool addModuleDescription(Module
     Stem = ensureNoCollisionWithReservedName(Stem);
     Module *SubModule = CurrentModule->findSubModule(Stem);
     if (!SubModule) {
-      SubModule = new Module(Stem);
+      SubModule = new Module(Stem, IsProblemFile);
       CurrentModule->SubModules.push_back(SubModule);
     }
     CurrentModule = SubModule;
@@ -204,10 +210,11 @@ static bool addModuleDescription(Module
 // Create the internal module tree representation.
 static Module *loadModuleDescriptions(
     llvm::StringRef RootModuleName, llvm::ArrayRef<std::string> HeaderFileNames,
+    llvm::ArrayRef<std::string> ProblemFileNames,
     DependencyMap &Dependencies, llvm::StringRef HeaderPrefix) {
 
   // Create root module.
-  Module *RootModule = new Module(RootModuleName);
+  Module *RootModule = new Module(RootModuleName, false);
 
   llvm::SmallString<256> CurrentDirectory;
   llvm::sys::fs::current_path(CurrentDirectory);
@@ -220,8 +227,16 @@ static Module *loadModuleDescriptions(
   for (llvm::ArrayRef<std::string>::iterator I = HeaderFileNames.begin(),
                                              E = HeaderFileNames.end();
        I != E; ++I) {
+    std::string Header(*I);
+    bool IsProblemFile = false;
+    for (auto &ProblemFile : ProblemFileNames) {
+      if (ProblemFile == Header) {
+        IsProblemFile = true;
+        break;
+      }
+    }
     // Add as a module.
-    if (!addModuleDescription(RootModule, *I, HeaderPrefix, Dependencies))
+    if (!addModuleDescription(RootModule, Header, HeaderPrefix, Dependencies, IsProblemFile))
       return nullptr;
   }
 
@@ -277,11 +292,14 @@ static bool writeModuleMap(llvm::StringR
 // Module map generation entry point.
 bool createModuleMap(llvm::StringRef ModuleMapPath,
                      llvm::ArrayRef<std::string> HeaderFileNames,
+                     llvm::ArrayRef<std::string> ProblemFileNames,
                      DependencyMap &Dependencies, llvm::StringRef HeaderPrefix,
                      llvm::StringRef RootModuleName) {
   // Load internal representation of modules.
-  std::unique_ptr<Module> RootModule(loadModuleDescriptions(
-      RootModuleName, HeaderFileNames, Dependencies, HeaderPrefix));
+  std::unique_ptr<Module> RootModule(
+    loadModuleDescriptions(
+      RootModuleName, HeaderFileNames, ProblemFileNames, Dependencies,
+      HeaderPrefix));
   if (!RootModule.get())
     return false;
 

Added: clang-tools-extra/trunk/test/modularize/Inputs/CompileError/HasError.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/modularize/Inputs/CompileError/HasError.h?rev=241880&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/modularize/Inputs/CompileError/HasError.h (added)
+++ clang-tools-extra/trunk/test/modularize/Inputs/CompileError/HasError.h Thu Jul  9 19:37:25 2015
@@ -0,0 +1,2 @@
+typedef WithoutDep BadType;
+

Added: clang-tools-extra/trunk/test/modularize/Inputs/CompileError/Level1A.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/modularize/Inputs/CompileError/Level1A.h?rev=241880&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/modularize/Inputs/CompileError/Level1A.h (added)
+++ clang-tools-extra/trunk/test/modularize/Inputs/CompileError/Level1A.h Thu Jul  9 19:37:25 2015
@@ -0,0 +1 @@
+#define MACRO_1A 1

Added: clang-tools-extra/trunk/test/modularize/Inputs/CompileError/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/modularize/Inputs/CompileError/module.modulemap?rev=241880&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/modularize/Inputs/CompileError/module.modulemap (added)
+++ clang-tools-extra/trunk/test/modularize/Inputs/CompileError/module.modulemap Thu Jul  9 19:37:25 2015
@@ -0,0 +1,10 @@
+// module.map
+
+module Level1A {
+  header "Level1A.h"
+  export *
+}
+module HasError {
+  header "HasError.h"
+  export *
+}

Added: clang-tools-extra/trunk/test/modularize/ProblemsCompileError.modularize
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/modularize/ProblemsCompileError.modularize?rev=241880&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/modularize/ProblemsCompileError.modularize (added)
+++ clang-tools-extra/trunk/test/modularize/ProblemsCompileError.modularize Thu Jul  9 19:37:25 2015
@@ -0,0 +1,3 @@
+# RUN: not modularize %S/Inputs/CompileError/module.modulemap 2>&1 | FileCheck %s
+
+# CHECK: {{.*}}{{[/\\]}}Inputs{{[/\\]}}CompileError{{[/\\]}}HasError.h:1:9: error: unknown type name 'WithoutDep'

Added: clang-tools-extra/trunk/test/modularize/ProblemsDisplayLists.modularize
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/modularize/ProblemsDisplayLists.modularize?rev=241880&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/modularize/ProblemsDisplayLists.modularize (added)
+++ clang-tools-extra/trunk/test/modularize/ProblemsDisplayLists.modularize Thu Jul  9 19:37:25 2015
@@ -0,0 +1,16 @@
+# RUN: not modularize -display-file-lists %S/Inputs/CompileError/module.modulemap 2>&1 | FileCheck %s
+
+# CHECK: {{.*}}{{[/\\]}}Inputs{{[/\\]}}CompileError{{[/\\]}}HasError.h:1:9: error: unknown type name 'WithoutDep'
+
+# CHECK: These are the files with possible errors:
+
+# CHECK: Inputs/CompileError/HasError.h
+
+# CHECK: These are the files with no detected errors:
+
+# CHECK: Inputs/CompileError/Level1A.h
+
+# CHECK: These are the combined files, with problem files preceded by #:
+
+# CHECK: {{.*}}Inputs/CompileError/HasError.h
+# CHECK: Inputs/CompileError/Level1A.h





More information about the cfe-commits mailing list