#pragma once // IWYU pragma: private, include "Common/PassVisitor.h" #include #include #include #include "Fwd.hpp" #include "Node.hpp" // Private prelude header, needed for some of the magic tricks this class pulls off #include "Pass.proto.hpp" namespace ast { //------------------------------------------------------------------------------------------------- // Templated visitor type // To use declare a Pass< YOUR VISITOR TYPE > // The visitor type should specify the previsit/postvisit for types that are desired. // Note: previsit/postvisit must be **public** members // // Several additional features are available through inheritance // | WithTypeSubstitution - provides polymorphic TypeSubstitution * env for the current expression // | WithStmtsToAdd - provides the ability to insert statements before or after the current // statement by adding new statements into stmtsToAddBefore or // stmtsToAddAfter respectively. // | WithShortCircuiting - provides the ability to skip visiting child nodes; set visit_children // to false in pre{visit,visit} to skip visiting children // | WithGuards - provides the ability to save/restore data like a LIFO stack; to save, // call GuardValue with the variable to save, the variable will // automatically be restored to its previous value after the corresponding // postvisit/postmutate teminates. //------------------------------------------------------------------------------------------------- template< typename pass_t > class Pass final : public ast::Visitor { public: template< typename... Args > Pass( Args &&... args) : m_pass( std::forward( args )... ) { // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor typedef Pass this_t; this_t * const * visitor = __pass::visitor(m_pass, 0); if(visitor) { *const_cast( visitor ) = this; } } virtual ~Pass() = default; pass_t m_pass; virtual DeclWithType * visit( const ObjectDecl * ) override final; virtual DeclWithType * visit( const FunctionDecl * ) override final; virtual Decl * visit( const StructDecl * ) override final; virtual Decl * visit( const UnionDecl * ) override final; virtual Decl * visit( const EnumDecl * ) override final; virtual Decl * visit( const TraitDecl * ) override final; virtual Decl * visit( const TypeDecl * ) override final; virtual Decl * visit( const TypedefDecl * ) override final; virtual AsmDecl * visit( const AsmDecl * ) override final; virtual StaticAssertDecl * visit( const StaticAssertDecl * ) override final; virtual CompoundStmt * visit( const CompoundStmt * ) override final; virtual Stmt * visit( const ExprStmt * ) override final; virtual Stmt * visit( const AsmStmt * ) override final; virtual Stmt * visit( const DirectiveStmt * ) override final; virtual Stmt * visit( const IfStmt * ) override final; virtual Stmt * visit( const WhileStmt * ) override final; virtual Stmt * visit( const ForStmt * ) override final; virtual Stmt * visit( const SwitchStmt * ) override final; virtual Stmt * visit( const CaseStmt * ) override final; virtual Stmt * visit( const BranchStmt * ) override final; virtual Stmt * visit( const ReturnStmt * ) override final; virtual Stmt * visit( const ThrowStmt * ) override final; virtual Stmt * visit( const TryStmt * ) override final; virtual Stmt * visit( const CatchStmt * ) override final; virtual Stmt * visit( const FinallyStmt * ) override final; virtual Stmt * visit( const WaitForStmt * ) override final; virtual Stmt * visit( const WithStmt * ) override final; virtual NullStmt * visit( const NullStmt * ) override final; virtual Stmt * visit( const DeclStmt * ) override final; virtual Stmt * visit( const ImplicitCtorDtorStmt * ) override final; virtual Expr * visit( const ApplicationExpr * ) override final; virtual Expr * visit( const UntypedExpr * ) override final; virtual Expr * visit( const NameExpr * ) override final; virtual Expr * visit( const AddressExpr * ) override final; virtual Expr * visit( const LabelAddressExpr * ) override final; virtual Expr * visit( const CastExpr * ) override final; virtual Expr * visit( const KeywordCastExpr * ) override final; virtual Expr * visit( const VirtualCastExpr * ) override final; virtual Expr * visit( const UntypedMemberExpr * ) override final; virtual Expr * visit( const MemberExpr * ) override final; virtual Expr * visit( const VariableExpr * ) override final; virtual Expr * visit( const ConstantExpr * ) override final; virtual Expr * visit( const SizeofExpr * ) override final; virtual Expr * visit( const AlignofExpr * ) override final; virtual Expr * visit( const UntypedOffsetofExpr * ) override final; virtual Expr * visit( const OffsetofExpr * ) override final; virtual Expr * visit( const OffsetPackExpr * ) override final; virtual Expr * visit( const AttrExpr * ) override final; virtual Expr * visit( const LogicalExpr * ) override final; virtual Expr * visit( const ConditionalExpr * ) override final; virtual Expr * visit( const CommaExpr * ) override final; virtual Expr * visit( const TypeExpr * ) override final; virtual Expr * visit( const AsmExpr * ) override final; virtual Expr * visit( const ImplicitCopyCtorExpr * ) override final; virtual Expr * visit( const ConstructorExpr * ) override final; virtual Expr * visit( const CompoundLiteralExpr * ) override final; virtual Expr * visit( const RangeExpr * ) override final; virtual Expr * visit( const UntypedTupleExpr * ) override final; virtual Expr * visit( const TupleExpr * ) override final; virtual Expr * visit( const TupleIndexExpr * ) override final; virtual Expr * visit( const TupleAssignExpr * ) override final; virtual Expr * visit( const StmtExpr * ) override final; virtual Expr * visit( const UniqueExpr * ) override final; virtual Expr * visit( const UntypedInitExpr * ) override final; virtual Expr * visit( const InitExpr * ) override final; virtual Expr * visit( const DeletedExpr * ) override final; virtual Expr * visit( const DefaultArgExpr * ) override final; virtual Expr * visit( const GenericExpr * ) override final; virtual Type * visit( const VoidType * ) override final; virtual Type * visit( const BasicType * ) override final; virtual Type * visit( const PointerType * ) override final; virtual Type * visit( const ArrayType * ) override final; virtual Type * visit( const ReferenceType * ) override final; virtual Type * visit( const QualifiedType * ) override final; virtual Type * visit( const FunctionType * ) override final; virtual Type * visit( const StructInstType * ) override final; virtual Type * visit( const UnionInstType * ) override final; virtual Type * visit( const EnumInstType * ) override final; virtual Type * visit( const TraitInstType * ) override final; virtual Type * visit( const TypeInstType * ) override final; virtual Type * visit( const TupleType * ) override final; virtual Type * visit( const TypeofType * ) override final; virtual Type * visit( const AttrType * ) override final; virtual Type * visit( const VarArgsType * ) override final; virtual Type * visit( const ZeroType * ) override final; virtual Type * visit( const OneType * ) override final; virtual Type * visit( const GlobalScopeType * ) override final; virtual Designation * visit( const Designation * ) override final; virtual Init * visit( const SingleInit * ) override final; virtual Init * visit( const ListInit * ) override final; virtual Init * visit( const ConstructorInit * ) override final; virtual Constant * visit( const Constant * ) override final; virtual Attribute * visit( const Attribute * ) override final; virtual TypeSubstitution * visit( const TypeSubstitution * ) override final; private: bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(m_pass, 0); return ptr ? *ptr : true; } private: template void maybe_accept(parent_t * & , typename parent_t::child_t *); ast::Statement * call_accept( const ast::Statement * ); ast::Expression * call_accept( const ast::Expression * ); template< template class container_t > container_t< ast::ptr > call_accept( const container_t< ast::ptr > & ); template< template class container_t, typename node_t > container_t< ast::ptr > call_accept( const container_t< ast::ptr > & container ); private: struct indexer_guard { Pass & pass; indexer_guard( Pass & pass ) : pass( pass ) { __pass::indexer::enter(pass, 0); } ~indexer_guard() { __pass::indexer::leave(pass, 0); } }; indexer_guard make_indexer_guard() { return { *this }; } private: struct scope_guard { Pass & pass; scope_guard( Pass & pass ) : pass( pass ) { __pass::scope::enter(pass, 0); } ~scope_guard() { __pass::scope::leave(pass, 0); } }; scope_guard make_scope_guard() { return { *this }; } }; //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // Guard value : RAII type to restore a value when the Pass finishes visiting this node template void GuardValue( pass_t * pass, T& val ) { pass->at_cleanup( [ val ]( void * newVal ) { * static_cast< T * >( newVal ) = val; }, static_cast< void * >( & val ) ); } //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // PASS ACCESSORIES //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // Keep track of the type substitution struct WithConstTypeSubstitution { const ast::TypeSubstitution * env = nullptr; }; template using std_list = std::list; // Used if visitor requires added statements before or after the current node. // The Pass template handles what *before* and *after* means automatically template< template class container_t = std_list > struct WithStmtsToAdd { container_t< ast::ptr< ast::Statement > > stmtsToAddBefore; container_t< ast::ptr< ast::Statement > > stmtsToAddAfter; }; // Used if visitor requires added declarations before or after the current node. // The Pass template handles what *before* and *after* means automatically template< template class container_t = std_list > struct WithDeclsToAdd { ~WithDeclsToAdd() { assert( declsToAddBefore.empty() ); } container_t< ast::ptr< ast::Declaration > > declsToAddBefore; container_t< ast::ptr< ast::Declaration > > declsToAddAfter; }; // Use if visitation should stop at certain levels // set visit_children false of all child nodes should be ignored struct WithShortCircuiting { __pass::bool_ref visit_children; }; // class WithGuards { // protected: // WithGuards() = default; // ~WithGuards() = default; // public: // at_cleanup_t at_cleanup; // template< typename T > // void GuardValue( T& val ) { // at_cleanup( [ val ]( void * newVal ) { // * static_cast< T * >( newVal ) = val; // }, static_cast< void * >( & val ) ); // } // template< typename T > // void GuardScope( T& val ) { // val.beginScope(); // at_cleanup( []( void * val ) { // static_cast< T * >( val )->endScope(); // }, static_cast< void * >( & val ) ); // } // template< typename Func > // void GuardAction( Func func ) { // at_cleanup( [func](__attribute__((unused)) void *) { func(); }, nullptr ); // } // }; // template // class WithVisitorRef { // protected: // WithVisitorRef() {} // ~WithVisitorRef() {} // public: // PassVisitor * const visitor = nullptr; // }; struct WithIndexer { SymTab::Indexer indexer; }; }