Search code examples
clangllvm-clanglibtooling

call graph(.dot) generated by clang libtooling has no node labels


I'm a beginner of clang libtooling. I'm trying to use clang::CallGraph viewGraph to generate a .dot file of my call graph. here is the code:

clang::CallGraph mCG;

for (unsigned i = 0 ; i < DeclsSize ; ++i) {
    clang::FunctionDecl *FnDecl = (clang::FunctionDecl *) (Decls[i]);
    mCG.addToCallGraph(FnDecl);
}

mCG.viewGraph();

The interesting thing is, the generated call graph file (.dot) has no node's labels, although I can print my call graph with all node's name correctly.

Here is the generated pic: enter image description here

I'm curious about why it shows like that. Which part is wrong in my code?

Thanks in advance!


Solution

  • I fixed this problem, but I'm not sure whether it is a correct way. Instead of invoking function - "viewGraph()", I use the "llvm::WriteGraph".

    Here is the code:

    string outputPath = "./";
    outputPath.append("CallGraph");
    outputPath.append(".dot");
    
    // Write .dot
    std::error_code EC;
    raw_fd_ostream O(outputPath, EC, sys::fs::F_RW);
    
    if (EC) {
        llvm::errs() << "Error: " << EC.message() << "\n";
        return;
    }
    
    llvm::WriteGraph(O, &mCG);
    

    Meanwhile, I changed the LLVM source code file -- GraphWriter.h

    void writeNode(NodeRef Node) {
    
    std::string NodeAttributes = DTraits.getNodeAttributes(Node, G);
    
    O << "\tNode" << static_cast<const void*>(Node) << " [shape=record,";
    if (!NodeAttributes.empty()) O << NodeAttributes << ",";
    O << "label=\"{";
    
    if (!DTraits.renderGraphFromBottomUp()) {
    
      // I add here: for show the node's label value (otherwise the label will be empty)
      std::string nodeLable ;
      if(Node == G->getRoot()){
         nodeLable = "root";
      }
      else{
        const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Node->getDecl());
        nodeLable = ND->getNameAsString();
      }
    
     // O << DOT::EscapeString(DTraits.getNodeLabel(Node, G));
      O << nodeLable;
    ...
    

    Anyway, it works for my code now. Not sure whether there are some other good ways.