diff options
author | bloodstalker <thabogre@gmail.com> | 2020-03-30 13:20:01 +0000 |
---|---|---|
committer | bloodstalker <thabogre@gmail.com> | 2020-03-30 13:20:01 +0000 |
commit | 3888347bc2e7714541bdc63e9861cd15e1a0c124 (patch) | |
tree | f1e34b3402f04b481c50b97534888a23c7f837bc | |
parent | travis fix (diff) | |
download | cgrep-3888347bc2e7714541bdc63e9861cd15e1a0c124.tar.gz cgrep-3888347bc2e7714541bdc63e9861cd15e1a0c124.zip |
declarations no longer print out the declarations since they are already matching declarations. added a new WIP switch called trace.
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | cgrep.cpp | 241 | ||||
-rw-r--r-- | pch.hpp | 2 |
3 files changed, 168 insertions, 77 deletions
@@ -19,7 +19,7 @@ and it will match your regex against all function declarations, and will output `cgrep` is implemented using Clang's libtooling libraries. -### Features +## Features * It's basically Clang regexing it's way through your C-family source-code. You have all the context you can ever need. * Can output whether to print the declaration of a match even if the match itself is not a declaration along with the matched result. @@ -25,7 +25,11 @@ cl::opt<std::string> CO_RECURSIVE( cl::init(""), cl::cat(CGrepCat), cl::Optional); cl::opt<std::string> CO_REGEX("regex", cl::desc("The regex to match against."), cl::init(""), cl::cat(CGrepCat), - cl::Required); // done + cl::Optional); // done +cl::opt<std::string> + CO_TRACE("trace", cl::desc("The variable that's going to be traced"), + cl::init(""), cl::cat(CGrepCat), + cl::Optional); // done cl::opt<bool> CO_FUNCTION("func", cl::desc("Match functions."), cl::init(false), cl::cat(CGrepCat), cl::Optional); // done @@ -48,17 +52,20 @@ cl::opt<bool> CO_CLASS("class", cl::desc("Match class declrations."), cl::opt<bool> CO_STRUCT("struct", cl::desc("Match structures."), cl::init(false), cl::cat(CGrepCat), cl::Optional); // done -cl::opt<bool> CO_CXXFIELD("cxxfield", cl::desc("Match CXX field member declarations."), - cl::init(false), cl::cat(CGrepCat), - cl::Optional); // done +cl::opt<bool> CO_CXXFIELD("cxxfield", + cl::desc("Match CXX field member declarations."), + cl::init(false), cl::cat(CGrepCat), + cl::Optional); // done cl::opt<bool> CO_UNION("union", cl::desc("Match unions."), cl::init(false), cl::cat(CGrepCat), cl::Optional); // done cl::opt<bool> CO_MACRO("macro", cl::desc("Match macro definitions."), cl::init(false), cl::cat(CGrepCat), cl::Optional); // done -cl::opt<bool> CO_CLANGDIAG("clangdiag", cl::desc("use clang's diagnostic consumer instead of the one that cgrep provide."), - cl::init(false), cl::cat(CGrepCat), - cl::Optional); // done +cl::opt<bool> CO_CLANGDIAG("clangdiag", + cl::desc("use clang's diagnostic consumer instead " + "of the one that cgrep provide."), + cl::init(false), cl::cat(CGrepCat), + cl::Optional); // done cl::opt<bool> CO_HEADER("header", cl::desc("Match headers in header inclusions."), cl::init(false), cl::cat(CGrepCat), @@ -149,10 +156,6 @@ cl::opt<int> CO_B("B", #define CC_NORMAL (CO_NOCOLOR == true ? "" : NORMAL) #define CC_CLEAR (CO_NOCOLOR == true ? "" : CLEAR) /***********************************************************************************************/ -// forwartd declarations -static ClangTool build_cgrep_instance(int argc, const char **argv); -static int run_cgrep_instance(ClangTool cgrepToolInstance); -/***********************************************************************************************/ static std::string get_line_from_file(SourceManager &SM, const MatchFinder::MatchResult &MR, SourceRange SR) { @@ -180,25 +183,6 @@ static std::string get_line_from_file(SourceManager &SM, } /** - * @brief recursively goes through all the directories starting from path - * - * @param path - */ -#if 0 -static void dig(boost::filesystem::path dir, int argc, const char** argv) { - //just to be compatible with old gcc versions - //for (const auto &entry : boost::filesystem::directory_iterator(dir)) { - for (boost::filesystem::path::iterator entry = dir.begin(); entry != dir.end(); ++entry ) { - if (true == is_directory(*entry)) { - auto cgrepInstance = build_cgrep_instance(argc, argv); - run_cgrep_instance(cgrepInstance); - dig((*entry).path(), argc, argv); - } - } -} -#endif - -/** * @brief does some preprocessing on the regex string we get as input * @param rx_str * @return the preprocessed string @@ -259,10 +243,7 @@ void output_handler(const MatchFinder::MatchResult &MR, SourceRange SR, } } if (!CO_NODECL) { - if (isdecl) { - std::cout << CC_GREEN << "\t<---declared here" << CC_NORMAL - << "\n"; - } else { + if (!isdecl) { const NamedDecl *ND = DTN.get<NamedDecl>(); if (nullptr != ND) { SourceRange ND_SR = ND->getSourceRange(); @@ -672,34 +653,97 @@ private: }; /***********************************************************************************************/ class RecordFieldHandler : public MatchFinder::MatchCallback { - public: - explicit RecordFieldHandler(Rewriter &Rewrite) : Rewrite(Rewrite) {} - - virtual void run(const MatchFinder::MatchResult &MR) { - const FieldDecl *FD = MR.Nodes.getNodeAs<clang::FieldDecl>("recordfielddecl"); - if (FD) { - SourceRange SR = FD->getSourceRange(); - SourceLocation SL = SR.getBegin(); - CheckSLValidity(SL); - SL = Devi::SourceLocationHasMacro(SL, Rewrite, "start"); - if (Devi::IsTheMatchInSysHeader(CO_SYSHDR, MR, SL)) - return void(); - if (!Devi::IsTheMatchInMainFile(CO_MAINFILE, MR, SL)) - return void(); - std::string name = FD->getNameAsString(); - if (regex_handler(REGEX_PP(CO_REGEX), name)) { - ast_type_traits::DynTypedNode DNode = - ast_type_traits::DynTypedNode::create(*FD); - auto StartLocation = FD->getLocation(); - auto EndLocation = StartLocation.getLocWithOffset(name.size() - 1); - auto Range = SourceRange(StartLocation, EndLocation); - output_handler(MR, Range, *MR.SourceManager, true, DNode); - } +public: + explicit RecordFieldHandler(Rewriter &Rewrite) : Rewrite(Rewrite) {} + + virtual void run(const MatchFinder::MatchResult &MR) { + const FieldDecl *FD = + MR.Nodes.getNodeAs<clang::FieldDecl>("recordfielddecl"); + if (FD) { + SourceRange SR = FD->getSourceRange(); + SourceLocation SL = SR.getBegin(); + CheckSLValidity(SL); + SL = Devi::SourceLocationHasMacro(SL, Rewrite, "start"); + if (Devi::IsTheMatchInSysHeader(CO_SYSHDR, MR, SL)) + return void(); + if (!Devi::IsTheMatchInMainFile(CO_MAINFILE, MR, SL)) + return void(); + std::string name = FD->getNameAsString(); + if (regex_handler(REGEX_PP(CO_REGEX), name)) { + ast_type_traits::DynTypedNode DNode = + ast_type_traits::DynTypedNode::create(*FD); + auto StartLocation = FD->getLocation(); + auto EndLocation = StartLocation.getLocWithOffset(name.size() - 1); + auto Range = SourceRange(StartLocation, EndLocation); + output_handler(MR, Range, *MR.SourceManager, true, DNode); + } + } + } + +private: + Rewriter &Rewrite [[maybe_unused]]; +}; +/***********************************************************************************************/ +class TraceVarHandlerSub : public MatchFinder::MatchCallback { +public: + explicit TraceVarHandlerSub(Rewriter &Rewrite) : Rewrite(Rewrite) {} + + virtual void run(const MatchFinder::MatchResult &MR) { + std::cout << "called\n"; + const DeclRefExpr *DRE = + MR.Nodes.getNodeAs<clang::DeclRefExpr>("tracevardeclrefexpr"); + if (DRE) { + if (DRE->getFoundDecl() == ND) { + std::cout << "DRE:" << std::hex << DRE->getFoundDecl() << "\n"; + std::cout << "ND:" << std::hex << ND << "\n"; + std::cout << DRE->getLocation().printToString(*(MR.SourceManager)) + << "\n"; + } + } + } + + void setND(NamedDecl const * Original_Declaration) { + ND = Original_Declaration; + } + +private: + Rewriter &Rewrite [[maybe_unused]]; + NamedDecl const *ND; +}; +/***********************************************************************************************/ +class TraceVarHandler : public MatchFinder::MatchCallback { +public: + explicit TraceVarHandler(Rewriter &Rewrite) + : Rewrite(Rewrite), SubMatcher(Rewrite) {} + ~TraceVarHandler() { + std::cout << "Destroy\n"; + } + + virtual void run(const MatchFinder::MatchResult &MR) { + const VarDecl *VD = MR.Nodes.getNodeAs<clang::VarDecl>("tracevar"); + if (VD) { + SourceRange SR = VD->getSourceRange(); + SourceLocation SL = SR.getBegin(); + CheckSLValidity(SL); + if (Devi::IsTheMatchInSysHeader(CO_SYSHDR, MR, SL)) + return void(); + if (!Devi::IsTheMatchInMainFile(CO_MAINFILE, MR, SL)) + return void(); + auto NameRef = VD->getName(); + if (!NameRef.empty()) { + SubMatcher.setND(VD->getCanonicalDecl()->getUnderlyingDecl()); + Matcher.addMatcher(declRefExpr(to(varDecl(hasName(VD->getName())))) + .bind("tracevardeclrefexpr"), + &SubMatcher); + Matcher.matchAST(*(MR.Context)); } } + } private: + MatchFinder Matcher; Rewriter &Rewrite [[maybe_unused]]; + TraceVarHandlerSub SubMatcher; }; /***********************************************************************************************/ class PPInclusion : public PPCallbacks { @@ -707,8 +751,10 @@ public: explicit PPInclusion(SourceManager *SM, Rewriter *Rewrite) : SM(*SM), Rewrite(*Rewrite) {} - virtual bool FileNotFound(StringRef FileName, SmallVectorImpl<char>&RecoveryPath) { - std::cerr << CC_RED << "Header not found: " << FileName.str() << CC_NORMAL << "\n"; + virtual bool FileNotFound(StringRef FileName, + SmallVectorImpl<char> &RecoveryPath) { + std::cerr << CC_RED << "Header not found: " << FileName.str() << CC_NORMAL + << "\n"; exit(1); } @@ -732,9 +778,7 @@ public: virtual void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange Range, - const MacroArgs *Args) { - - } + const MacroArgs *Args) {} #if __clang_major__ <= 6 virtual void InclusionDirective(SourceLocation HashLoc, @@ -775,25 +819,26 @@ private: Rewriter &Rewrite [[maybe_unused]]; }; /***********************************************************************************************/ -/// @brief A Clang Diagnostic Consumer that does nothing since we don't want -/// clang to print out diag info. class CgrepDiagConsumer : public clang::DiagnosticConsumer { public: CgrepDiagConsumer() = default; virtual ~CgrepDiagConsumer() {} virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override { - if ((clang::DiagnosticsEngine::Level::Error == DiagLevel) - || (clang::DiagnosticsEngine::Level::Fatal == DiagLevel)) { + if ((clang::DiagnosticsEngine::Level::Error == DiagLevel) || + (clang::DiagnosticsEngine::Level::Fatal == DiagLevel)) { SmallVector<char, 16> OutStr; Info.FormatDiagnostic(OutStr); std::cout << "Error:"; - for (auto &iter : OutStr) std::cout << iter; + for (auto &iter : OutStr) + std::cout << iter; ArrayRef<CharSourceRange> SourceRanges = Info.getRanges(); for (auto &iter : SourceRanges) { if (Info.hasSourceManager()) { - std::cout << iter.getBegin().printToString(Info.getSourceManager()) << - ":" << iter.getEnd().printToString(Info.getSourceManager()) << "\n"; + std::cout << iter.getBegin().printToString(Info.getSourceManager()) + << ":" + << iter.getEnd().printToString(Info.getSourceManager()) + << "\n"; } } ArrayRef<FixItHint> FixItHints [[maybe_unused]] = Info.getFixItHints(); @@ -802,6 +847,21 @@ public: } }; /***********************************************************************************************/ +class TraceASTConsumer : public ASTConsumer { +public: + explicit TraceASTConsumer(Rewriter &R) : HandlerForTraceVar(R) { + Matcher.addMatcher(varDecl().bind("tracevar"), &HandlerForTraceVar); + } + + void HandleTranslationUnit(ASTContext &Context) override { + Matcher.matchAST(Context); + } + +private: + TraceVarHandler HandlerForTraceVar; + MatchFinder Matcher; +}; +/***********************************************************************************************/ class CgrepASTConsumer : public ASTConsumer { public: explicit CgrepASTConsumer(Rewriter &R) @@ -861,7 +921,9 @@ public: &HandlerForCXXCallExpr); } if (CO_CXXFIELD || CO_ALL) { - Matcher.addMatcher(fieldDecl(hasParent(cxxRecordDecl())).bind("recordfielddecl"), &HandlerForRecordField); + Matcher.addMatcher( + fieldDecl(hasParent(cxxRecordDecl())).bind("recordfielddecl"), + &HandlerForRecordField); } } @@ -885,15 +947,37 @@ private: MatchFinder Matcher; }; /***********************************************************************************************/ +class TraceFrontendAction : public ASTFrontendAction { +public: + TraceFrontendAction() {} + ~TraceFrontendAction() {} + + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef file) override { + if (!CO_CLANGDIAG) { + DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics(); + DE.setClient(BDCProto, false); + } + TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); +#if __clang_major__ <= 9 + return llvm::make_unique<TraceASTConsumer>(TheRewriter); +#endif +#if __clang_major__ >= 10 + return std::make_unique<TraceASTConsumer>(TheRewriter); +#endif + } + +private: + CgrepDiagConsumer *BDCProto = new CgrepDiagConsumer; + Rewriter TheRewriter; +}; +/***********************************************************************************************/ class CgrepFrontendAction : public ASTFrontendAction { public: CgrepFrontendAction() {} ~CgrepFrontendAction() { delete BDCProto; } - void EndSourceFileAction() override { - std::error_code EC; - // TheRewriter.getEditBuffer(TheRewriter.getSourceMgr().getMainFileID()).write(llvm::outs()); - } + void EndSourceFileAction() override { std::error_code EC; } std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override { @@ -927,7 +1011,14 @@ private: int main(int argc, const char **argv) { CommonOptionsParser op(argc, argv, CGrepCat); ClangTool Tool(op.getCompilations(), op.getSourcePathList()); - int ret = Tool.run(newFrontendActionFactory<CgrepFrontendAction>().get()); + int ret = 0; + + if ("" != CO_TRACE) { + ret = Tool.run(newFrontendActionFactory<TraceFrontendAction>().get()); + } else { + ret = Tool.run(newFrontendActionFactory<CgrepFrontendAction>().get()); + } + return ret; } /***********************************************************************************************/ @@ -1,3 +1,4 @@ +#include "./cfe-extra/cfe_extra.h" #include "clang/AST/AST.h" #include "clang/AST/ASTConsumer.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -19,4 +20,3 @@ #include <regex> #include <string> #include <vector> -#include "./cfe-extra/cfe_extra.h" |