Search code examples
c++clangllvmabstract-syntax-tree

clang ASTContext.getParents always returns an empty list


I am writing a tool for clang 4.0 using LibTooling based on the example Clang ASTFrontendActions sample. Given a current statement stmt, I want to get the immediate parent of it in the AST. So I try the below code to dump all parents of stmt (for testing purpose) :

bool VisitStmt(Stmt *s) {
    cout <<"Trying to get parents \n";
    const Stmt  currentStmt = *s;
    const auto& parents  = Context->getParents(currentStmt);
    auto it = Context->getParents(currentStmt).begin();
    if(it == Context->getParents(currentStmt).end())
        cout<< "parents not found\n";
    cout<<"parents size "<< parents.size() <<": \n";
    if (!parents.empty()){
        for (int i = 0; i< parents.size(); i++ ){
            cout<<"parent at "<< i <<": \n";
            const Stmt* parentStmt =  parents[i].get<Stmt>();
            parentStmt->dump();
        }

    }
}

Context is ASTContext and worked fine when I use other functions of it such as : Context->getSourceManager()
For all the statements visited, the result is always (regardless what I put in the input):

Trying to get parents 
parents not found
parents size 0: 

Do I miss anything (initialization, setup) to use getParents?


Solution

  • The problem comes from the following line:

    const Stmt  currentStmt = *s;
    

    What this does is make a copy of the statement. Context->getParents() works by looking for nodes that have the passed argument as a child. But since currentStmt only lives on your stack, and not within the context, it fails to find any such node.

    By making currentStmt a reference to the node pointed by s:

    const Stmt& currentStmt = *s;
    

    Then you would be passing to the context the actual node instance that it has within itself, and clang will manage to find the parents successfully.