[cfe-dev] clang plugin registry

akshay ratnaparkhi ackk007 at gmail.com
Fri Apr 6 02:18:21 PDT 2012


Hi ,
    I wrote my callgraph plugin code as following...

#include "clang/AST/DeclBase.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"

#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/AST.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/Support/raw_ostream.h"

// call graph structure method

namespace clang{
class CallGraphNode;

class CallGraph{

  public:


          typedef llvm::DenseMap<Decl *, CallGraphNode *> FunctionMapTy;
          FunctionMapTy FunctionMap;

          CallGraphNode *Root;

          CallGraph();
          ~CallGraph();

          llvm::SetVector<CallGraphNode *> ParentlessNodes;

          void addToCallGraph(Decl *D, bool isGlobal);
          void addToCallGraph(TranslationUnitDecl *TU);

          CallGraphNode *getNode(const Decl * ) const ;
          CallGraphNode *getOrInsertNode(Decl *);

          typedef FunctionMapTy::iterator iterator;
          typedef FunctionMapTy::const_iterator const_iterator;

          iterator begin() { return FunctionMap.begin(); }
          iterator end() { return FunctionMap.end(); }
          const_iterator begin() const { return FunctionMap.begin(); }
          const_iterator end() const { return FunctionMap.end(); }

          typedef llvm::SetVector<CallGraphNode *>::iterator Nodes_iterator;
          typedef llvm::SetVector<CallGraphNode *>::const_iterator
const_Nodes_iterator;

          Nodes_iterator parentless_begin() { return
ParentlessNodes.begin(); }
          Nodes_iterator parentless_end() { return ParentlessNodes.end(); }
          const_Nodes_iterator parentless_begin() const { return
ParentlessNodes.begin(); }
          const_Nodes_iterator parentless_end() const { return
ParentlessNodes.end(); }

          CallGraphNode *getRoot() const { return Root; }


  }; // end of class CallGraph


 class CallGraphNode{
   public:
         typedef CallGraphNode *CallRecord;

   private:
   Decl *FD;
   llvm::SmallVector<CallRecord , 5> CalledFunctions;
   public:




            CallGraphNode(Decl *D):FD(D) {}   // constructor



            typedef llvm::SmallVector<CallRecord , 5>::iterator iterator;
            typedef llvm::SmallVector<CallRecord , 5>::const_iterator
const_iterator;

            inline iterator begin() { return CalledFunctions.begin(); }
            inline iterator end() { return CalledFunctions.end(); }
            inline const_iterator begin() const { return
CalledFunctions.begin(); }
            inline const_iterator end() const { return
CalledFunctions.end(); }

            inline bool empty() const { return CalledFunctions.empty(); }
            inline unsigned size() const { return CalledFunctions.size(); }

            void addCallee(CallGraphNode *N , CallGraph *CG)
               {
                  CalledFunctions.push_back(N);
                  CG->ParentlessNodes.remove(N);
               }

           Decl *getDecl() const { return FD; }
           StringRef getName() const ;

 }; // end of CallGrsphNode class


} //end of namespace clang




using namespace clang;

static bool includeInGraph(const Decl *D)
 {
   if(const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)){

     if(!FD->isThisDeclarationADefinition() || FD->isDependentContext())
        return false;

     IdentifierInfo *II = FD->getIdentifier();

     if(II && II->getName().startswith("__inline"))
       return false;
   }

  return true;
 }


namespace{
class CGBuilder:public StmtVisitor<CGBuilder>,public ASTConsumer{

  CallGraph *G;
  const Decl *FD;
  CallGraphNode *callernode;

protected:
        virtual bool HandleTopLevelDecl(DeclGroupRef DG) {return true;}
public:

     CGBuilder() {}
     CGBuilder(CallGraph *g, const Decl *D, CallGraphNode *N
):G(g),FD(D),callernode(N) {}
  void VisitStmt(Stmt *S){ VisitChildren(S); }

