1 //===-- CoverageChecker.h - Module map coverage checker -*- C++ -*-------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===--------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Definitions for CoverageChecker.
12 ///
13 //===--------------------------------------------------------------------===//
14 
15 #ifndef COVERAGECHECKER_H
16 #define COVERAGECHECKER_H
17 
18 #include "clang/Basic/Diagnostic.h"
19 #include "clang/Basic/FileManager.h"
20 #include "clang/Basic/LangOptions.h"
21 #include "clang/Basic/TargetInfo.h"
22 #include "clang/Basic/TargetOptions.h"
23 #include "clang/Frontend/TextDiagnosticPrinter.h"
24 #include "clang/Lex/HeaderSearch.h"
25 #include "clang/Lex/HeaderSearchOptions.h"
26 #include "clang/Lex/ModuleMap.h"
27 #include "clang/Lex/Preprocessor.h"
28 #include "llvm/ADT/StringSet.h"
29 #include "llvm/Support/Host.h"
30 #include <string>
31 #include <vector>
32 
33 namespace Modularize {
34 
35 /// Module map checker class.
36 /// This is the heart of the checker.
37 /// The doChecks function does the main work.
38 /// The data members store the options and internally collected data.
39 class CoverageChecker {
40   // Checker arguments.
41 
42   /// The module.modulemap file path. Can be relative or absolute.
43   llvm::StringRef ModuleMapPath;
44   /// The include paths to check for files.
45   /// (Note that other directories above these paths are ignored.
46   /// To expect all files to be accounted for from the module.modulemap
47   /// file directory on down, leave this empty.)
48   std::vector<std::string> IncludePaths;
49   /// The remaining arguments, to be passed to the front end.
50   llvm::ArrayRef<std::string> CommandLine;
51   /// The module map.
52   clang::ModuleMap *ModMap;
53 
54   // Internal data.
55 
56   /// Directory containing the module map.
57   /// Might be relative to the current directory, or absolute.
58   std::string ModuleMapDirectory;
59   /// Set of all the headers found in the module map.
60   llvm::StringSet<llvm::MallocAllocator> ModuleMapHeadersSet;
61   /// All the headers found in the file system starting at the
62   /// module map, or the union of those from the include paths.
63   std::vector<std::string> FileSystemHeaders;
64   /// Headers found in file system, but not in module map.
65   std::vector<std::string> UnaccountedForHeaders;
66 
67 public:
68   /// Constructor.
69   /// You can use the static createCoverageChecker to create an instance
70   /// of this object.
71   /// \param ModuleMapPath The module.modulemap file path.
72   ///   Can be relative or absolute.
73   /// \param IncludePaths The include paths to check for files.
74   ///   (Note that other directories above these paths are ignored.
75   ///   To expect all files to be accounted for from the module.modulemap
76   ///   file directory on down, leave this empty.)
77   /// \param CommandLine Compile command line arguments.
78   /// \param ModuleMap The module map to check.
79   CoverageChecker(llvm::StringRef ModuleMapPath,
80     std::vector<std::string> &IncludePaths,
81     llvm::ArrayRef<std::string> CommandLine,
82     clang::ModuleMap *ModuleMap);
83 
84   /// Create instance of CoverageChecker.
85   /// \param ModuleMapPath The module.modulemap file path.
86   ///   Can be relative or absolute.
87   /// \param IncludePaths The include paths to check for files.
88   ///   (Note that other directories above these paths are ignored.
89   ///   To expect all files to be accounted for from the module.modulemap
90   ///   file directory on down, leave this empty.)
91   /// \param CommandLine Compile command line arguments.
92   /// \param ModuleMap The module map to check.
93   /// \returns Initialized CoverageChecker object.
94   static std::unique_ptr<CoverageChecker> createCoverageChecker(
95       llvm::StringRef ModuleMapPath, std::vector<std::string> &IncludePaths,
96       llvm::ArrayRef<std::string> CommandLine, clang::ModuleMap *ModuleMap);
97 
98   /// Do checks.
99   /// Starting from the directory of the module.modulemap file,
100   /// Find all header files, optionally looking only at files
101   /// covered by the include path options, and compare against
102   /// the headers referenced by the module.modulemap file.
103   /// Display warnings for unaccounted-for header files.
104   /// \returns 0 if there were no errors or warnings, 1 if there
105   ///   were warnings, 2 if any other problem, such as a bad
106   ///   module map path argument was specified.
107   std::error_code doChecks();
108 
109   // The following functions are called by doChecks.
110 
111   /// Collect module headers.
112   /// Walks the modules and collects referenced headers into
113   /// ModuleMapHeadersSet.
114   void collectModuleHeaders();
115 
116   /// Collect referenced headers from one module.
117   /// Collects the headers referenced in the given module into
118   /// ModuleMapHeadersSet.
119   /// \param Mod The module reference.
120   /// \return True if no errors.
121   bool collectModuleHeaders(const clang::Module &Mod);
122 
123   /// Collect headers from an umbrella directory.
124   /// \param UmbrellaDirName The umbrella directory name.
125   /// \return True if no errors.
126   bool collectUmbrellaHeaders(llvm::StringRef UmbrellaDirName);
127 
128   /// Collect headers rferenced from an umbrella file.
129   /// \param UmbrellaHeaderName The umbrella file path.
130   /// \return True if no errors.
131   bool collectUmbrellaHeaderHeaders(llvm::StringRef UmbrellaHeaderName);
132 
133   /// Called from CoverageCheckerCallbacks to track a header included
134   /// from an umbrella header.
135   /// \param HeaderName The header file path.
136   void collectUmbrellaHeaderHeader(llvm::StringRef HeaderName);
137 
138   /// Collect file system header files.
139   /// This function scans the file system for header files,
140   /// starting at the directory of the module.modulemap file,
141   /// optionally filtering out all but the files covered by
142   /// the include path options.
143   /// \returns True if no errors.
144   bool collectFileSystemHeaders();
145 
146   /// Collect file system header files from the given path.
147   /// This function scans the file system for header files,
148   /// starting at the given directory, which is assumed to be
149   /// relative to the directory of the module.modulemap file.
150   /// \returns True if no errors.
151   bool collectFileSystemHeaders(llvm::StringRef IncludePath);
152 
153   /// Find headers unaccounted-for in module map.
154   /// This function compares the list of collected header files
155   /// against those referenced in the module map.  Display
156   /// warnings for unaccounted-for header files.
157   /// Save unaccounted-for file list for possible.
158   /// fixing action.
159   void findUnaccountedForHeaders();
160 };
161 
162 } // end namespace Modularize
163 
164 #endif // COVERAGECHECKER_H
165