Handling multiple translation units

Dear all,
I need to perform code transformations based on inter-procedural analysis done on multiple translation units.

In order to do that I need to keep the AST generated for each translation unit in memory, do my analysis and then restart rewriting part of the AST I need to modify. Conceptually is not difficult my I am experiencing a weird behavior of Clang and maybe you can help me.

basically that’s what I am doing:

vector<ASTContext*> ctxs;
for each input file{
Preprocessor PP(…);
InitializePreprocessor(PP);
ctxs.push_back( new ASTContext(…, false, 0) );
ParseAST(PP, *ctxs.back(),…);
}
// Now do ANALYSIS (e.g. building a clang::CallGraph )
for each context in ctxs{
DeclContext DC=ctxs[i];
for each decl{
if decl is a func{
FuncDecl
FD = ();
cout << FD->getNameAsString() << endl; <— ERROR
}
}
}

As you can see from the code, every time I try to access the information of the ASTContext it looks like everything is gone. why?
I have to say that every time I parse a new translation unit I reinitialize the Preprocessor and I use different SourceManagers.

I also saw the possibility to use PHC files but I as I already told you I need to modify portion of the code and I am afraid PHC will not be suitable for me.

regards, Simone

Dear all,
I need to perform code transformations based on inter-procedural analysis done on multiple translation units.

In order to do that I need to keep the AST generated for each translation unit in memory, do my analysis and then restart rewriting part of the AST I need to modify. Conceptually is not difficult my I am experiencing a weird behavior of Clang and maybe you can help me.

basically that’s what I am doing:

vector<ASTContext*> ctxs;
for each input file{
Preprocessor PP(…);
InitializePreprocessor(PP);
ctxs.push_back( new ASTContext(…, false, 0) );
ParseAST(PP, *ctxs.back(),…);
}

You will need to make sure that the SourceManager is also retained, since the ASTContext stores a reference to its SourceManager. The same is true for TargetInfo, IdentifierTable, SelectorTable, etc.

// Now do ANALYSIS (e.g. building a clang::CallGraph )
for each context in ctxs{
DeclContext DC=ctxs[i];
for each decl{
if decl is a func{
FuncDecl
FD = ();
cout << FD->getNameAsString() << endl; <— ERROR
}
}
}

As you can see from the code, every time I try to access the information of the ASTContext it looks like everything is gone. why?

Well, getNameAsString() is going to try to look at an IdentifierInfo that may have been deallocated when the IdentifierTable is destroyed. Your best bet would be to keep the whole Preprocessor alive for each ASTContext.

  • Doug

Douglas Gregor wrote:

Dear all,
I need to perform code transformations based on inter-procedural analysis done on multiple translation units.

In order to do that I need to keep the AST generated for each translation unit in memory, do my analysis and then restart rewriting part of the AST I need to modify. Conceptually is not difficult my I am experiencing a weird behavior of Clang and maybe you can help me.

basically that's what I am doing:

vector<ASTContext*> ctxs;
for each input file{
    Preprocessor PP(...);
    InitializePreprocessor(PP);
    ctxs.push_back( new ASTContext(...., false, 0) );
    ParseAST(PP, *ctxs.back(),...);
}

You will need to make sure that the SourceManager is also retained, since the ASTContext stores a reference to its SourceManager. The same is true for TargetInfo, IdentifierTable, SelectorTable, etc.

// Now do ANALYSIS (e.g. building a clang::CallGraph )
for each context in ctxs{
    DeclContext *DC=ctxs[i];
    for each decl{
        if decl is a func{
            FuncDecl* FD = ();
            cout << FD->getNameAsString() << endl; <--- ERROR
        }
    }
}
   As you can see from the code, every time I try to access the information of the ASTContext it looks like everything is gone. why?

Well, getNameAsString() is going to try to look at an IdentifierInfo that may have been deallocated when the IdentifierTable is destroyed. Your best bet would be to keep the whole Preprocessor alive for each ASTContext.

Thanks Doug,
it works as expected now... no more strange error messages because of corrupted memory!
cheers bye