  void VisitCallExpr(CallExpr *CE){
     if(FunctionDecl *calleeDecl = CE->getDirectCallee())
       {
         if(includeInGraph(calleeDecl))
           {
             CallGraphNode *calleenode = G->getOrInsertNode(calleeDecl);
             callernode->addCallee(calleenode,G);
           }
       }
   }

  void VisitChildren(Stmt *S)
   {
     for(Stmt::child_range I = S->children() ; I ; ++I)
      if(*I)
         static_cast<CGBuilder*>(this)->Visit(*I);
   }



};//end of class CGBuilder


class CGDeclVisitor:public RecursiveASTVisitor<CGDeclVisitor>{
  CallGraph *CG;
  public:
        CGDeclVisitor(CallGraph *inCG):CG(inCG) {}

        bool VisitFunctionDecl(FunctionDecl *FD)
         {
           if(includeInGraph(FD))
               CG->addToCallGraph(FD,FD->isGlobal());
           return true;
         }

};//end of CGDeclVisitor class


class CGBuilderAction : public PluginASTAction {
protected:
  ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef) {
    return new CGBuilder();
  }

};


static FrontendPluginRegistry::Add<CGBuilderAction>
X("print-cgp", "print callgraph");

}//end of namespace



CallGraph::CallGraph()
{
  Root = getOrInsertNode(0);
}


CallGraph::~CallGraph()
{
   if(!FunctionMap.empty())
     {
       for(FunctionMapTy::iterator I = FunctionMap.begin(), E =
FunctionMap.end() ; I != E ; ++I)
         delete I->second;
       FunctionMap.clear();
     }
}


CallGraphNode *CallGraph::getOrInsertNode(Decl *F)
{
  CallGraphNode *&Node = FunctionMap[F];
  if(Node)
     return Node;

  Node = new CallGraphNode(F);
  if(F!=0)
    ParentlessNodes.insert(Node);
  return Node;
}

void CallGraph::addToCallGraph( Decl *D , bool isGlobal)
{
  assert(D);
  CallGraphNode *Node = getOrInsertNode(D);

  if(isGlobal)
     Root->addCallee(Node,this);

  CGBuilder builder(this,D,Node);
  if(Stmt *Body = D->getBody())
     builder.Visit(Body);
}

void CallGraph::addToCallGraph(TranslationUnitDecl *TU)
{
    CGDeclVisitor(this).TraverseDecl(TU);
}





after compiling plugin it will give me error as following.....

In file included from
/home/akshay/llvmsrc/llvm/tools/clang/examples/CallGraph/../../include/clang/Frontend/FrontendPluginRegistry.h:14:
/home/akshay/llvmsrc/llvm/include/llvm/Support/Registry.h:195:39: error:
allocating an object of abstract class type 'CGBuilderAction'
      static T *CtorFn() { return new V(); }
                                      ^
/home/akshay/llvmsrc/llvm/include/llvm/Support/Registry.h:199:29: note: in
instantiation of member function
      'llvm::Registry<clang::PluginASTAction,
llvm::RegistryTraits<clang::PluginASTAction>
>::Add<<anonymous>::CGBuilderAction>::CtorFn'
      requested here
        : Entry(Name, Desc, CtorFn), Node(Entry) {}
                            ^
/home/akshay/llvmsrc/llvm/tools/clang/examples/CallGraph/callgraph.cpp:190:1:
note: in instantiation of member function
      'llvm::Registry<clang::PluginASTAction,
llvm::RegistryTraits<clang::PluginASTAction>
>::Add<<anonymous>::CGBuilderAction>::Add'
      requested here
X("print-cgp", "print callgraph");
^
/home/akshay/llvmsrc/llvm/tools/clang/examples/CallGraph/../../include/clang/Frontend/FrontendAction.h:228:16:
note: unimplemented pure
      virtual method 'ParseArgs' in 'CGBuilderAction'
  virtual bool ParseArgs(const CompilerInstance &CI,

can anyone tell me what is going on here?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20120406/a3e86b9f/attachment.html>


More information about the cfe-dev mailing list