Hi ,<br> I wrote my callgraph plugin code as following...<br><br>#include "clang/AST/DeclBase.h"<br>#include "llvm/ADT/DenseMap.h"<br>#include "llvm/ADT/SetVector.h"<br><br>#include "clang/AST/ASTContext.h"<br>
#include "clang/AST/Decl.h"<br>#include "clang/AST/RecursiveASTVisitor.h"<br>#include "clang/AST/StmtVisitor.h"<br><br>#include "clang/Frontend/FrontendPluginRegistry.h"<br>#include "clang/AST/ASTConsumer.h"<br>
#include "clang/AST/AST.h"<br>#include "clang/Frontend/CompilerInstance.h"<br>#include "llvm/Support/raw_ostream.h"<br><br>// call graph structure method<br><br>namespace clang{<br>class CallGraphNode;<br>
<br>class CallGraph{<br> <br> public:<br> <br><br> typedef llvm::DenseMap<Decl *, CallGraphNode *> FunctionMapTy;<br> FunctionMapTy FunctionMap;<br> <br> CallGraphNode *Root;<br>
<br> CallGraph();<br> ~CallGraph();<br> <br> llvm::SetVector<CallGraphNode *> ParentlessNodes;<br><br> void addToCallGraph(Decl *D, bool isGlobal);<br> void addToCallGraph(TranslationUnitDecl *TU);<br>
<br> CallGraphNode *getNode(const Decl * ) const ;<br> CallGraphNode *getOrInsertNode(Decl *);<br> <br> typedef FunctionMapTy::iterator iterator;<br> typedef FunctionMapTy::const_iterator const_iterator;<br>
<br> iterator begin() { return FunctionMap.begin(); }<br> iterator end() { return FunctionMap.end(); } <br> const_iterator begin() const { return FunctionMap.begin(); }<br> const_iterator end() const { return FunctionMap.end(); }<br>
<br> typedef llvm::SetVector<CallGraphNode *>::iterator Nodes_iterator;<br> typedef llvm::SetVector<CallGraphNode *>::const_iterator const_Nodes_iterator;<br><br> Nodes_iterator parentless_begin() { return ParentlessNodes.begin(); }<br>
Nodes_iterator parentless_end() { return ParentlessNodes.end(); }<br> const_Nodes_iterator parentless_begin() const { return ParentlessNodes.begin(); }<br> const_Nodes_iterator parentless_end() const { return ParentlessNodes.end(); }<br>
<br> CallGraphNode *getRoot() const { return Root; }<br> <br> <br> }; // end of class CallGraph<br><br><br> class CallGraphNode{<br> public:<br> typedef CallGraphNode *CallRecord;<br> <br> private:<br>
Decl *FD;<br> llvm::SmallVector<CallRecord , 5> CalledFunctions; <br> public:<br> <br> <br> <br> <br> CallGraphNode(Decl *D):FD(D) {} // constructor <br>
<br> <br> <br> typedef llvm::SmallVector<CallRecord , 5>::iterator iterator;<br> typedef llvm::SmallVector<CallRecord , 5>::const_iterator const_iterator;<br> <br>
inline iterator begin() { return CalledFunctions.begin(); }<br> inline iterator end() { return CalledFunctions.end(); }<br> inline const_iterator begin() const { return CalledFunctions.begin(); }<br>
inline const_iterator end() const { return CalledFunctions.end(); }<br> <br> inline bool empty() const { return CalledFunctions.empty(); }<br> inline unsigned size() const { return CalledFunctions.size(); }<br>
<br> void addCallee(CallGraphNode *N , CallGraph *CG)<br> {<br> CalledFunctions.push_back(N);<br> CG->ParentlessNodes.remove(N);<br> }<br> <br> Decl *getDecl() const { return FD; }<br>
StringRef getName() const ;<br><br> }; // end of CallGrsphNode class<br><br><br>} //end of namespace clang<br><br><br><br><br>using namespace clang;<br><br>static bool includeInGraph(const Decl *D)<br> {<br> if(const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)){<br>
<br> if(!FD->isThisDeclarationADefinition() || FD->isDependentContext())<br> return false;<br><br> IdentifierInfo *II = FD->getIdentifier();<br><br> if(II && II->getName().startswith("__inline"))<br>
return false; <br> }<br><br> return true;<br> }<br><br><br>namespace{<br>class CGBuilder:public StmtVisitor<CGBuilder>,public ASTConsumer{<br><br> CallGraph *G;<br> const Decl *FD;<br> CallGraphNode *callernode;<br>
<br>protected:<br> virtual bool HandleTopLevelDecl(DeclGroupRef DG) {return true;}<br>public:<br> <br> CGBuilder() {}<br> CGBuilder(CallGraph *g, const Decl *D, CallGraphNode *N ):G(g),FD(D),callernode(N) {}<br>
void VisitStmt(Stmt *S){ VisitChildren(S); }<br> <br> void VisitCallExpr(CallExpr *CE){<br> if(FunctionDecl *calleeDecl = CE->getDirectCallee())<br> {<br> if(includeInGraph(calleeDecl))<br> {<br>
CallGraphNode *calleenode = G->getOrInsertNode(calleeDecl);<br> callernode->addCallee(calleenode,G);<br> }<br> }<br> }<br><br> void VisitChildren(Stmt *S)<br> {<br> for(Stmt::child_range I = S->children() ; I ; ++I)<br>
if(*I)<br> static_cast<CGBuilder*>(this)->Visit(*I);<br> }<br><br> <br><br>};//end of class CGBuilder<br><br><br>class CGDeclVisitor:public RecursiveASTVisitor<CGDeclVisitor>{<br> CallGraph *CG; <br>
public:<br> CGDeclVisitor(CallGraph *inCG):CG(inCG) {}<br> <br> bool VisitFunctionDecl(FunctionDecl *FD)<br> {<br> if(includeInGraph(FD))<br> CG->addToCallGraph(FD,FD->isGlobal());<br>
return true;<br> }<br><br>};//end of CGDeclVisitor class<br><br><br>class CGBuilderAction : public PluginASTAction {<br>protected:<br> ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef) {<br>
return new CGBuilder();<br> }<br><br>};<br><br> <br>static FrontendPluginRegistry::Add<CGBuilderAction><br>X("print-cgp", "print callgraph");<br><br>}//end of namespace<br><br><br><br>CallGraph::CallGraph()<br>
{<br> Root = getOrInsertNode(0);<br>}<br><br><br>CallGraph::~CallGraph()<br>{<br> if(!FunctionMap.empty())<br> {<br> for(FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end() ; I != E ; ++I)<br>
delete I->second;<br> FunctionMap.clear();<br> }<br>}<br><br><br>CallGraphNode *CallGraph::getOrInsertNode(Decl *F)<br>{<br> CallGraphNode *&Node = FunctionMap[F];<br> if(Node)<br> return Node;<br>
<br> Node = new CallGraphNode(F);<br> if(F!=0)<br> ParentlessNodes.insert(Node);<br> return Node;<br>}<br><br>void CallGraph::addToCallGraph( Decl *D , bool isGlobal)<br>{<br> assert(D);<br> CallGraphNode *Node = getOrInsertNode(D);<br>
<br> if(isGlobal)<br> Root->addCallee(Node,this);<br><br> CGBuilder builder(this,D,Node);<br> if(Stmt *Body = D->getBody()) <br> builder.Visit(Body);<br>}<br><br>void CallGraph::addToCallGraph(TranslationUnitDecl *TU)<br>
{<br> CGDeclVisitor(this).TraverseDecl(TU);<br>}<br><br><br><br><br><br>after compiling plugin it will give me error as following.....<br><br>In file included from /home/akshay/llvmsrc/llvm/tools/clang/examples/CallGraph/../../include/clang/Frontend/FrontendPluginRegistry.h:14:<br>
/home/akshay/llvmsrc/llvm/include/llvm/Support/Registry.h:195:39: error: allocating an object of abstract class type 'CGBuilderAction'<br> static T *CtorFn() { return new V(); }<br> ^<br>
/home/akshay/llvmsrc/llvm/include/llvm/Support/Registry.h:199:29: note: in instantiation of member function<br> 'llvm::Registry<clang::PluginASTAction, llvm::RegistryTraits<clang::PluginASTAction> >::Add<<anonymous>::CGBuilderAction>::CtorFn'<br>
requested here<br> : Entry(Name, Desc, CtorFn), Node(Entry) {}<br> ^<br>/home/akshay/llvmsrc/llvm/tools/clang/examples/CallGraph/callgraph.cpp:190:1: note: in instantiation of member function<br>
'llvm::Registry<clang::PluginASTAction, llvm::RegistryTraits<clang::PluginASTAction> >::Add<<anonymous>::CGBuilderAction>::Add'<br> requested here<br>X("print-cgp", "print callgraph");<br>
^<br>/home/akshay/llvmsrc/llvm/tools/clang/examples/CallGraph/../../include/clang/Frontend/FrontendAction.h:228:16: note: unimplemented pure<br> virtual method 'ParseArgs' in 'CGBuilderAction'<br> virtual bool ParseArgs(const CompilerInstance &CI,<br>
<br>can anyone tell me what is going on here? <br><br><br><br>