Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clang AST visitor, avoid traversing include files

Hello I am trying to implement an AST Clang visitor and this is my code.

class ExampleVisitor : public RecursiveASTVisitor<ExampleVisitor> {
private:
    ASTContext *astContext; // used for getting additional AST info

public:
    virtual bool VisitVarDecl(VarDecl *var) 
    {
        numVariables++;
        string varName = var->getQualifiedNameAsString();
        string varType = var->getType().getAsString();
        cout << "Found variable declaration: " << varName << " of type " << varType << "\n";
        APIs << varType << ", ";
        return true;
    }

    virtual bool VisitFunctionDecl(FunctionDecl *func)
    {
        numFunctions++;
        string funcName = func->getNameInfo().getName().getAsString();
        string funcType = func->getResultType().getAsString();
        cout << "Found function declaration: " << funcName << " of type " << funcType << "\n";
        APIs << "\n\n" << funcName <<": ";
        APIs << funcType << ", ";
        return true;
    }

    virtual bool VisitStmt(Stmt *st) 
    {
        if (CallExpr *call = dyn_cast<CallExpr>(st)) 
        {
            numFuncCalls++;
            FunctionDecl *func_decl = call->getDirectCallee();
            string funcCall = func_decl->getNameInfo().getName().getAsString();
            cout << "Found function call: " << funcCall << " with arguments ";
            APIs << funcCall << ", ";
            for(int i=0, j = call->getNumArgs(); i<j; i++)
            {
                string TypeS;
                raw_string_ostream s(TypeS);
                call->getArg(i)->printPretty(s, 0, Policy);
                cout<< s.str() << ", ";
                APIs<< s.str() << ", ";
           }
            cout << "\n";
        }
        return true;
    }
};

How can I avoid traversing the included header files, but without loosing their information. I just dont want to print any information about this files but I want clang to know about these files

Thank you

like image 308
Andreas Geo Avatar asked Jun 22 '16 20:06

Andreas Geo


1 Answers

By using AST context you can get all the nescecarry information for the code you are parsing. The function which distinguish between AST nodes being in the main file or the header files is called isInMainFile() and can be used as follows.

bool VisitVarDecl(VarDecl *var)
{
    if (astContext->getSourceManager().isInMainFile(var->getLocStart())) //checks if the node is in the main = input file.
    {
        if(var->hasLocalStorage() || var->isStaticLocal())
        {
            //var->dump(); //prints the corresponding line of the AST.
            FullSourceLoc FullLocation = astContext->getFullLoc(var->getLocStart());
            numVariables++;
            string varName = var->getQualifiedNameAsString();
            string varType = var->getType().getAsString();
            REPORT << "Variable Declaration [" << FullLocation.getSpellingLineNumber() << "," << FullLocation.getSpellingColumnNumber() << "]: " << varName << " of type " << varType << "\n";
            APIs << varType << ",";
        }
    }
    return true;
}

For more information on how to use astContext follow the official recursive ASTvisitor tutorial in clang website.

like image 187
Andreas Geo Avatar answered Sep 22 '22 02:09

Andreas Geo