diff options
12 files changed, 403 insertions, 37 deletions
diff --git a/clang-tools-extra/docs/ModularizeUsage.rst b/clang-tools-extra/docs/ModularizeUsage.rst index c1e3c87fac9..b7c4b65c09e 100644 --- a/clang-tools-extra/docs/ModularizeUsage.rst +++ b/clang-tools-extra/docs/ModularizeUsage.rst @@ -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. diff --git a/clang-tools-extra/docs/modularize.rst b/clang-tools-extra/docs/modularize.rst index 2612461aa1a..98bb8a08c0d 100644 --- a/clang-tools-extra/docs/modularize.rst +++ b/clang-tools-extra/docs/modularize.rst @@ -210,6 +210,10 @@ The following module map will be generated:: 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
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; } diff --git a/clang-tools-extra/modularize/Modularize.h b/clang-tools-extra/modularize/Modularize.h index ef24fc6b3e7..a3f2ad3e069 100644 --- a/clang-tools-extra/modularize/Modularize.h +++ b/clang-tools-extra/modularize/Modularize.h @@ -37,6 +37,7 @@ typedef llvm::StringMap<DependentsVector> DependencyMap; /// 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> DependencyMap; /// \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); diff --git a/clang-tools-extra/modularize/ModularizeUtilities.cpp b/clang-tools-extra/modularize/ModularizeUtilities.cpp index 7594b6725cc..08c92fc90c0 100644 --- a/clang-tools-extra/modularize/ModularizeUtilities.cpp +++ b/clang-tools-extra/modularize/ModularizeUtilities.cpp @@ -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(std::vector<std::string> &InputPaths, // 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::loadAllHeaderListsAndDependencies() { } } } + // 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::loadSingleHeaderListsAndDependencies( 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::collectUmbrellaHeaders(StringRef UmbrellaDirName, } // 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::getDirectoryFromPath(StringRef Path) { 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"; + } +} diff --git a/clang-tools-extra/modularize/ModularizeUtilities.h b/clang-tools-extra/modularize/ModularizeUtilities.h index 9c1ee74107d..a3c412e43de 100644 --- a/clang-tools-extra/modularize/ModularizeUtilities.h +++ b/clang-tools-extra/modularize/ModularizeUtilities.h @@ -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. diff --git a/clang-tools-extra/modularize/ModuleAssistant.cpp b/clang-tools-extra/modularize/ModuleAssistant.cpp index 8a9b0c43f73..f982f17e8af 100644 --- a/clang-tools-extra/modularize/ModuleAssistant.cpp +++ b/clang-tools-extra/modularize/ModuleAssistant.cpp @@ -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 &OS, int Indent) { 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::StringRef MightBeReservedName) { 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 *RootModule, 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 *RootModule, // 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::StringRef ModuleMapPath, // 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; diff --git a/clang-tools-extra/test/modularize/Inputs/CompileError/HasError.h b/clang-tools-extra/test/modularize/Inputs/CompileError/HasError.h new file mode 100644 index 00000000000..4395cb166de --- /dev/null +++ b/clang-tools-extra/test/modularize/Inputs/CompileError/HasError.h @@ -0,0 +1,2 @@ +typedef WithoutDep BadType; + diff --git a/clang-tools-extra/test/modularize/Inputs/CompileError/Level1A.h b/clang-tools-extra/test/modularize/Inputs/CompileError/Level1A.h new file mode 100644 index 00000000000..10eef6787e4 --- /dev/null +++ b/clang-tools-extra/test/modularize/Inputs/CompileError/Level1A.h @@ -0,0 +1 @@ +#define MACRO_1A 1 diff --git a/clang-tools-extra/test/modularize/Inputs/CompileError/module.modulemap b/clang-tools-extra/test/modularize/Inputs/CompileError/module.modulemap new file mode 100644 index 00000000000..fbb8e7db4d1 --- /dev/null +++ b/clang-tools-extra/test/modularize/Inputs/CompileError/module.modulemap @@ -0,0 +1,10 @@ +// module.map
+
+module Level1A {
+ header "Level1A.h"
+ export *
+}
+module HasError {
+ header "HasError.h"
+ export *
+}
diff --git a/clang-tools-extra/test/modularize/ProblemsCompileError.modularize b/clang-tools-extra/test/modularize/ProblemsCompileError.modularize new file mode 100644 index 00000000000..a7ad29862b1 --- /dev/null +++ b/clang-tools-extra/test/modularize/ProblemsCompileError.modularize @@ -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' diff --git a/clang-tools-extra/test/modularize/ProblemsDisplayLists.modularize b/clang-tools-extra/test/modularize/ProblemsDisplayLists.modularize new file mode 100644 index 00000000000..31be95c6b6b --- /dev/null +++ b/clang-tools-extra/test/modularize/ProblemsDisplayLists.modularize @@ -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 |