// // 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 {}; template struct __GetCL; template struct __GetCL { static inline CodeLocation const * get( node_t const * node ) { return &node->location; } static inline CodeLocation * get( node_t * node ) { return &node->location; } }; template struct __GetCL { static inline CodeLocation * 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 ); } template CodeLocation * get_code_location( node_t * node ) { return __GetCL< node_t, has_code_location< node_t >::value >::get( node ); } // Fill every location with a nearby (parent) location. class FillCore : public ast::WithGuards { CodeLocation const * parent; public: FillCore() : parent( nullptr ) {} template node_t const * previsit( node_t const * node ) { GuardValue( parent ); CodeLocation const * location = get_code_location( node ); if ( location && location->isUnset() ) { assert( parent ); node_t * newNode = ast::mutate( node ); CodeLocation * newLocation = get_code_location( newNode ); assert( newLocation ); *newLocation = *parent; parent = newLocation; return newNode; } else if ( location ) { parent = location; } return 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 ); }