Kaydet (Commit) ade47d3d authored tarafından Luboš Luňák's avatar Luboš Luňák

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
üst d0db3134
......@@ -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 );
};
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment