// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // CodeLocationTools.cpp -- Additional tools for code locations. // // Author : Andrew Beach // Created On : Fri Dec 4 15:42:00 2020 // Last Modified By : Andrew Beach // Last Modified On : Mon Dec 7 15:15:00 2020 // Update Count : 0 // #include "CodeLocationTools.hpp" #include #include "AST/Pass.hpp" #include "AST/TranslationUnit.hpp" #include "Common/CodeLocation.h" namespace { template struct has_code_location : public std::is_base_of {}; // Fill every location class FillCore : public ast::WithGuards { CodeLocation const * parent; // This mimics a partially specialized method. template struct FillNode; template friend struct FillNode; template struct FillNode { static node_t const * go( FillCore * core, node_t const * node ) { node_t * newNode = nullptr; if ( node->location.isUnset() ) { // Just hoping that top level nodes are always marked. assert( core->parent ); newNode = ast::mutate( node ); newNode->location = *core->parent; } core->GuardValue( core->parent ); core->parent = &node->location; return (newNode) ? newNode : node; } }; template struct FillNode { static node_t const * go( FillCore *, node_t const * node ) { return node; } }; public: FillCore() : parent( nullptr ) {} template node_t const * previsit( node_t const * node ) { using Filler = FillNode::value>; return Filler::go( this, node ); } }; template struct __GetCL; template struct __GetCL { static CodeLocation const * get( node_t const * node ) { return &node->location; } }; template struct __GetCL { static CodeLocation const * get( node_t const * ) { return nullptr; } }; template CodeLocation const * get_code_location( node_t const * node ) { return __GetCL< node_t, has_code_location< node_t >::value >::get( node ); } // Collect pointers to all the nodes with unset code locations. class CollectCore { std::list< ast::ptr< ast::Node > > & unset; public: CollectCore( std::list< ast::ptr< ast::Node > > & unset ) : unset( unset ) {} template void previsit( node_t const * node ) { CodeLocation const * location = get_code_location( node ); if ( location && location->isUnset() ) { unset.push_back( node ); } } }; } // namespace void checkAllCodeLocations( ast::TranslationUnit const & unit ) { std::list< ast::ptr< ast::Node > > unsetNodes; { ast::Pass collector( unsetNodes ); for ( auto node : unit.decls ) { node->accept( collector ); } } if ( unsetNodes.empty() ) { return; } std::cerr << "Total nodes without a set code location: " << unsetNodes.size() << std::endl; assert( unsetNodes.empty() ); } void forceFillCodeLocations( ast::TranslationUnit & unit ) { ast::Pass::run( unit ); }