diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx index 330090811423..6611606d793f 100644 --- a/compilerplugins/clang/plugin.cxx +++ b/compilerplugins/clang/plugin.cxx @@ -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 ) diff --git a/compilerplugins/clang/plugin.hxx b/compilerplugins/clang/plugin.hxx index 9c9ce7b72f55..56dee27ef913 100644 --- a/compilerplugins/clang/plugin.hxx +++ b/compilerplugins/clang/plugin.hxx @@ -19,6 +19,7 @@ #include #include #include +#include #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 2 #include @@ -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 ); }; /**