54 #include "clang/AST/ASTConsumer.h" 56 #include "clang/AST/ASTContext.h" 57 #include "clang/AST/RecursiveASTVisitor.h" 58 #include "clang/Basic/SourceManager.h" 59 #include "clang/Driver/Options.h" 60 #include "clang/Frontend/CompilerInstance.h" 61 #include "clang/Frontend/FrontendAction.h" 62 #include "clang/Frontend/FrontendActions.h" 63 #include "clang/Lex/PPCallbacks.h" 64 #include "clang/Lex/Preprocessor.h" 65 #include "clang/Tooling/CompilationDatabase.h" 66 #include "clang/Tooling/Tooling.h" 67 #include "llvm/Option/Option.h" 68 #include "llvm/Support/CommandLine.h" 69 #include "llvm/Support/FileSystem.h" 70 #include "llvm/Support/Path.h" 71 #include "llvm/Support/raw_ostream.h" 74 using namespace clang;
78 namespace cl = llvm::cl;
91 CharSourceRange FilenameRange,
const FileEntry *File,
92 StringRef SearchPath, StringRef RelativePath,
93 const Module *Imported,
94 SrcMgr::CharacteristicKind FileType)
override {
95 Checker.collectUmbrellaHeaderHeader(File->getName());
109 PP.addPPCallbacks(std::make_unique<CoverageCheckerCallbacks>(Checker));
119 StringRef InFile)
override {
120 return std::make_unique<CoverageCheckerConsumer>(Checker,
121 CI.getPreprocessor());
131 : Checker(Checker) {}
133 std::unique_ptr<FrontendAction>
create()
override {
134 return std::make_unique<CoverageCheckerAction>(Checker);
147 clang::ModuleMap *ModuleMap)
148 : ModuleMapPath(ModuleMapPath), IncludePaths(IncludePaths),
149 CommandLine(CommandLine),
155 StringRef ModuleMapPath, std::vector<std::string> &IncludePaths,
156 ArrayRef<std::string> CommandLine, clang::ModuleMap *ModuleMap) {
158 return std::make_unique<CoverageChecker>(ModuleMapPath, IncludePaths,
159 CommandLine, ModuleMap);
172 std::error_code returnValue;
179 return std::error_code(2, std::generic_category());
185 if (!UnaccountedForHeaders.empty())
186 returnValue = std::error_code(1, std::generic_category());
197 for (ModuleMap::module_iterator I = ModMap->module_begin(),
198 E = ModMap->module_end();
210 if (
const FileEntry *UmbrellaHeader = Mod.getUmbrellaHeader().Entry) {
213 UmbrellaHeader->getName()));
218 else if (
const DirectoryEntry *UmbrellaDir = Mod.getUmbrellaDir().Entry) {
224 for (
auto &HeaderKind : Mod.Headers)
225 for (
auto &Header : HeaderKind)
227 Header.Entry->getName()));
229 for (
auto MI = Mod.submodule_begin(), MIEnd = Mod.submodule_end();
239 SmallString<256>
Directory(ModuleMapDirectory);
240 if (UmbrellaDirName.size())
241 sys::path::append(Directory, UmbrellaDirName);
242 if (Directory.size() == 0)
246 for (sys::fs::directory_iterator I(Directory.str(), EC),
E; I !=
E;
250 std::string File(I->path());
251 llvm::ErrorOr<sys::fs::basic_file_status> Status = I->status();
254 sys::fs::file_type
Type = Status->type();
256 if (Type == sys::fs::file_type::directory_file) {
274 SmallString<256> PathBuf(ModuleMapDirectory);
277 if (ModuleMapDirectory.length() == 0)
278 sys::fs::current_path(PathBuf);
281 std::unique_ptr<CompilationDatabase> Compilations;
282 Compilations.reset(
new FixedCompilationDatabase(Twine(PathBuf), CommandLine));
284 std::vector<std::string> HeaderPath;
285 HeaderPath.push_back(UmbrellaHeaderName);
288 ClangTool Tool(*Compilations, HeaderPath);
299 SmallString<256> PathBuf(ModuleMapDirectory);
301 if (ModuleMapDirectory.length() == 0)
302 sys::fs::current_path(PathBuf);
305 if (HeaderName.startswith(PathBuf))
306 HeaderName = HeaderName.substr(PathBuf.size() + 1);
325 if (IncludePaths.size() == 0) {
332 for (std::vector<std::string>::const_iterator I = IncludePaths.begin(),
333 E = IncludePaths.end();
341 std::sort(FileSystemHeaders.begin(), FileSystemHeaders.end());
354 SmallString<256>
Directory(ModuleMapDirectory);
355 if (IncludePath.size())
356 sys::path::append(Directory, IncludePath);
357 if (Directory.size() == 0)
359 if (IncludePath.startswith(
"/") || IncludePath.startswith(
"\\") ||
360 ((IncludePath.size() >= 2) && (IncludePath[1] ==
':'))) {
361 llvm::errs() <<
"error: Include path \"" << IncludePath
362 <<
"\" is not relative to the module map file.\n";
369 for (sys::fs::recursive_directory_iterator I(Directory.str(), EC),
E; I !=
E;
374 StringRef file(I->path());
375 llvm::ErrorOr<sys::fs::basic_file_status> Status = I->status();
378 sys::fs::file_type type = Status->type();
380 if (type == sys::fs::file_type::directory_file)
384 if ((file.find(
"\\.") != StringRef::npos) ||
385 (file.find(
"/.") != StringRef::npos))
395 llvm::errs() <<
"warning: No headers found in include path: \"" 396 << IncludePath <<
"\"\n";
413 for (std::vector<std::string>::const_iterator I = FileSystemHeaders.begin(),
414 E = FileSystemHeaders.end();
417 if (ModuleMapHeadersSet.insert(*I).second) {
418 UnaccountedForHeaders.push_back(*I);
419 llvm::errs() <<
"warning: " << ModuleMapPath
420 <<
" does not account for file: " << *I <<
"\n";
bool collectUmbrellaHeaders(llvm::StringRef UmbrellaDirName)
Collect headers from an umbrella directory.
static std::string getCanonicalPath(llvm::StringRef FilePath)
Convert header path to canonical form.
CoverageChecker(llvm::StringRef ModuleMapPath, std::vector< std::string > &IncludePaths, llvm::ArrayRef< std::string > CommandLine, clang::ModuleMap *ModuleMap)
Constructor.
CoverageCheckerCallbacks(CoverageChecker &Checker)
std::unique_ptr< FrontendAction > create() override
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
static std::string getDirectoryFromPath(llvm::StringRef Path)
Get directory path component from file path.
void collectModuleHeaders()
Collect module headers.
static cl::opt< std::string > ModuleMapPath("module-map-path", cl::init(""), cl::desc("Turn on module map output and specify output path or file name." " If no path is specified and if prefix option is specified," " use prefix for file path."))
CoverageCheckerAction(CoverageChecker &Checker)
void collectUmbrellaHeaderHeader(llvm::StringRef HeaderName)
Called from CoverageCheckerCallbacks to track a header included from an umbrella header.
CoverageCheckerFrontendActionFactory(CoverageChecker &Checker)
ModularizeUtilities class definition.
std::vector< llvm::StringRef > CommandLine
void findUnaccountedForHeaders()
Find headers unaccounted-for in module map.
~CoverageCheckerCallbacks() override
bool collectUmbrellaHeaderHeaders(llvm::StringRef UmbrellaHeaderName)
Collect headers rferenced from an umbrella file.
Definitions for CoverageChecker.
bool IsAngled
true if this was an include with angle brackets
static std::unique_ptr< CoverageChecker > createCoverageChecker(llvm::StringRef ModuleMapPath, std::vector< std::string > &IncludePaths, llvm::ArrayRef< std::string > CommandLine, clang::ModuleMap *ModuleMap)
Create instance of CoverageChecker.
std::error_code doChecks()
Do checks.
llvm::StringRef Directory
static cl::list< std::string > IncludePaths("I", cl::desc("Include path for coverage check."), cl::ZeroOrMore, cl::value_desc("path"))
bool collectFileSystemHeaders()
Collect file system header files.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, StringRef SearchPath, StringRef RelativePath, const Module *Imported, SrcMgr::CharacteristicKind FileType) override
CoverageCheckerConsumer(CoverageChecker &Checker, Preprocessor &PP)
Module map checker class.
static bool isHeader(llvm::StringRef FileName)
Check for header file extension.