make it easy to get a parent of an AST node
Clang API doesn't provide this, but it's occasionally needed, and so far the way has been inspecting the highest possible node in AST and walking down and remembering, which is complicated, error-prone and annoying. Change-Id: Id5b72cb5ebfc069e90efe6d673c0ef18ebcdab61
This commit is contained in:
@@ -67,6 +67,71 @@ void Plugin::registerPlugin( Plugin* (*create)( CompilerInstance&, Rewriter& ),
|
||||
PluginHandler::registerPlugin( create, optionName, isRewriter );
|
||||
}
|
||||
|
||||
unordered_map< const Stmt*, const Stmt* > Plugin::parents;
|
||||
|
||||
const Stmt* Plugin::parentStmt( const Stmt* stmt )
|
||||
{
|
||||
if( parents.empty())
|
||||
buildParents( compiler );
|
||||
assert( parents.count( stmt ) == 1 );
|
||||
return parents[ stmt ];
|
||||
}
|
||||
|
||||
Stmt* Plugin::parentStmt( Stmt* stmt )
|
||||
{
|
||||
if( parents.empty())
|
||||
buildParents( compiler );
|
||||
assert( parents.count( stmt ) == 1 );
|
||||
return const_cast< Stmt* >( parents[ stmt ] );
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class ParentBuilder
|
||||
: public RecursiveASTVisitor< ParentBuilder >
|
||||
{
|
||||
public:
|
||||
bool VisitFunctionDecl( const FunctionDecl* function );
|
||||
void walk( const Stmt* stmt );
|
||||
unordered_map< const Stmt*, const Stmt* >* parents;
|
||||
};
|
||||
|
||||
bool ParentBuilder::VisitFunctionDecl( const FunctionDecl* function )
|
||||
{
|
||||
// if( ignoreLocation( declaration ))
|
||||
// return true; ???
|
||||
if( !function->doesThisDeclarationHaveABody())
|
||||
return true;
|
||||
const Stmt* body = function->getBody();
|
||||
(*parents)[ body ] = NULL; // no parent
|
||||
walk( body );
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParentBuilder::walk( const Stmt* stmt )
|
||||
{
|
||||
for( ConstStmtIterator it = stmt->child_begin();
|
||||
it != stmt->child_end();
|
||||
++it )
|
||||
{
|
||||
if( *it != NULL )
|
||||
{
|
||||
(*parents)[ *it ] = stmt;
|
||||
walk( *it );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Plugin::buildParents( CompilerInstance& compiler )
|
||||
{
|
||||
assert( parents.empty());
|
||||
ParentBuilder builder;
|
||||
builder.parents = &parents;
|
||||
builder.TraverseDecl( compiler.getASTContext().getTranslationUnitDecl());
|
||||
}
|
||||
|
||||
/////
|
||||
|
||||
RewritePlugin::RewritePlugin( CompilerInstance& compiler, Rewriter& rewriter )
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include <clang/Basic/SourceManager.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
#if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 2
|
||||
#include <clang/Rewrite/Rewriter.h>
|
||||
@@ -54,10 +55,18 @@ class Plugin
|
||||
bool ignoreLocation( const Decl* decl );
|
||||
bool ignoreLocation( const Stmt* stmt );
|
||||
CompilerInstance& compiler;
|
||||
/**
|
||||
Returns the parent of the given AST node. Clang's internal AST representation doesn't provide this information,
|
||||
it can only provide children, but getting the parent is often useful for inspecting a part of the AST.
|
||||
*/
|
||||
const Stmt* parentStmt( const Stmt* stmt );
|
||||
Stmt* parentStmt( Stmt* stmt );
|
||||
private:
|
||||
static void registerPlugin( Plugin* (*create)( CompilerInstance&, Rewriter& ), const char* optionName, bool isRewriter );
|
||||
template< typename T > static Plugin* createHelper( CompilerInstance& compiler, Rewriter& rewriter );
|
||||
enum { isRewriter = false };
|
||||
static unordered_map< const Stmt*, const Stmt* > parents;
|
||||
static void buildParents( CompilerInstance& compiler );
|
||||
};
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user