57int main(
int argc,
const char** argv)
59 spdlog::cfg::load_env_levels();
61 auto ExpectedParser = clang::tooling::CommonOptionsParser::create(argc, argv,
InstantiatorOptions, llvm::cl::OneOrMore);
64 llvm::errs() << ExpectedParser.takeError();
67 clang::tooling::CommonOptionsParser& OptionsParser = ExpectedParser.get();
71 auto excludedNameMatcher = clang::ast_matchers::matchesName(
"^::" +
excludePatterns[0] +
"::.*$");
73 excludedNameMatcher = clang::ast_matchers::anyOf(excludedNameMatcher, clang::ast_matchers::matchesName(
"^::" + *it +
"::.*$"));
75 auto includedNameMatcher = clang::ast_matchers::matchesName(
"^::" +
includePatterns[0] +
"::.*$");
77 includedNameMatcher = clang::ast_matchers::anyOf(includedNameMatcher, clang::ast_matchers::matchesName(
"^::" + *it +
"::.*$"));
80 clang::ast_matchers::DeclarationMatcher TemplateInstantiationMatcher =
TemplInstWithoutDef(excludedNameMatcher, includedNameMatcher);
82 clang::ast_matchers::DeclarationMatcher FunctionDefMatcher =
FuncWithDef(excludedNameMatcher, includedNameMatcher);
84 std::error_code tmp_create_error;
85 auto tmpdir = std::filesystem::temp_directory_path(tmp_create_error);
86 if(tmp_create_error) {
87 std::cerr <<
"Error (" << tmp_create_error.value() <<
") while getting temporary directory:\n" << tmp_create_error.message() << std::endl;
91 std::vector<std::filesystem::path> main_and_injection_files;
92 for(
const auto& file : OptionsParser.getCompilations().getAllFiles()) { main_and_injection_files.push_back(std::filesystem::path(file)); }
94 spdlog::info(
"Source files from CompilationDatabase:\n{}", main_and_injection_files);
95 llvm::ArrayRef<std::filesystem::path> sources(main_and_injection_files.data(), main_and_injection_files.size());
99 for(std::size_t i = 0; i < sources.size(); i++) {
101 bool HAS_INJECTED_INSTANTIATION =
true;
102 while(HAS_INJECTED_INSTANTIATION) {
105 auto gen_file = sources[i];
106 gen_file.replace_extension(
"gen.cpp");
107 std::ofstream f(gen_file, std::ios::out | std::ios::trunc);
109 HAS_INJECTED_INSTANTIATION =
false;
111 std::unique_ptr<clang::ASTUnit> AST;
112 parseOrLoadAST(AST, OptionsParser.getCompilations(), sources[i], tmpdir);
113 clang::Rewriter rewriter(AST->getSourceManager(), AST->getLangOpts());
116 clang::ast_matchers::MatchFinder Inst_Finder;
117 Inst_Finder.addMatcher(
TemplInst(excludedNameMatcher, includedNameMatcher), &Deleter);
118 Inst_Finder.matchAST(AST->getASTContext());
119 rewriter.overwriteChangedFiles();
120 HAS_INJECTED_INSTANTIATION = rewriter.buffer_begin() != rewriter.buffer_end();
131 std::vector<Injection> toDoList;
133 clang::ast_matchers::MatchFinder Finder;
134 Finder.addMatcher( TemplateInstantiationMatcher, &Getter);
137 std::unordered_set<std::string> workList;
138 workList.insert(OptionsParser.getSourcePathList()[0]);
140 while(workList.size() > 0) {
141 auto copyOf_workList = workList;
142 for(
const auto& item : copyOf_workList) {
143 spdlog::info(
"Processing file {}", item);
144 workList.erase(item);
145 std::unique_ptr<clang::ASTUnit> source_AST;
146 parseOrLoadAST(source_AST, OptionsParser.getCompilations(), item, tmpdir);
147 spdlog::debug(
"Got AST for file {}", item);
148 Finder.matchAST(source_AST->getASTContext());
149 spdlog::info(
"Found {} todos for file {}", toDoList.size(), item);
150 for(
const auto& toDo : toDoList) { spdlog::debug(
"\t{}", toDo); }
151 ProgressBar inner_bar(main_and_injection_files.size());
153 for(
const auto& file_for_search : main_and_injection_files) {
154 if(toDoList.size() == 0) {
159 std::unique_ptr<clang::ASTUnit> target_AST;
160 parseOrLoadAST(target_AST, OptionsParser.getCompilations(), file_for_search, tmpdir);
161 spdlog::info(
"Search in AST of file {}", file_for_search);
162 clang::Rewriter rewriter(target_AST->getSourceManager(), target_AST->getLangOpts());
163 clang::ast_matchers::MatchFinder FuncFinder;
168 FuncFinder.addMatcher( FunctionDefMatcher, &instantiator);
169 FuncFinder.matchAST(target_AST->getASTContext());
170 spdlog::debug(
"Called matchAST()");
171 rewriter.overwriteChangedFiles();
172 spdlog::debug(
"Called rewriter");
173 bool HAS_INJECTED_INTANTIATION = rewriter.buffer_begin() != rewriter.buffer_end();
174 if(HAS_INJECTED_INTANTIATION) {
175 spdlog::info(
"HAS_INJECTED={}", fmt::format(fg(fmt::color::green),
"{}", HAS_INJECTED_INTANTIATION));
176 workList.insert(file_for_search);
178 spdlog::info(
"HAS_INJECTED={}", fmt::format(fg(fmt::color::red),
"{}", HAS_INJECTED_INTANTIATION));
184 spdlog::critical(
"#toDos that are left: {}", toDoList.size());
185 if(toDoList.size() > 0) { spdlog::critical(
"toDos left:"); }
186 std::size_t count = 0ul;
187 for(
const auto& toDo : toDoList) { spdlog::critical(
"{}: {}", count++, toDo); }