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;
75 using namespace clang::driver;
76 using namespace clang::driver::options;
78 namespace cl = llvm::cl;
91 CharSourceRange FilenameRange,
92 Optional<FileEntryRef> File, StringRef SearchPath,
93 StringRef RelativePath,
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)
156 ArrayRef<std::string>
CommandLine, clang::ModuleMap *ModuleMap) {
158 return std::make_unique<CoverageChecker>(ModuleMapPath, IncludePaths,
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);
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(std::string(UmbrellaHeaderName));
288 ClangTool Tool(*Compilations, HeaderPath);
299 SmallString<256> PathBuf(ModuleMapDirectory);
301 if (ModuleMapDirectory.length() == 0)
302 sys::fs::current_path(PathBuf);
325 if (IncludePaths.size() == 0) {
332 for (std::vector<std::string>::const_iterator I = IncludePaths.begin(),
333 E = IncludePaths.end();
341 llvm::sort(FileSystemHeaders);
354 SmallString<256>
Directory(ModuleMapDirectory);
355 if (IncludePath.size())
356 sys::path::append(
Directory, IncludePath);
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.contains(
"\\.") || file.contains(
"/."))
394 llvm::errs() <<
"warning: No headers found in include path: \""
395 << IncludePath <<
"\"\n";
412 for (std::vector<std::string>::const_iterator I = FileSystemHeaders.begin(),
413 E = FileSystemHeaders.end();
416 if (ModuleMapHeadersSet.insert(*I).second) {
417 UnaccountedForHeaders.push_back(*I);
418 llvm::errs() <<
"warning: " << ModuleMapPath
419 <<
" does not account for file: " << *I <<
"\n";