diff --git a/src/CTUApexAction.cpp b/src/CTUApexAction.cpp index 8c4b9261065c634de84f92950dd1622be117ffe4..5acd247aa6866186ee2c3dc73f8c852da3ce86c8 100644 --- a/src/CTUApexAction.cpp +++ b/src/CTUApexAction.cpp @@ -7,7 +7,8 @@ std::unique_ptr<clang::ASTConsumer> CTUApexAction::CreateASTConsumer(clang::CompilerInstance &Compiler, llvm::StringRef InFile) { - std::unique_ptr<PreprocessorExtract> includeFinder = std::make_unique<PreprocessorExtract>(Compiler.getSourceManager(), includes, macros, pragmas); - Compiler.getPreprocessor().addPPCallbacks(std::move(includeFinder)); + SPDLOG_DEBUG("Registering PP callback"); + Compiler.getPreprocessor().addPPCallbacks(std::make_unique<PreprocessorExtract>(Compiler.getSourceManager(), includes, macros, pragmas)); + SPDLOG_DEBUG("Registered PP callback"); return std::make_unique<CTUApexConsumer>(call_graph,includes,macros,pragmas); } \ No newline at end of file diff --git a/src/CTUApexConsumer.cpp b/src/CTUApexConsumer.cpp index 8da27a9630632d787c19df31c6bce02737f736da..cc852da4c8c6f84a51ee10204623c5c905451097 100644 --- a/src/CTUApexConsumer.cpp +++ b/src/CTUApexConsumer.cpp @@ -12,10 +12,15 @@ void CTUApexConsumer::outlineFunctions() { for (const auto &node: call_graph->getNodes()) { if (auto md = node.second->checkAndGet<ExtractionMetadata>(); md.first && md.second->get_decl_node()) { ExtractionBlock eb; - clang::SourceRange sourceRange = md.second->get_decl_node()->getSourceRange(); - eb.begin = sourceRange.getBegin(); - eb.end = sourceRange.getEnd(); if(md.second->isMarkedToExtract()){ + clang::SourceRange sourceRange; + if(md.second->get_decl_node()->isTemplateInstantiation()){ + sourceRange =md.second->get_decl_node()->getPrimaryTemplate()->getSourceRange(); + }else{ + sourceRange= md.second->get_decl_node()->getSourceRange(); + } + eb.begin = sourceRange.getBegin(); + eb.end = sourceRange.getEnd(); //std::cout<<"Need to extract: "<<md.second->get_decl_node()->getNameAsString()<<"\n"; eb.contents = clang::Lexer::getSourceText(clang::CharSourceRange::getTokenRange(sourceRange), md.second->get_decl_node()->getASTContext().getSourceManager(), @@ -61,6 +66,8 @@ void CTUApexConsumer::outlineGlobals() { ExtractionBlock CTUApexConsumer::getNextExtractionBlock() { //find the earliest block by starting source location + //we need to do a potentially expensive copy of the full struct + //as we will erase parts of the vectors later, potentially invalidating pointers in the process ExtractionBlock min; if (!includes.empty()) { SPDLOG_TRACE("Setting include as assumed min"); @@ -79,7 +86,6 @@ ExtractionBlock CTUApexConsumer::getNextExtractionBlock() { min = pragmas.front(); } - while (!funcs.empty() && min.begin > funcs.front().begin) { SPDLOG_TRACE("Overwriting with funcs as min"); min = funcs.front(); @@ -123,6 +129,7 @@ ExtractionBlock CTUApexConsumer::getNextExtractionBlock() { return min; } + void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) { const auto &translation_unit = Context.getTranslationUnitDecl(); @@ -143,10 +150,13 @@ void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) { std::ofstream outFile; outFile.open(filename); assert(outFile.is_open()); + while (!(includes.empty() && funcs.empty() && globals.empty() && macros.empty() && pragmas.empty())) { outFile << getNextExtractionBlock().contents << "\n"; } + + SPDLOG_INFO("Generate wrapper calls"); SPDLOG_CRITICAL("WRAPPER CALLS CAN NOT YET BE IMPLEMENTED"); diff --git a/src/CTUApexVisitor.cpp b/src/CTUApexVisitor.cpp index 761560c8a59d845e99476b3e003f6c318ddea69e..aaa05b44453acbe690d9dd577f275075ecdf6e61 100644 --- a/src/CTUApexVisitor.cpp +++ b/src/CTUApexVisitor.cpp @@ -30,7 +30,6 @@ bool FunctionFinderVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDec if (!D->getASTContext().getSourceManager().isInMainFile(D->getSourceRange().getBegin())) { return true; } - SPDLOG_DEBUG("FunctionTemplateDecl {} is visited", D->getNameAsString()); for (const auto &s: D->specializations()) { for (const auto &name: getMangledName(s)) { @@ -66,8 +65,6 @@ bool FunctionFinderVisitor::VisitFunctionDecl(clang::FunctionDecl *functionDecl) return true; } - SPDLOG_DEBUG("Function {} is visited", functionDecl->getNameAsString()); - const auto &possibleNames = getMangledName(functionDecl); //std::cout<<functionDecl->getNameAsString()<<col2str(possibleNames," All possible manglings are:(",",",")")<<"\n"; diff --git a/src/PreprocessorExtract.cpp b/src/PreprocessorExtract.cpp index 5b5dd4f3bed1654a27cfa11e4043a776f3230ebc..620d1d809143c09e0df71ae38a76962215f96ebf 100644 --- a/src/PreprocessorExtract.cpp +++ b/src/PreprocessorExtract.cpp @@ -12,6 +12,7 @@ void PreprocessorExtract::If(clang::SourceLocation Loc, clang::SourceRange Condi assert(Loc.isValid()); macroNestingStack.emplace(Loc, Loc, ""); } + void PreprocessorExtract::Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, const clang::MacroDefinition &MD) { if (!sourceManager.isInMainFile(Loc)) { @@ -20,6 +21,7 @@ void PreprocessorExtract::Ifdef(clang::SourceLocation Loc, const clang::Token &M assert(Loc.isValid()); macroNestingStack.emplace(Loc, Loc, ""); } + void PreprocessorExtract::Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, const clang::MacroDefinition &MD) { Ifdef(Loc, MacroNameTok, MD); }; @@ -30,15 +32,15 @@ void PreprocessorExtract::Endif(clang::SourceLocation Loc, clang::SourceLocation assert(macroNestingStack.top().begin.isValid()); assert(macroNestingStack.top().end.isValid()); assert(IfLoc.isValid()); - assert("If these are not equal, we overwrote the last found macro end location allready" && + assert("If these are not equal, we overwrote the last found macro end location already" && macroNestingStack.top().begin == macroNestingStack.top().end); assert("The last found macros start should be the if loc we found" && macroNestingStack.top().begin == IfLoc); ExtractionBlock macro = macroNestingStack.top(); macroNestingStack.pop(); macro.end = Loc; - clang::SourceRange sourceRange(macro.begin,macro.end); - clang::CharSourceRange charSourceRange(sourceRange,true); - macro.contents = "#"+clang::Lexer::getSourceText(charSourceRange,sourceManager,clang::LangOptions()).str(); + clang::SourceRange sourceRange(macro.begin, macro.end); + clang::CharSourceRange charSourceRange(sourceRange, true); + macro.contents = "#" + clang::Lexer::getSourceText(charSourceRange, sourceManager, clang::LangOptions()).str(); macros.push_back(macro); } @@ -47,13 +49,20 @@ inline void PreprocessorExtract::PragmaDirective(clang::SourceLocation Loc, if (!sourceManager.isInMainFile(Loc)) { return; } - clang::SourceRange sourceRange(Loc,Loc); - clang::CharSourceRange charSourceRange(sourceRange,true); + //We only get the start of the pragma + clang::CharSourceRange charSourceRange({Loc, Loc.getLocWithOffset(0)}, true); + + //We move forward until we encounter a newline, which finishes the pragma, + // or enounter a \ followed by a newline, which means the pragma goes on in the next line + int i=0; + while(!clang::Lexer::getSourceText({{Loc, Loc.getLocWithOffset(i)}, true}, sourceManager, clang::LangOptions()).endswith("\n") || + clang::Lexer::getSourceText({{Loc, Loc.getLocWithOffset(i)}, true}, sourceManager, clang::LangOptions()).endswith("\\\n") ) { + i++; + } ExtractionBlock res; - res.begin=Loc; - res.end=charSourceRange.getEnd(); - res.contents=clang::Lexer::getSourceText(charSourceRange,sourceManager,clang::LangOptions()); - std::cout<<res.contents; + res.begin = Loc; + res.end = charSourceRange.getEnd(); + res.contents = clang::Lexer::getSourceText({{Loc, Loc.getLocWithOffset(i)}, true}, sourceManager, clang::LangOptions()); pragmas.push_back(res); } @@ -66,6 +75,6 @@ void PreprocessorExtract::InclusionDirective(clang::SourceLocation HashLoc, cons clang::SrcMgr::CharacteristicKind FileType) { //Note: we currently exclude headers only by name, we could also compare them according to their sourcerange if (sourceManager.isInMainFile(HashLoc)) { - includes.emplace_back(HashLoc, FilenameRange.getEnd(), "#include \""+FileName.str()+"\""); + includes.emplace_back(HashLoc, FilenameRange.getEnd(), "#include \"" + FileName.str() + "\""); } } diff --git a/src/main.cpp b/src/main.cpp index 35f25c794aae69d2fc2835f4df849fe967449dc9..8f6910bfda17111452b412791e0551912bc5efe3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -131,12 +131,32 @@ std::vector<std::string> clangResourceDirBasedAdjuster(const CommandLineArgument std::vector<std::string> ret; ret.assign(cla.begin(), cla.end()); trim(txt); + //we do need to strip the newline char at the end txt.pop_back(); - ret.push_back("-I" + txt + "/include"); + //the compiler jobs last entries are the file, the denotion for positional arguments and the syntax only flag + //additional search paths need to be inserted before these 3 + auto t=std::prev(ret.end(),3); + ret.insert(t,{"-I" + txt + "/include"}); + std::cout<<"\n"; return ret; } - +void printMarkedFunctions(const metacg::Callgraph &cg) { + std::cout << "Extracting:\n"; + for (const auto &[_, node]: cg.getNodes()) { + if (node->has<ExtractionMetadata>()) { + size_t size=500; + char* a = static_cast<char *>(malloc(size * sizeof(char))); + int status; + if(llvm::itaniumDemangle(node->getFunctionName().c_str(),a,&size,&status);status==llvm::demangle_success){ + if(llvm::StringRef b =a;!b.startswith("std::")){ + std::cout << "Node: " << demangle(node->getFunctionName()) << "\n"; + } + } + free(a); + } + } +} int main(int argc, const char **argv) { @@ -211,6 +231,7 @@ int main(int argc, const char **argv) { } markFunctionsAlongCallpaths(cg); - tool.run(argumentParsingFrontendActionFactory<CTUApexAction>(mcgManager.getCallgraph()).get()); + //printMarkedFunctions(cg); + tool.run(argumentParsingFrontendActionFactory<CTUApexAction>(mcgManager.getCallgraph()).get()) ; return 0; }