49int main(
int argc,
const char** argv)
51 spdlog::cfg::load_env_levels();
53 auto ExpectedParser = clang::tooling::CommonOptionsParser::create(argc, argv,
InstantiatorOptions, llvm::cl::OneOrMore);
56 llvm::errs() << ExpectedParser.takeError();
59 clang::tooling::CommonOptionsParser& OptionsParser = ExpectedParser.get();
62 clang::ast_matchers::internal::Matcher<clang::NamedDecl> nameMatcher = clang::ast_matchers::matchesName(
IgnorePatterns[0] +
"::");
64 nameMatcher = clang::ast_matchers::anyOf(nameMatcher, clang::ast_matchers::matchesName(*it +
"::"));
67 clang::ast_matchers::DeclarationMatcher TemplateInstantiationMatcher =
TemplInstWithoutDef(nameMatcher);
69 clang::ast_matchers::DeclarationMatcher FunctionDefMatcher =
FuncWithDef(nameMatcher);
71 std::error_code tmp_create_error;
72 auto tmpdir = std::filesystem::temp_directory_path(tmp_create_error);
73 if(tmp_create_error) {
74 std::cerr <<
"Error (" << tmp_create_error.value() <<
") while getting temporary directory:\n" << tmp_create_error.message() << std::endl;
78 std::vector<std::filesystem::path> main_and_injection_files;
79 for(
const auto& file : OptionsParser.getCompilations().getAllFiles()) { main_and_injection_files.push_back(std::filesystem::path(file)); }
81 spdlog::info(
"Source files from CompilationDatabase:\n{}", main_and_injection_files);
82 llvm::ArrayRef<std::filesystem::path> sources(main_and_injection_files.data(), main_and_injection_files.size());
86 for(std::size_t i = 0; i < sources.size(); i++) {
88 bool HAS_INJECTED_INSTANTIATION =
true;
89 while(HAS_INJECTED_INSTANTIATION) {
92 auto gen_file = sources[i];
93 gen_file.replace_extension(
"gen.cpp");
94 std::ofstream f(gen_file, std::ios::out | std::ios::trunc);
96 HAS_INJECTED_INSTANTIATION =
false;
98 std::unique_ptr<clang::ASTUnit> AST;
99 parseOrLoadAST(AST, OptionsParser.getCompilations(), sources[i], tmpdir);
100 clang::Rewriter rewriter(AST->getSourceManager(), AST->getLangOpts());
103 clang::ast_matchers::MatchFinder Inst_Finder;
104 Inst_Finder.addMatcher(
TemplInst(nameMatcher), &Deleter);
105 Inst_Finder.matchAST(AST->getASTContext());
106 rewriter.overwriteChangedFiles();
107 HAS_INJECTED_INSTANTIATION = rewriter.buffer_begin() != rewriter.buffer_end();
118 std::vector<Injection> toDoList;
120 clang::ast_matchers::MatchFinder Finder;
121 Finder.addMatcher( TemplateInstantiationMatcher, &Getter);
124 std::unordered_set<std::string> workList;
125 workList.insert(OptionsParser.getSourcePathList()[0]);
127 while(workList.size() > 0) {
128 auto copyOf_workList = workList;
129 for(
const auto& item : copyOf_workList) {
130 spdlog::info(
"Processing file {}", item);
131 workList.erase(item);
132 std::unique_ptr<clang::ASTUnit> source_AST;
133 parseOrLoadAST(source_AST, OptionsParser.getCompilations(), item, tmpdir);
134 spdlog::debug(
"Got AST for file {}", item);
135 Finder.matchAST(source_AST->getASTContext());
136 spdlog::info(
"Found {} todos for file {}", toDoList.size(), item);
137 for(
const auto& toDo : toDoList) { spdlog::debug(
"\t{}", toDo); }
138 ProgressBar inner_bar(main_and_injection_files.size());
140 for(
const auto& file_for_search : main_and_injection_files) {
141 if(toDoList.size() == 0) {
146 std::unique_ptr<clang::ASTUnit> target_AST;
147 parseOrLoadAST(target_AST, OptionsParser.getCompilations(), file_for_search, tmpdir);
148 spdlog::info(
"Search in AST of file {}", file_for_search);
149 clang::Rewriter rewriter(target_AST->getSourceManager(), target_AST->getLangOpts());
150 clang::ast_matchers::MatchFinder FuncFinder;
155 FuncFinder.addMatcher( FunctionDefMatcher, &instantiator);
156 FuncFinder.matchAST(target_AST->getASTContext());
157 spdlog::debug(
"Called matchAST()");
158 rewriter.overwriteChangedFiles();
159 spdlog::debug(
"Called rewriter");
160 bool HAS_INJECTED_INTANTIATION = rewriter.buffer_begin() != rewriter.buffer_end();
161 spdlog::info(
"HAS_INJECTED={}", HAS_INJECTED_INTANTIATION);
162 if(HAS_INJECTED_INTANTIATION) { workList.insert(file_for_search); }
167 spdlog::critical(
"#toDos that are left: {}", toDoList.size());
168 if(toDoList.size() > 0) { spdlog::critical(
"toDos left:"); }
169 std::size_t count = 0ul;
170 for(
const auto& toDo : toDoList) { spdlog::critical(
"{}: {}", count++, toDo); }