source: src/AST/Pass.impl.hpp @ 378de69

ADTast-experimental
Last change on this file since 378de69 was d0bdb18, checked in by Andrew Beach <ajbeach@…>, 23 months ago

Removed extra scope calls in the new Pass. Added some documentation on the core's possible special members.

  • Property mode set to 100644
File size: 65.1 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ast::Pass.impl.hpp --
8//
9// Author           : Thierry Delisle
10// Created On       : Thu May 09 15::37::05 2019
11// Last Modified By :
12// Last Modified On :
13// Update Count     :
14//
15
16#pragma once
17// IWYU pragma: private, include "AST/Pass.hpp"
18
19#include <type_traits>
20#include <unordered_map>
21
22#include "AST/TranslationUnit.hpp"
23#include "AST/TypeSubstitution.hpp"
24
25#define VISIT_START( node ) \
26        using namespace ast; \
27        /* back-up the last known code location */ \
28        __attribute__((unused)) auto loc_guard = ast::__pass::make_location_guard( core, node, 0 ); \
29        /* back-up the visit children */ \
30        __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(core, 0) ); \
31        /* setup the scope for passes that want to run code at exit */ \
32        __attribute__((unused)) ast::__pass::guard_value          guard2( ast::__pass::at_cleanup    (core, 0) ); \
33        /* begin tracing memory allocation if requested by this pass */ \
34        __pass::beginTrace( core, 0 ); \
35        /* call the implementation of the previsit of this pass */ \
36        __pass::previsit( core, node, 0 );
37
38#define VISIT_END( type, node ) \
39        /* call the implementation of the postvisit of this pass */ \
40        auto __return = __pass::postvisit( core, node, 0 ); \
41        assertf(__return, "post visit should never return null"); \
42        /* end tracing memory allocation if requested by this pass */ \
43        __pass::endTrace( core, 0 ); \
44        return __return;
45
46#ifdef PEDANTIC_PASS_ASSERT
47#define __pedantic_pass_assert(...) assert (__VA_ARGS__)
48#define __pedantic_pass_assertf(...) assertf(__VA_ARGS__)
49#else
50#define __pedantic_pass_assert(...)
51#define __pedantic_pass_assertf(...)
52#endif
53
54namespace ast {
55        template<typename node_t>
56        node_t * shallowCopy( const node_t * node );
57
58        namespace __pass {
59                // Check if this is either a null pointer or a pointer to an empty container
60                template<typename T>
61                static inline bool empty( T * ptr ) {
62                        return !ptr || ptr->empty();
63                }
64
65                template< typename core_t, typename node_t >
66                static inline node_t* mutate(const node_t *node) {
67                        return std::is_base_of<PureVisitor, core_t>::value ? ::ast::shallowCopy(node) : ::ast::mutate(node);
68                }
69
70                //------------------------------
71                template<typename it_t, template <class...> class container_t>
72                static inline void take_all( it_t it, container_t<ast::ptr<ast::Decl>> * decls, bool * mutated = nullptr ) {
73                        if(empty(decls)) return;
74
75                        std::transform(decls->begin(), decls->end(), it, [](const ast::Decl * decl) -> auto {
76                                        return new DeclStmt( decl->location, decl );
77                                });
78                        decls->clear();
79                        if(mutated) *mutated = true;
80                }
81
82                template<typename it_t, template <class...> class container_t>
83                static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * stmts, bool * mutated = nullptr ) {
84                        if(empty(stmts)) return;
85
86                        std::move(stmts->begin(), stmts->end(), it);
87                        stmts->clear();
88                        if(mutated) *mutated = true;
89                }
90
91                //------------------------------
92                /// Check if should be skipped, different for pointers and containers
93                template<typename node_t>
94                bool skip( const ast::ptr<node_t> & val) {
95                        return !val;
96                }
97
98                template< template <class...> class container_t, typename node_t >
99                bool skip( const container_t<ast::ptr< node_t >> & val ) {
100                        return val.empty();
101                }
102
103                //------------------------------
104                /// Get the value to visit, different for pointers and containers
105                template<typename node_t>
106                auto get( const ast::ptr<node_t> & val, int ) -> decltype(val.get()) {
107                        return val.get();
108                }
109
110                template<typename node_t>
111                const node_t & get( const node_t & val, long) {
112                        return val;
113                }
114
115                //------------------------------
116                /// Check if value was mutated, different for pointers and containers
117                template<typename lhs_t, typename rhs_t>
118                bool differs( const lhs_t * old_val, const rhs_t * new_val ) {
119                        return old_val != new_val;
120                }
121
122                template< template <class...> class container_t, typename node_t >
123                bool differs( const container_t<ast::ptr< node_t >> &, const container_t<ast::ptr< node_t >> & new_val ) {
124                        return !new_val.empty();
125                }
126        }
127
128        template< typename node_t >
129        template< typename object_t, typename super_t, typename field_t >
130        void __pass::result1< node_t >::apply( object_t * object, field_t super_t::* field ) {
131                object->*field = value;
132        }
133
134        template< typename core_t >
135        template< typename node_t >
136        auto ast::Pass< core_t >::call_accept( const node_t * node )
137                -> typename ast::Pass< core_t >::template generic_call_accept_result<node_t>::type
138        {
139                __pedantic_pass_assert( __visit_children() );
140                __pedantic_pass_assert( node );
141
142                static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
143                static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR");
144
145                auto nval = node->accept( *this );
146                __pass::result1<
147                        typename std::remove_pointer< decltype( node->accept(*this) ) >::type
148                > res;
149                res.differs = nval != node;
150                res.value = nval;
151                return res;
152        }
153
154        template< typename core_t >
155        __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
156                __pedantic_pass_assert( __visit_children() );
157                __pedantic_pass_assert( expr );
158
159                auto nval = expr->accept( *this );
160                return { nval != expr, nval };
161        }
162
163        template< typename core_t >
164        __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
165                __pedantic_pass_assert( __visit_children() );
166                __pedantic_pass_assert( stmt );
167
168                const ast::Stmt * nval = stmt->accept( *this );
169                return { nval != stmt, nval };
170        }
171
172        template< typename core_t >
173        __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept_top( const ast::Expr * expr ) {
174                __pedantic_pass_assert( __visit_children() );
175                __pedantic_pass_assert( expr );
176
177                const ast::TypeSubstitution ** typeSubs_ptr = __pass::typeSubs( core, 0 );
178                if ( typeSubs_ptr && expr->env ) {
179                        *typeSubs_ptr = expr->env;
180                }
181
182                auto nval = expr->accept( *this );
183                return { nval != expr, nval };
184        }
185
186        template< typename core_t >
187        __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
188                __pedantic_pass_assert( __visit_children() );
189                __pedantic_pass_assert( stmt );
190
191                // add a few useful symbols to the scope
192                using __pass::empty;
193
194                // get the stmts/decls that will need to be spliced in
195                auto stmts_before = __pass::stmtsToAddBefore( core, 0 );
196                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0 );
197                auto decls_before = __pass::declsToAddBefore( core, 0 );
198                auto decls_after  = __pass::declsToAddAfter ( core, 0 );
199
200                // These may be modified by subnode but most be restored once we exit this statemnet.
201                ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::typeSubs( core, 0 ) );
202                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
203                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
204                ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
205                ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
206
207                // Now is the time to actually visit the node
208                const ast::Stmt * nstmt = stmt->accept( *this );
209
210                // If the pass doesn't want to add anything then we are done
211                if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {
212                        return { nstmt != stmt, nstmt };
213                }
214
215                // Make sure that it is either adding statements or declartions but not both
216                // this is because otherwise the order would be awkward to predict
217                assert(( empty( stmts_before ) && empty( stmts_after ))
218                    || ( empty( decls_before ) && empty( decls_after )) );
219
220                // Create a new Compound Statement to hold the new decls/stmts
221                ast::CompoundStmt * compound = new ast::CompoundStmt( stmt->location );
222
223                // Take all the declarations that go before
224                __pass::take_all( std::back_inserter( compound->kids ), decls_before );
225                __pass::take_all( std::back_inserter( compound->kids ), stmts_before );
226
227                // Insert the original declaration
228                compound->kids.emplace_back( nstmt );
229
230                // Insert all the declarations that go before
231                __pass::take_all( std::back_inserter( compound->kids ), decls_after );
232                __pass::take_all( std::back_inserter( compound->kids ), stmts_after );
233
234                return {true, compound};
235        }
236
237        template< template <class...> class container_t >
238        template< typename object_t, typename super_t, typename field_t >
239        void __pass::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) {
240                auto & container = object->*field;
241                __pedantic_pass_assert( container.size() <= values.size() );
242
243                auto cit = enumerate(container).begin();
244
245                container_t<ptr<Stmt>> nvals;
246                for (delta & d : values) {
247                        if ( d.is_old ) {
248                                __pedantic_pass_assert( cit.idx <= d.old_idx );
249                                std::advance( cit, d.old_idx - cit.idx );
250                                nvals.push_back( std::move( (*cit).val) );
251                        } else {
252                                nvals.push_back( std::move(d.new_val) );
253                        }
254                }
255
256                container = std::move(nvals);
257        }
258
259        template< template <class...> class container_t >
260        template< template <class...> class incontainer_t >
261        void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Stmt>> * stmts ) {
262                if (!stmts || stmts->empty()) return;
263
264                std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ),
265                        [](ast::ptr<ast::Stmt>& stmt) -> delta {
266                                return delta( stmt.release(), -1, false );
267                        });
268                stmts->clear();
269                differs = true;
270        }
271
272        template< template<class...> class container_t >
273        template< template<class...> class incontainer_t >
274        void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Decl>> * decls ) {
275                if (!decls || decls->empty()) return;
276
277                std::transform(decls->begin(), decls->end(), std::back_inserter( values ),
278                        [](ast::ptr<ast::Decl>& decl) -> delta {
279                                auto loc = decl->location;
280                                auto stmt = new DeclStmt( loc, decl.release() );
281                                return delta( stmt, -1, false );
282                        });
283                decls->clear();
284                differs = true;
285        }
286
287        template< typename core_t >
288        template< template <class...> class container_t >
289        __pass::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
290                __pedantic_pass_assert( __visit_children() );
291                if( statements.empty() ) return {};
292
293                // We are going to aggregate errors for all these statements
294                SemanticErrorException errors;
295
296                // add a few useful symbols to the scope
297                using __pass::empty;
298
299                // get the stmts/decls that will need to be spliced in
300                auto stmts_before = __pass::stmtsToAddBefore( core, 0 );
301                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0 );
302                auto decls_before = __pass::declsToAddBefore( core, 0 );
303                auto decls_after  = __pass::declsToAddAfter ( core, 0 );
304
305                // These may be modified by subnode but most be restored once we exit this statemnet.
306                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
307                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
308                ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
309                ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
310
311                // update pass statitistics
312                pass_visitor_stats.depth++;
313                pass_visitor_stats.max->push(pass_visitor_stats.depth);
314                pass_visitor_stats.avg->push(pass_visitor_stats.depth);
315
316                __pass::resultNstmt<container_t> new_kids;
317                for( auto value : enumerate( statements ) ) {
318                        try {
319                                size_t i = value.idx;
320                                const Stmt * stmt = value.val;
321                                __pedantic_pass_assert( stmt );
322                                const ast::Stmt * new_stmt = stmt->accept( *this );
323                                assert( new_stmt );
324                                if(new_stmt != stmt ) { new_kids.differs = true; }
325
326                                // Make sure that it is either adding statements or declartions but not both
327                                // this is because otherwise the order would be awkward to predict
328                                assert(( empty( stmts_before ) && empty( stmts_after ))
329                                    || ( empty( decls_before ) && empty( decls_after )) );
330
331                                // Take all the statements which should have gone after, N/A for first iteration
332                                new_kids.take_all( decls_before );
333                                new_kids.take_all( stmts_before );
334
335                                // Now add the statement if there is one
336                                if(new_stmt != stmt) {
337                                        new_kids.values.emplace_back( new_stmt, i, false );
338                                } else {
339                                        new_kids.values.emplace_back( nullptr, i, true );
340                                }
341
342                                // Take all the declarations that go before
343                                new_kids.take_all( decls_after );
344                                new_kids.take_all( stmts_after );
345                        }
346                        catch ( SemanticErrorException &e ) {
347                                errors.append( e );
348                        }
349                }
350                pass_visitor_stats.depth--;
351                if ( !errors.isEmpty() ) { throw errors; }
352
353                return new_kids;
354        }
355
356        template< template <class...> class container_t, typename node_t >
357        template< typename object_t, typename super_t, typename field_t >
358        void __pass::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) {
359                auto & container = object->*field;
360                __pedantic_pass_assert( container.size() == values.size() );
361
362                for(size_t i = 0; i < container.size(); i++) {
363                        // Take all the elements that are different in 'values'
364                        // and swap them into 'container'
365                        if( values[i] != nullptr ) swap(container[i], values[i]);
366                }
367
368                // Now the original containers should still have the unchanged values
369                // but also contain the new values
370        }
371
372        template< typename core_t >
373        template< template <class...> class container_t, typename node_t >
374        __pass::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
375                __pedantic_pass_assert( __visit_children() );
376                if( container.empty() ) return {};
377                SemanticErrorException errors;
378
379                pass_visitor_stats.depth++;
380                pass_visitor_stats.max->push(pass_visitor_stats.depth);
381                pass_visitor_stats.avg->push(pass_visitor_stats.depth);
382
383                bool mutated = false;
384                container_t<ptr<node_t>> new_kids;
385                for ( const node_t * node : container ) {
386                        try {
387                                __pedantic_pass_assert( node );
388                                const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) );
389                                if(new_stmt != node ) {
390                                        mutated = true;
391                                        new_kids.emplace_back( new_stmt );
392                                } else {
393                                        new_kids.emplace_back( nullptr );
394                                }
395
396                        }
397                        catch( SemanticErrorException &e ) {
398                                errors.append( e );
399                        }
400                }
401
402                __pedantic_pass_assert( new_kids.size() == container.size() );
403                pass_visitor_stats.depth--;
404                if ( ! errors.isEmpty() ) { throw errors; }
405
406                return ast::__pass::resultN<container_t, node_t>{ mutated, new_kids };
407        }
408
409        template< typename core_t >
410        template<typename node_t, typename super_t, typename field_t>
411        void ast::Pass< core_t >::maybe_accept(
412                const node_t * & parent,
413                field_t super_t::*field
414        ) {
415                static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
416
417                if(__pass::skip(parent->*field)) return;
418                const auto & old_val = __pass::get(parent->*field, 0);
419
420                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
421
422                auto new_val = call_accept( old_val );
423
424                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR");
425
426                if( new_val.differs ) {
427                        auto new_parent = __pass::mutate<core_t>(parent);
428                        new_val.apply(new_parent, field);
429                        parent = new_parent;
430                }
431        }
432
433        template< typename core_t >
434        template<typename node_t, typename super_t, typename field_t>
435        void ast::Pass< core_t >::maybe_accept_top(
436                const node_t * & parent,
437                field_t super_t::*field
438        ) {
439                static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
440
441                if(__pass::skip(parent->*field)) return;
442                const auto & old_val = __pass::get(parent->*field, 0);
443
444                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
445
446                auto new_val = call_accept_top( old_val );
447
448                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR");
449
450                if( new_val.differs ) {
451                        auto new_parent = __pass::mutate<core_t>(parent);
452                        new_val.apply(new_parent, field);
453                        parent = new_parent;
454                }
455        }
456
457        template< typename core_t >
458        template<typename node_t, typename super_t, typename field_t>
459        void ast::Pass< core_t >::maybe_accept_as_compound(
460                const node_t * & parent,
461                field_t super_t::*child
462        ) {
463                static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
464
465                if(__pass::skip(parent->*child)) return;
466                const auto & old_val = __pass::get(parent->*child, 0);
467
468                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
469
470                auto new_val = call_accept_as_compound( old_val );
471
472                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
473
474                if( new_val.differs ) {
475                        auto new_parent = __pass::mutate<core_t>(parent);
476                        new_val.apply( new_parent, child );
477                        parent = new_parent;
478                }
479        }
480
481}
482
483//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
484//========================================================================================================================================================================
485//========================================================================================================================================================================
486//========================================================================================================================================================================
487//========================================================================================================================================================================
488//========================================================================================================================================================================
489//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
490
491template< typename core_t >
492inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< core_t > & visitor ) {
493        // We are going to aggregate errors for all these statements
494        SemanticErrorException errors;
495
496        // add a few useful symbols to the scope
497        using __pass::empty;
498
499        // get the stmts/decls that will need to be spliced in
500        auto decls_before = __pass::declsToAddBefore( visitor.core, 0);
501        auto decls_after  = __pass::declsToAddAfter ( visitor.core, 0);
502
503        // update pass statitistics
504        pass_visitor_stats.depth++;
505        pass_visitor_stats.max->push(pass_visitor_stats.depth);
506        pass_visitor_stats.avg->push(pass_visitor_stats.depth);
507
508        for ( std::list< ast::ptr<ast::Decl> >::iterator i = decls.begin(); ; ++i ) {
509                // splice in new declarations after previous decl
510                if ( !empty( decls_after ) ) { decls.splice( i, *decls_after ); }
511
512                if ( i == decls.end() ) break;
513
514                try {
515                        // run visitor on declaration
516                        ast::ptr<ast::Decl> & node = *i;
517                        assert( node );
518                        node = node->accept( visitor );
519                }
520                catch( SemanticErrorException &e ) {
521                        if (__pass::on_error (visitor.core, *i, 0))
522                                errors.append( e );
523                }
524
525                // splice in new declarations before current decl
526                if ( !empty( decls_before ) ) { decls.splice( i, *decls_before ); }
527        }
528        pass_visitor_stats.depth--;
529        if ( !errors.isEmpty() ) { throw errors; }
530}
531
532template< typename core_t >
533inline void ast::accept_all( ast::TranslationUnit & unit, ast::Pass< core_t > & visitor ) {
534        if ( auto ptr = __pass::translation_unit::get_cptr( visitor.core, 0 ) ) {
535                ValueGuard<const TranslationUnit *> guard( *ptr );
536                *ptr = &unit;
537                return ast::accept_all( unit.decls, visitor );
538        } else {
539                return ast::accept_all( unit.decls, visitor );
540        }
541}
542
543// A NOTE ON THE ORDER OF TRAVERSAL
544//
545// Types and typedefs have their base types visited before they are added to the type table.  This is ok, since there is
546// no such thing as a recursive type or typedef.
547//
548//             typedef struct { T *x; } T; // never allowed
549//
550// for structs/unions, it is possible to have recursion, so the decl should be added as if it's incomplete to begin, the
551// members are traversed, and then the complete type should be added (assuming the type is completed by this particular
552// declaration).
553//
554//             struct T { struct T *x; }; // allowed
555//
556// It is important to add the complete type to the symbol table *after* the members/base has been traversed, since that
557// traversal may modify the definition of the type and these modifications should be visible when the symbol table is
558// queried later in this pass.
559
560//--------------------------------------------------------------------------
561// ObjectDecl
562template< typename core_t >
563const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::ObjectDecl * node ) {
564        VISIT_START( node );
565
566        if ( __visit_children() ) {
567                {
568                        guard_symtab guard { *this };
569                        maybe_accept( node, &ObjectDecl::type );
570                }
571                maybe_accept( node, &ObjectDecl::init          );
572                maybe_accept( node, &ObjectDecl::bitfieldWidth );
573                maybe_accept( node, &ObjectDecl::attributes    );
574        }
575
576        __pass::symtab::addId( core, 0, node );
577
578        VISIT_END( DeclWithType, node );
579}
580
581//--------------------------------------------------------------------------
582// FunctionDecl
583template< typename core_t >
584const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::FunctionDecl * node ) {
585        VISIT_START( node );
586
587        __pass::symtab::addId( core, 0, node );
588
589        if ( __visit_children() ) {
590                maybe_accept( node, &FunctionDecl::withExprs );
591        }
592        {
593                // with clause introduces a level of scope (for the with expression members).
594                // with clause exprs are added to the symbol table before parameters so that parameters
595                // shadow with exprs and not the other way around.
596                guard_symtab guard { *this };
597                __pass::symtab::addWith( core, 0, node->withExprs, node );
598                {
599                        guard_symtab guard { *this };
600                        // implicit add __func__ identifier as specified in the C manual 6.4.2.2
601                        // This is a C name and so has C linkage.
602                        static ast::ptr< ast::ObjectDecl > func{ new ast::ObjectDecl{
603                                CodeLocation{}, "__func__",
604                                new ast::ArrayType{
605                                        new ast::BasicType{ ast::BasicType::Char, ast::CV::Const },
606                                        nullptr, VariableLen, DynamicDim
607                                },
608                                nullptr,
609                                ast::Storage::Classes(),
610                                ast::Linkage::C,
611                        } };
612                        __pass::symtab::addId( core, 0, func );
613                        if ( __visit_children() ) {
614                                maybe_accept( node, &FunctionDecl::type_params );
615                                maybe_accept( node, &FunctionDecl::assertions );
616                                maybe_accept( node, &FunctionDecl::params );
617                                maybe_accept( node, &FunctionDecl::returns );
618                                maybe_accept( node, &FunctionDecl::type );
619                                maybe_accept( node, &FunctionDecl::attributes );
620                                // First remember that we are now within a function.
621                                ValueGuard< bool > oldInFunction( inFunction );
622                                inFunction = true;
623                                // The function body needs to have the same scope as parameters.
624                                // A CompoundStmt will not enter a new scope if atFunctionTop is true.
625                                ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
626                                atFunctionTop = true;
627                                maybe_accept( node, &FunctionDecl::stmts );
628                        }
629                }
630        }
631
632        VISIT_END( DeclWithType, node );
633}
634
635//--------------------------------------------------------------------------
636// StructDecl
637template< typename core_t >
638const ast::Decl * ast::Pass< core_t >::visit( const ast::StructDecl * node ) {
639        VISIT_START( node );
640
641        // make up a forward declaration and add it before processing the members
642        // needs to be on the heap because addStruct saves the pointer
643        __pass::symtab::addStructFwd( core, 0, node );
644
645        if ( __visit_children() ) {
646                guard_symtab guard { * this };
647                maybe_accept( node, &StructDecl::params     );
648                maybe_accept( node, &StructDecl::members    );
649                maybe_accept( node, &StructDecl::attributes );
650        }
651
652        // this addition replaces the forward declaration
653        __pass::symtab::addStruct( core, 0, node );
654
655        VISIT_END( Decl, node );
656}
657
658//--------------------------------------------------------------------------
659// UnionDecl
660template< typename core_t >
661const ast::Decl * ast::Pass< core_t >::visit( const ast::UnionDecl * node ) {
662        VISIT_START( node );
663
664        // make up a forward declaration and add it before processing the members
665        __pass::symtab::addUnionFwd( core, 0, node );
666
667        if ( __visit_children() ) {
668                guard_symtab guard { * this };
669                maybe_accept( node, &UnionDecl::params     );
670                maybe_accept( node, &UnionDecl::members    );
671                maybe_accept( node, &UnionDecl::attributes );
672        }
673
674        __pass::symtab::addUnion( core, 0, node );
675
676        VISIT_END( Decl, node );
677}
678
679//--------------------------------------------------------------------------
680// EnumDecl
681template< typename core_t >
682const ast::Decl * ast::Pass< core_t >::visit( const ast::EnumDecl * node ) {
683        VISIT_START( node );
684
685        __pass::symtab::addEnum( core, 0, node );
686
687        if ( __visit_children() ) {
688                if ( node->hide == ast::EnumDecl::EnumHiding::Hide ) {
689                        guard_symtab guard { *this };
690                        maybe_accept( node, &EnumDecl::base );
691                        maybe_accept( node, &EnumDecl::params     );
692                        maybe_accept( node, &EnumDecl::members    );
693                        maybe_accept( node, &EnumDecl::attributes );
694                } else {
695                        maybe_accept( node, &EnumDecl::base );
696                        maybe_accept( node, &EnumDecl::params     );
697                        maybe_accept( node, &EnumDecl::members    );
698                        maybe_accept( node, &EnumDecl::attributes );
699                }
700        }
701
702        VISIT_END( Decl, node );
703}
704
705//--------------------------------------------------------------------------
706// TraitDecl
707template< typename core_t >
708const ast::Decl * ast::Pass< core_t >::visit( const ast::TraitDecl * node ) {
709        VISIT_START( node );
710
711        if ( __visit_children() ) {
712                guard_symtab guard { *this };
713                maybe_accept( node, &TraitDecl::params     );
714                maybe_accept( node, &TraitDecl::members    );
715                maybe_accept( node, &TraitDecl::attributes );
716        }
717
718        __pass::symtab::addTrait( core, 0, node );
719
720        VISIT_END( Decl, node );
721}
722
723//--------------------------------------------------------------------------
724// TypeDecl
725template< typename core_t >
726const ast::Decl * ast::Pass< core_t >::visit( const ast::TypeDecl * node ) {
727        VISIT_START( node );
728
729        if ( __visit_children() ) {
730                guard_symtab guard { *this };
731                maybe_accept( node, &TypeDecl::base   );
732        }
733
734        // see A NOTE ON THE ORDER OF TRAVERSAL, above
735        // note that assertions come after the type is added to the symtab, since they are not part of the type proper
736        // and may depend on the type itself
737        __pass::symtab::addType( core, 0, node );
738
739        if ( __visit_children() ) {
740                maybe_accept( node, &TypeDecl::assertions );
741
742                {
743                        guard_symtab guard { *this };
744                        maybe_accept( node, &TypeDecl::init );
745                }
746        }
747
748        VISIT_END( Decl, node );
749}
750
751//--------------------------------------------------------------------------
752// TypedefDecl
753template< typename core_t >
754const ast::Decl * ast::Pass< core_t >::visit( const ast::TypedefDecl * node ) {
755        VISIT_START( node );
756
757        if ( __visit_children() ) {
758                guard_symtab guard { *this };
759                maybe_accept( node, &TypedefDecl::base   );
760        }
761
762        __pass::symtab::addType( core, 0, node );
763
764        if ( __visit_children() ) {
765                maybe_accept( node, &TypedefDecl::assertions );
766        }
767
768        VISIT_END( Decl, node );
769}
770
771//--------------------------------------------------------------------------
772// AsmDecl
773template< typename core_t >
774const ast::AsmDecl * ast::Pass< core_t >::visit( const ast::AsmDecl * node ) {
775        VISIT_START( node );
776
777        if ( __visit_children() ) {
778                maybe_accept( node, &AsmDecl::stmt );
779        }
780
781        VISIT_END( AsmDecl, node );
782}
783
784//--------------------------------------------------------------------------
785// DirectiveDecl
786template< typename core_t >
787const ast::DirectiveDecl * ast::Pass< core_t >::visit( const ast::DirectiveDecl * node ) {
788        VISIT_START( node );
789
790        if ( __visit_children() ) {
791                maybe_accept( node, &DirectiveDecl::stmt );
792        }
793
794        VISIT_END( DirectiveDecl, node );
795}
796
797//--------------------------------------------------------------------------
798// StaticAssertDecl
799template< typename core_t >
800const ast::StaticAssertDecl * ast::Pass< core_t >::visit( const ast::StaticAssertDecl * node ) {
801        VISIT_START( node );
802
803        if ( __visit_children() ) {
804                maybe_accept_top( node, &StaticAssertDecl::cond );
805                maybe_accept( node, &StaticAssertDecl::msg  );
806        }
807
808        VISIT_END( StaticAssertDecl, node );
809}
810
811//--------------------------------------------------------------------------
812// InlineMemberDecl
813template< typename core_t >
814const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::InlineMemberDecl * node ) {
815        VISIT_START( node );
816
817        if ( __visit_children() ) {
818                {
819                        guard_symtab guard { *this };
820                        maybe_accept( node, &InlineMemberDecl::type );
821                }
822        }
823
824        VISIT_END( DeclWithType, node );
825}
826
827//--------------------------------------------------------------------------
828// CompoundStmt
829template< typename core_t >
830const ast::CompoundStmt * ast::Pass< core_t >::visit( const ast::CompoundStmt * node ) {
831        VISIT_START( node );
832
833        if ( __visit_children() ) {
834                // Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result.
835                auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() {
836                        if ( enterScope ) {
837                                __pass::symtab::enter(core, 0);
838                        }
839                }, [this, leaveScope = !this->atFunctionTop]() {
840                        if ( leaveScope ) {
841                                __pass::symtab::leave(core, 0);
842                        }
843                });
844                ValueGuard< bool > guard2( atFunctionTop );
845                atFunctionTop = false;
846                guard_scope guard3 { *this };
847                maybe_accept( node, &CompoundStmt::kids );
848        }
849
850        VISIT_END( CompoundStmt, node );
851}
852
853//--------------------------------------------------------------------------
854// ExprStmt
855template< typename core_t >
856const ast::Stmt * ast::Pass< core_t >::visit( const ast::ExprStmt * node ) {
857        VISIT_START( node );
858
859        if ( __visit_children() ) {
860                maybe_accept_top( node, &ExprStmt::expr );
861        }
862
863        VISIT_END( Stmt, node );
864}
865
866//--------------------------------------------------------------------------
867// AsmStmt
868template< typename core_t >
869const ast::Stmt * ast::Pass< core_t >::visit( const ast::AsmStmt * node ) {
870        VISIT_START( node )
871
872        if ( __visit_children() ) {
873                maybe_accept( node, &AsmStmt::instruction );
874                maybe_accept( node, &AsmStmt::output      );
875                maybe_accept( node, &AsmStmt::input       );
876                maybe_accept( node, &AsmStmt::clobber     );
877        }
878
879        VISIT_END( Stmt, node );
880}
881
882//--------------------------------------------------------------------------
883// DirectiveStmt
884template< typename core_t >
885const ast::Stmt * ast::Pass< core_t >::visit( const ast::DirectiveStmt * node ) {
886        VISIT_START( node )
887
888        VISIT_END( Stmt, node );
889}
890
891//--------------------------------------------------------------------------
892// IfStmt
893template< typename core_t >
894const ast::Stmt * ast::Pass< core_t >::visit( const ast::IfStmt * node ) {
895        VISIT_START( node );
896
897        if ( __visit_children() ) {
898                // if statements introduce a level of scope (for the initialization)
899                guard_symtab guard { *this };
900                maybe_accept( node, &IfStmt::inits    );
901                maybe_accept_top( node, &IfStmt::cond     );
902                maybe_accept_as_compound( node, &IfStmt::then );
903                maybe_accept_as_compound( node, &IfStmt::else_ );
904        }
905
906        VISIT_END( Stmt, node );
907}
908
909//--------------------------------------------------------------------------
910// WhileDoStmt
911template< typename core_t >
912const ast::Stmt * ast::Pass< core_t >::visit( const ast::WhileDoStmt * node ) {
913        VISIT_START( node );
914
915        if ( __visit_children() ) {
916                // while statements introduce a level of scope (for the initialization)
917                guard_symtab guard { *this };
918                maybe_accept( node, &WhileDoStmt::inits );
919                maybe_accept_top( node, &WhileDoStmt::cond  );
920                maybe_accept_as_compound( node, &WhileDoStmt::body  );
921        }
922
923        VISIT_END( Stmt, node );
924}
925
926//--------------------------------------------------------------------------
927// ForStmt
928template< typename core_t >
929const ast::Stmt * ast::Pass< core_t >::visit( const ast::ForStmt * node ) {
930        VISIT_START( node );
931
932        if ( __visit_children() ) {
933                // for statements introduce a level of scope (for the initialization)
934                guard_symtab guard { *this };
935                // xxx - old ast does not create WithStmtsToAdd scope for loop inits. should revisit this later.
936                maybe_accept( node, &ForStmt::inits );
937                maybe_accept_top( node, &ForStmt::cond  );
938                maybe_accept_top( node, &ForStmt::inc   );
939                maybe_accept_as_compound( node, &ForStmt::body  );
940        }
941
942        VISIT_END( Stmt, node );
943}
944
945//--------------------------------------------------------------------------
946// SwitchStmt
947template< typename core_t >
948const ast::Stmt * ast::Pass< core_t >::visit( const ast::SwitchStmt * node ) {
949        VISIT_START( node );
950
951        if ( __visit_children() ) {
952                maybe_accept_top( node, &SwitchStmt::cond  );
953                maybe_accept( node, &SwitchStmt::cases );
954        }
955
956        VISIT_END( Stmt, node );
957}
958
959//--------------------------------------------------------------------------
960// CaseClause
961template< typename core_t >
962const ast::CaseClause * ast::Pass< core_t >::visit( const ast::CaseClause * node ) {
963        VISIT_START( node );
964
965        if ( __visit_children() ) {
966                maybe_accept_top( node, &CaseClause::cond  );
967                maybe_accept( node, &CaseClause::stmts );
968        }
969
970        VISIT_END( CaseClause, node );
971}
972
973//--------------------------------------------------------------------------
974// BranchStmt
975template< typename core_t >
976const ast::Stmt * ast::Pass< core_t >::visit( const ast::BranchStmt * node ) {
977        VISIT_START( node );
978        VISIT_END( Stmt, node );
979}
980
981//--------------------------------------------------------------------------
982// ReturnStmt
983template< typename core_t >
984const ast::Stmt * ast::Pass< core_t >::visit( const ast::ReturnStmt * node ) {
985        VISIT_START( node );
986
987        if ( __visit_children() ) {
988                maybe_accept_top( node, &ReturnStmt::expr );
989        }
990
991        VISIT_END( Stmt, node );
992}
993
994//--------------------------------------------------------------------------
995// ThrowStmt
996template< typename core_t >
997const ast::Stmt * ast::Pass< core_t >::visit( const ast::ThrowStmt * node ) {
998        VISIT_START( node );
999
1000        if ( __visit_children() ) {
1001                maybe_accept( node, &ThrowStmt::expr   );
1002                maybe_accept( node, &ThrowStmt::target );
1003        }
1004
1005        VISIT_END( Stmt, node );
1006}
1007
1008//--------------------------------------------------------------------------
1009// TryStmt
1010template< typename core_t >
1011const ast::Stmt * ast::Pass< core_t >::visit( const ast::TryStmt * node ) {
1012        VISIT_START( node );
1013
1014        if ( __visit_children() ) {
1015                maybe_accept( node, &TryStmt::body     );
1016                maybe_accept( node, &TryStmt::handlers );
1017                maybe_accept( node, &TryStmt::finally  );
1018        }
1019
1020        VISIT_END( Stmt, node );
1021}
1022
1023//--------------------------------------------------------------------------
1024// CatchClause
1025template< typename core_t >
1026const ast::CatchClause * ast::Pass< core_t >::visit( const ast::CatchClause * node ) {
1027        VISIT_START( node );
1028
1029        if ( __visit_children() ) {
1030                // catch statements introduce a level of scope (for the caught exception)
1031                guard_symtab guard { *this };
1032                maybe_accept( node, &CatchClause::decl );
1033                maybe_accept_top( node, &CatchClause::cond );
1034                maybe_accept_as_compound( node, &CatchClause::body );
1035        }
1036
1037        VISIT_END( CatchClause, node );
1038}
1039
1040//--------------------------------------------------------------------------
1041// FinallyClause
1042template< typename core_t >
1043const ast::FinallyClause * ast::Pass< core_t >::visit( const ast::FinallyClause * node ) {
1044        VISIT_START( node );
1045
1046        if ( __visit_children() ) {
1047                maybe_accept( node, &FinallyClause::body );
1048        }
1049
1050        VISIT_END( FinallyClause, node );
1051}
1052
1053//--------------------------------------------------------------------------
1054// FinallyStmt
1055template< typename core_t >
1056const ast::Stmt * ast::Pass< core_t >::visit( const ast::SuspendStmt * node ) {
1057        VISIT_START( node );
1058
1059        if ( __visit_children() ) {
1060                maybe_accept( node, &SuspendStmt::then   );
1061        }
1062
1063        VISIT_END( Stmt, node );
1064}
1065
1066//--------------------------------------------------------------------------
1067// WaitForStmt
1068template< typename core_t >
1069const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitForStmt * node ) {
1070        VISIT_START( node );
1071
1072        if ( __visit_children() ) {
1073                maybe_accept( node, &WaitForStmt::clauses );
1074                maybe_accept( node, &WaitForStmt::timeout_time );
1075                maybe_accept( node, &WaitForStmt::timeout_stmt );
1076                maybe_accept( node, &WaitForStmt::timeout_cond );
1077                maybe_accept( node, &WaitForStmt::else_stmt );
1078                maybe_accept( node, &WaitForStmt::else_cond );
1079        }
1080
1081        VISIT_END( Stmt, node );
1082}
1083
1084//--------------------------------------------------------------------------
1085// WaitForClause
1086template< typename core_t >
1087const ast::WaitForClause * ast::Pass< core_t >::visit( const ast::WaitForClause * node ) {
1088        VISIT_START( node );
1089
1090        if ( __visit_children() ) {
1091                maybe_accept( node, &WaitForClause::target_func );
1092                maybe_accept( node, &WaitForClause::target_args );
1093                maybe_accept( node, &WaitForClause::stmt );
1094                maybe_accept( node, &WaitForClause::cond );
1095        }
1096
1097        VISIT_END( WaitForClause, node );
1098}
1099
1100//--------------------------------------------------------------------------
1101// WithStmt
1102template< typename core_t >
1103const ast::Decl * ast::Pass< core_t >::visit( const ast::WithStmt * node ) {
1104        VISIT_START( node );
1105
1106        if ( __visit_children() ) {
1107                maybe_accept( node, &WithStmt::exprs );
1108                {
1109                        // catch statements introduce a level of scope (for the caught exception)
1110                        guard_symtab guard { *this };
1111                        __pass::symtab::addWith( core, 0, node->exprs, node );
1112                        maybe_accept( node, &WithStmt::stmt );
1113                }
1114        }
1115
1116        VISIT_END( Stmt, node );
1117}
1118
1119//--------------------------------------------------------------------------
1120// NullStmt
1121template< typename core_t >
1122const ast::NullStmt * ast::Pass< core_t >::visit( const ast::NullStmt * node ) {
1123        VISIT_START( node );
1124        VISIT_END( NullStmt, node );
1125}
1126
1127//--------------------------------------------------------------------------
1128// DeclStmt
1129template< typename core_t >
1130const ast::Stmt * ast::Pass< core_t >::visit( const ast::DeclStmt * node ) {
1131        VISIT_START( node );
1132
1133        if ( __visit_children() ) {
1134                maybe_accept( node, &DeclStmt::decl );
1135        }
1136
1137        VISIT_END( Stmt, node );
1138}
1139
1140//--------------------------------------------------------------------------
1141// ImplicitCtorDtorStmt
1142template< typename core_t >
1143const ast::Stmt * ast::Pass< core_t >::visit( const ast::ImplicitCtorDtorStmt * node ) {
1144        VISIT_START( node );
1145
1146        // For now this isn't visited, it is unclear if this causes problem
1147        // if all tests are known to pass, remove this code
1148        if ( __visit_children() ) {
1149                maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
1150        }
1151
1152        VISIT_END( Stmt, node );
1153}
1154
1155//--------------------------------------------------------------------------
1156// MutexStmt
1157template< typename core_t >
1158const ast::Stmt * ast::Pass< core_t >::visit( const ast::MutexStmt * node ) {
1159        VISIT_START( node );
1160
1161        if ( __visit_children() ) {
1162                // mutex statements introduce a level of scope (for the initialization)
1163                guard_symtab guard { *this };
1164                maybe_accept( node, &MutexStmt::stmt );
1165                maybe_accept( node, &MutexStmt::mutexObjs );
1166        }
1167
1168        VISIT_END( Stmt, node );
1169}
1170
1171//--------------------------------------------------------------------------
1172// ApplicationExpr
1173template< typename core_t >
1174const ast::Expr * ast::Pass< core_t >::visit( const ast::ApplicationExpr * node ) {
1175        VISIT_START( node );
1176
1177        if ( __visit_children() ) {
1178                {
1179                        guard_symtab guard { *this };
1180                        maybe_accept( node, &ApplicationExpr::result );
1181                }
1182                maybe_accept( node, &ApplicationExpr::func );
1183                maybe_accept( node, &ApplicationExpr::args );
1184        }
1185
1186        VISIT_END( Expr, node );
1187}
1188
1189//--------------------------------------------------------------------------
1190// UntypedExpr
1191template< typename core_t >
1192const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedExpr * node ) {
1193        VISIT_START( node );
1194
1195        if ( __visit_children() ) {
1196                {
1197                        guard_symtab guard { *this };
1198                        maybe_accept( node, &UntypedExpr::result );
1199                }
1200
1201                maybe_accept( node, &UntypedExpr::args );
1202        }
1203
1204        VISIT_END( Expr, node );
1205}
1206
1207//--------------------------------------------------------------------------
1208// NameExpr
1209template< typename core_t >
1210const ast::Expr * ast::Pass< core_t >::visit( const ast::NameExpr * node ) {
1211        VISIT_START( node );
1212
1213        if ( __visit_children() ) {
1214                guard_symtab guard { *this };
1215                maybe_accept( node, &NameExpr::result );
1216        }
1217
1218        VISIT_END( Expr, node );
1219}
1220
1221//--------------------------------------------------------------------------
1222// QualifiedNameExpr
1223template< typename core_t >
1224const ast::Expr * ast::Pass< core_t >::visit( const ast::QualifiedNameExpr * node ) {
1225        VISIT_START( node );
1226        if ( __visit_children() ) {
1227                guard_symtab guard { *this };
1228                maybe_accept( node, &QualifiedNameExpr::type_decl );
1229        }
1230        VISIT_END( Expr, node );
1231}
1232
1233//--------------------------------------------------------------------------
1234// CastExpr
1235template< typename core_t >
1236const ast::Expr * ast::Pass< core_t >::visit( const ast::CastExpr * node ) {
1237        VISIT_START( node );
1238
1239        if ( __visit_children() ) {
1240                {
1241                        guard_symtab guard { *this };
1242                        maybe_accept( node, &CastExpr::result );
1243                }
1244                maybe_accept( node, &CastExpr::arg );
1245        }
1246
1247        VISIT_END( Expr, node );
1248}
1249
1250//--------------------------------------------------------------------------
1251// KeywordCastExpr
1252template< typename core_t >
1253const ast::Expr * ast::Pass< core_t >::visit( const ast::KeywordCastExpr * node ) {
1254        VISIT_START( node );
1255
1256        if ( __visit_children() ) {
1257                {
1258                        guard_symtab guard { *this };
1259                        maybe_accept( node, &KeywordCastExpr::result );
1260                }
1261                maybe_accept( node, &KeywordCastExpr::arg );
1262        }
1263
1264        VISIT_END( Expr, node );
1265}
1266
1267//--------------------------------------------------------------------------
1268// VirtualCastExpr
1269template< typename core_t >
1270const ast::Expr * ast::Pass< core_t >::visit( const ast::VirtualCastExpr * node ) {
1271        VISIT_START( node );
1272
1273        if ( __visit_children() ) {
1274                {
1275                        guard_symtab guard { *this };
1276                        maybe_accept( node, &VirtualCastExpr::result );
1277                }
1278                maybe_accept( node, &VirtualCastExpr::arg );
1279        }
1280
1281        VISIT_END( Expr, node );
1282}
1283
1284//--------------------------------------------------------------------------
1285// AddressExpr
1286template< typename core_t >
1287const ast::Expr * ast::Pass< core_t >::visit( const ast::AddressExpr * node ) {
1288        VISIT_START( node );
1289
1290        if ( __visit_children() ) {
1291                {
1292                        guard_symtab guard { *this };
1293                        maybe_accept( node, &AddressExpr::result );
1294                }
1295                maybe_accept( node, &AddressExpr::arg );
1296        }
1297
1298        VISIT_END( Expr, node );
1299}
1300
1301//--------------------------------------------------------------------------
1302// LabelAddressExpr
1303template< typename core_t >
1304const ast::Expr * ast::Pass< core_t >::visit( const ast::LabelAddressExpr * node ) {
1305        VISIT_START( node );
1306
1307        if ( __visit_children() ) {
1308                guard_symtab guard { *this };
1309                maybe_accept( node, &LabelAddressExpr::result );
1310        }
1311
1312        VISIT_END( Expr, node );
1313}
1314
1315//--------------------------------------------------------------------------
1316// UntypedMemberExpr
1317template< typename core_t >
1318const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedMemberExpr * node ) {
1319        VISIT_START( node );
1320
1321        if ( __visit_children() ) {
1322                {
1323                        guard_symtab guard { *this };
1324                        maybe_accept( node, &UntypedMemberExpr::result );
1325                }
1326                maybe_accept( node, &UntypedMemberExpr::aggregate );
1327                maybe_accept( node, &UntypedMemberExpr::member    );
1328        }
1329
1330        VISIT_END( Expr, node );
1331}
1332
1333//--------------------------------------------------------------------------
1334// MemberExpr
1335template< typename core_t >
1336const ast::Expr * ast::Pass< core_t >::visit( const ast::MemberExpr * node ) {
1337        VISIT_START( node );
1338
1339        if ( __visit_children() ) {
1340                {
1341                        guard_symtab guard { *this };
1342                        maybe_accept( node, &MemberExpr::result );
1343                }
1344                maybe_accept( node, &MemberExpr::aggregate );
1345        }
1346
1347        VISIT_END( Expr, node );
1348}
1349
1350//--------------------------------------------------------------------------
1351// VariableExpr
1352template< typename core_t >
1353const ast::Expr * ast::Pass< core_t >::visit( const ast::VariableExpr * node ) {
1354        VISIT_START( node );
1355
1356        if ( __visit_children() ) {
1357                guard_symtab guard { *this };
1358                maybe_accept( node, &VariableExpr::result );
1359        }
1360
1361        VISIT_END( Expr, node );
1362}
1363
1364//--------------------------------------------------------------------------
1365// ConstantExpr
1366template< typename core_t >
1367const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstantExpr * node ) {
1368        VISIT_START( node );
1369
1370        if ( __visit_children() ) {
1371                guard_symtab guard { *this };
1372                maybe_accept( node, &ConstantExpr::result );
1373        }
1374
1375        VISIT_END( Expr, node );
1376}
1377
1378//--------------------------------------------------------------------------
1379// SizeofExpr
1380template< typename core_t >
1381const ast::Expr * ast::Pass< core_t >::visit( const ast::SizeofExpr * node ) {
1382        VISIT_START( node );
1383
1384        if ( __visit_children() ) {
1385                {
1386                        guard_symtab guard { *this };
1387                        maybe_accept( node, &SizeofExpr::result );
1388                }
1389                if ( node->type ) {
1390                        maybe_accept( node, &SizeofExpr::type );
1391                } else {
1392                        maybe_accept( node, &SizeofExpr::expr );
1393                }
1394        }
1395
1396        VISIT_END( Expr, node );
1397}
1398
1399//--------------------------------------------------------------------------
1400// AlignofExpr
1401template< typename core_t >
1402const ast::Expr * ast::Pass< core_t >::visit( const ast::AlignofExpr * node ) {
1403        VISIT_START( node );
1404
1405        if ( __visit_children() ) {
1406                {
1407                        guard_symtab guard { *this };
1408                        maybe_accept( node, &AlignofExpr::result );
1409                }
1410                if ( node->type ) {
1411                        maybe_accept( node, &AlignofExpr::type );
1412                } else {
1413                        maybe_accept( node, &AlignofExpr::expr );
1414                }
1415        }
1416
1417        VISIT_END( Expr, node );
1418}
1419
1420//--------------------------------------------------------------------------
1421// UntypedOffsetofExpr
1422template< typename core_t >
1423const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedOffsetofExpr * node ) {
1424        VISIT_START( node );
1425
1426        if ( __visit_children() ) {
1427                {
1428                        guard_symtab guard { *this };
1429                        maybe_accept( node, &UntypedOffsetofExpr::result );
1430                }
1431                maybe_accept( node, &UntypedOffsetofExpr::type   );
1432        }
1433
1434        VISIT_END( Expr, node );
1435}
1436
1437//--------------------------------------------------------------------------
1438// OffsetofExpr
1439template< typename core_t >
1440const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetofExpr * node ) {
1441        VISIT_START( node );
1442
1443        if ( __visit_children() ) {
1444                {
1445                        guard_symtab guard { *this };
1446                        maybe_accept( node, &OffsetofExpr::result );
1447                }
1448                maybe_accept( node, &OffsetofExpr::type   );
1449        }
1450
1451        VISIT_END( Expr, node );
1452}
1453
1454//--------------------------------------------------------------------------
1455// OffsetPackExpr
1456template< typename core_t >
1457const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetPackExpr * node ) {
1458        VISIT_START( node );
1459
1460        if ( __visit_children() ) {
1461                {
1462                        guard_symtab guard { *this };
1463                        maybe_accept( node, &OffsetPackExpr::result );
1464                }
1465                maybe_accept( node, &OffsetPackExpr::type   );
1466        }
1467
1468        VISIT_END( Expr, node );
1469}
1470
1471//--------------------------------------------------------------------------
1472// LogicalExpr
1473template< typename core_t >
1474const ast::Expr * ast::Pass< core_t >::visit( const ast::LogicalExpr * node ) {
1475        VISIT_START( node );
1476
1477        if ( __visit_children() ) {
1478                {
1479                        guard_symtab guard { *this };
1480                        maybe_accept( node, &LogicalExpr::result );
1481                }
1482                maybe_accept( node, &LogicalExpr::arg1 );
1483                maybe_accept( node, &LogicalExpr::arg2 );
1484        }
1485
1486        VISIT_END( Expr, node );
1487}
1488
1489//--------------------------------------------------------------------------
1490// ConditionalExpr
1491template< typename core_t >
1492const ast::Expr * ast::Pass< core_t >::visit( const ast::ConditionalExpr * node ) {
1493        VISIT_START( node );
1494
1495        if ( __visit_children() ) {
1496                {
1497                        guard_symtab guard { *this };
1498                        maybe_accept( node, &ConditionalExpr::result );
1499                }
1500                maybe_accept( node, &ConditionalExpr::arg1 );
1501                maybe_accept( node, &ConditionalExpr::arg2 );
1502                maybe_accept( node, &ConditionalExpr::arg3 );
1503        }
1504
1505        VISIT_END( Expr, node );
1506}
1507
1508//--------------------------------------------------------------------------
1509// CommaExpr
1510template< typename core_t >
1511const ast::Expr * ast::Pass< core_t >::visit( const ast::CommaExpr * node ) {
1512        VISIT_START( node );
1513
1514        if ( __visit_children() ) {
1515                {
1516                        guard_symtab guard { *this };
1517                        maybe_accept( node, &CommaExpr::result );
1518                }
1519                maybe_accept( node, &CommaExpr::arg1 );
1520                maybe_accept( node, &CommaExpr::arg2 );
1521        }
1522
1523        VISIT_END( Expr, node );
1524}
1525
1526//--------------------------------------------------------------------------
1527// TypeExpr
1528template< typename core_t >
1529const ast::Expr * ast::Pass< core_t >::visit( const ast::TypeExpr * node ) {
1530        VISIT_START( node );
1531
1532        if ( __visit_children() ) {
1533                {
1534                        guard_symtab guard { *this };
1535                        maybe_accept( node, &TypeExpr::result );
1536                }
1537                maybe_accept( node, &TypeExpr::type );
1538        }
1539
1540        VISIT_END( Expr, node );
1541}
1542
1543//--------------------------------------------------------------------------
1544// DimensionExpr
1545template< typename core_t >
1546const ast::Expr * ast::Pass< core_t >::visit( const ast::DimensionExpr * node ) {
1547        VISIT_START( node );
1548
1549        if ( __visit_children() ) {
1550                guard_symtab guard { *this };
1551                maybe_accept( node, &DimensionExpr::result );
1552        }
1553
1554        VISIT_END( Expr, node );
1555}
1556
1557//--------------------------------------------------------------------------
1558// AsmExpr
1559template< typename core_t >
1560const ast::Expr * ast::Pass< core_t >::visit( const ast::AsmExpr * node ) {
1561        VISIT_START( node );
1562
1563        if ( __visit_children() ) {
1564                {
1565                        guard_symtab guard { *this };
1566                        maybe_accept( node, &AsmExpr::result );
1567                }
1568                maybe_accept( node, &AsmExpr::constraint );
1569                maybe_accept( node, &AsmExpr::operand    );
1570        }
1571
1572        VISIT_END( Expr, node );
1573}
1574
1575//--------------------------------------------------------------------------
1576// ImplicitCopyCtorExpr
1577template< typename core_t >
1578const ast::Expr * ast::Pass< core_t >::visit( const ast::ImplicitCopyCtorExpr * node ) {
1579        VISIT_START( node );
1580
1581        if ( __visit_children() ) {
1582                {
1583                        guard_symtab guard { *this };
1584                        maybe_accept( node, &ImplicitCopyCtorExpr::result );
1585                }
1586                maybe_accept( node, &ImplicitCopyCtorExpr::callExpr    );
1587        }
1588
1589        VISIT_END( Expr, node );
1590}
1591
1592//--------------------------------------------------------------------------
1593// ConstructorExpr
1594template< typename core_t >
1595const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstructorExpr * node ) {
1596        VISIT_START( node );
1597
1598        if ( __visit_children() ) {
1599                {
1600                        guard_symtab guard { *this };
1601                        maybe_accept( node, &ConstructorExpr::result );
1602                }
1603                maybe_accept( node, &ConstructorExpr::callExpr );
1604        }
1605
1606        VISIT_END( Expr, node );
1607}
1608
1609//--------------------------------------------------------------------------
1610// CompoundLiteralExpr
1611template< typename core_t >
1612const ast::Expr * ast::Pass< core_t >::visit( const ast::CompoundLiteralExpr * node ) {
1613        VISIT_START( node );
1614
1615        if ( __visit_children() ) {
1616                {
1617                        guard_symtab guard { *this };
1618                        maybe_accept( node, &CompoundLiteralExpr::result );
1619                }
1620                maybe_accept( node, &CompoundLiteralExpr::init );
1621        }
1622
1623        VISIT_END( Expr, node );
1624}
1625
1626//--------------------------------------------------------------------------
1627// RangeExpr
1628template< typename core_t >
1629const ast::Expr * ast::Pass< core_t >::visit( const ast::RangeExpr * node ) {
1630        VISIT_START( node );
1631
1632        if ( __visit_children() ) {
1633                {
1634                        guard_symtab guard { *this };
1635                        maybe_accept( node, &RangeExpr::result );
1636                }
1637                maybe_accept( node, &RangeExpr::low    );
1638                maybe_accept( node, &RangeExpr::high   );
1639        }
1640
1641        VISIT_END( Expr, node );
1642}
1643
1644//--------------------------------------------------------------------------
1645// UntypedTupleExpr
1646template< typename core_t >
1647const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedTupleExpr * node ) {
1648        VISIT_START( node );
1649
1650        if ( __visit_children() ) {
1651                {
1652                        guard_symtab guard { *this };
1653                        maybe_accept( node, &UntypedTupleExpr::result );
1654                }
1655                maybe_accept( node, &UntypedTupleExpr::exprs  );
1656        }
1657
1658        VISIT_END( Expr, node );
1659}
1660
1661//--------------------------------------------------------------------------
1662// TupleExpr
1663template< typename core_t >
1664const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleExpr * node ) {
1665        VISIT_START( node );
1666
1667        if ( __visit_children() ) {
1668                {
1669                        guard_symtab guard { *this };
1670                        maybe_accept( node, &TupleExpr::result );
1671                }
1672                maybe_accept( node, &TupleExpr::exprs  );
1673        }
1674
1675        VISIT_END( Expr, node );
1676}
1677
1678//--------------------------------------------------------------------------
1679// TupleIndexExpr
1680template< typename core_t >
1681const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleIndexExpr * node ) {
1682        VISIT_START( node );
1683
1684        if ( __visit_children() ) {
1685                {
1686                        guard_symtab guard { *this };
1687                        maybe_accept( node, &TupleIndexExpr::result );
1688                }
1689                maybe_accept( node, &TupleIndexExpr::tuple  );
1690        }
1691
1692        VISIT_END( Expr, node );
1693}
1694
1695//--------------------------------------------------------------------------
1696// TupleAssignExpr
1697template< typename core_t >
1698const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleAssignExpr * node ) {
1699        VISIT_START( node );
1700
1701        if ( __visit_children() ) {
1702                {
1703                        guard_symtab guard { *this };
1704                        maybe_accept( node, &TupleAssignExpr::result );
1705                }
1706                maybe_accept( node, &TupleAssignExpr::stmtExpr );
1707        }
1708
1709        VISIT_END( Expr, node );
1710}
1711
1712//--------------------------------------------------------------------------
1713// StmtExpr
1714template< typename core_t >
1715const ast::Expr * ast::Pass< core_t >::visit( const ast::StmtExpr * node ) {
1716        VISIT_START( node );
1717
1718        if ( __visit_children() ) {
1719                // don't want statements from outer CompoundStmts to be added to this StmtExpr
1720                // get the stmts that will need to be spliced in
1721                auto stmts_before = __pass::stmtsToAddBefore( core, 0);
1722                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0);
1723
1724                // These may be modified by subnode but most be restored once we exit this statemnet.
1725                ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::typeSubs( core, 0 ) );
1726                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
1727                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
1728
1729                {
1730                        guard_symtab guard { *this };
1731                        maybe_accept( node, &StmtExpr::result );
1732                }
1733                maybe_accept( node, &StmtExpr::stmts       );
1734                maybe_accept( node, &StmtExpr::returnDecls );
1735                maybe_accept( node, &StmtExpr::dtors       );
1736        }
1737
1738        VISIT_END( Expr, node );
1739}
1740
1741//--------------------------------------------------------------------------
1742// UniqueExpr
1743template< typename core_t >
1744const ast::Expr * ast::Pass< core_t >::visit( const ast::UniqueExpr * node ) {
1745        VISIT_START( node );
1746
1747        if ( __visit_children() ) {
1748                {
1749                        guard_symtab guard { *this };
1750                        maybe_accept( node, &UniqueExpr::result );
1751                }
1752                maybe_accept( node, &UniqueExpr::expr   );
1753        }
1754
1755        VISIT_END( Expr, node );
1756}
1757
1758//--------------------------------------------------------------------------
1759// UntypedInitExpr
1760template< typename core_t >
1761const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedInitExpr * node ) {
1762        VISIT_START( node );
1763
1764        if ( __visit_children() ) {
1765                {
1766                        guard_symtab guard { *this };
1767                        maybe_accept( node, &UntypedInitExpr::result );
1768                }
1769                maybe_accept( node, &UntypedInitExpr::expr   );
1770                // not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
1771        }
1772
1773        VISIT_END( Expr, node );
1774}
1775
1776//--------------------------------------------------------------------------
1777// InitExpr
1778template< typename core_t >
1779const ast::Expr * ast::Pass< core_t >::visit( const ast::InitExpr * node ) {
1780        VISIT_START( node );
1781
1782        if ( __visit_children() ) {
1783                {
1784                        guard_symtab guard { *this };
1785                        maybe_accept( node, &InitExpr::result );
1786                }
1787                maybe_accept( node, &InitExpr::expr   );
1788                maybe_accept( node, &InitExpr::designation );
1789        }
1790
1791        VISIT_END( Expr, node );
1792}
1793
1794//--------------------------------------------------------------------------
1795// DeletedExpr
1796template< typename core_t >
1797const ast::Expr * ast::Pass< core_t >::visit( const ast::DeletedExpr * node ) {
1798        VISIT_START( node );
1799
1800        if ( __visit_children() ) {
1801                {
1802                        guard_symtab guard { *this };
1803                        maybe_accept( node, &DeletedExpr::result );
1804                }
1805                maybe_accept( node, &DeletedExpr::expr );
1806                // don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
1807        }
1808
1809        VISIT_END( Expr, node );
1810}
1811
1812//--------------------------------------------------------------------------
1813// DefaultArgExpr
1814template< typename core_t >
1815const ast::Expr * ast::Pass< core_t >::visit( const ast::DefaultArgExpr * node ) {
1816        VISIT_START( node );
1817
1818        if ( __visit_children() ) {
1819                {
1820                        guard_symtab guard { *this };
1821                        maybe_accept( node, &DefaultArgExpr::result );
1822                }
1823                maybe_accept( node, &DefaultArgExpr::expr );
1824        }
1825
1826        VISIT_END( Expr, node );
1827}
1828
1829//--------------------------------------------------------------------------
1830// GenericExpr
1831template< typename core_t >
1832const ast::Expr * ast::Pass< core_t >::visit( const ast::GenericExpr * node ) {
1833        VISIT_START( node );
1834
1835        if ( __visit_children() ) {
1836                {
1837                        guard_symtab guard { *this };
1838                        maybe_accept( node, &GenericExpr::result );
1839                }
1840                maybe_accept( node, &GenericExpr::control );
1841
1842                std::vector<GenericExpr::Association> new_kids;
1843                new_kids.reserve(node->associations.size());
1844                bool mutated = false;
1845                for( const auto & assoc : node->associations ) {
1846                        const Type * type = nullptr;
1847                        if( assoc.type ) {
1848                                guard_symtab guard { *this };
1849                                type = assoc.type->accept( *this );
1850                                if( type != assoc.type ) mutated = true;
1851                        }
1852                        const Expr * expr = nullptr;
1853                        if( assoc.expr ) {
1854                                expr = assoc.expr->accept( *this );
1855                                if( expr != assoc.expr ) mutated = true;
1856                        }
1857                        new_kids.emplace_back( type, expr );
1858                }
1859
1860                if(mutated) {
1861                        auto n = __pass::mutate<core_t>(node);
1862                        n->associations = std::move( new_kids );
1863                        node = n;
1864                }
1865        }
1866
1867        VISIT_END( Expr, node );
1868}
1869
1870//--------------------------------------------------------------------------
1871// VoidType
1872template< typename core_t >
1873const ast::Type * ast::Pass< core_t >::visit( const ast::VoidType * node ) {
1874        VISIT_START( node );
1875
1876        VISIT_END( Type, node );
1877}
1878
1879//--------------------------------------------------------------------------
1880// BasicType
1881template< typename core_t >
1882const ast::Type * ast::Pass< core_t >::visit( const ast::BasicType * node ) {
1883        VISIT_START( node );
1884
1885        VISIT_END( Type, node );
1886}
1887
1888//--------------------------------------------------------------------------
1889// PointerType
1890template< typename core_t >
1891const ast::Type * ast::Pass< core_t >::visit( const ast::PointerType * node ) {
1892        VISIT_START( node );
1893
1894        if ( __visit_children() ) {
1895                maybe_accept( node, &PointerType::dimension );
1896                maybe_accept( node, &PointerType::base );
1897        }
1898
1899        VISIT_END( Type, node );
1900}
1901
1902//--------------------------------------------------------------------------
1903// ArrayType
1904template< typename core_t >
1905const ast::Type * ast::Pass< core_t >::visit( const ast::ArrayType * node ) {
1906        VISIT_START( node );
1907
1908        if ( __visit_children() ) {
1909                maybe_accept( node, &ArrayType::dimension );
1910                maybe_accept( node, &ArrayType::base );
1911        }
1912
1913        VISIT_END( Type, node );
1914}
1915
1916//--------------------------------------------------------------------------
1917// ReferenceType
1918template< typename core_t >
1919const ast::Type * ast::Pass< core_t >::visit( const ast::ReferenceType * node ) {
1920        VISIT_START( node );
1921
1922        if ( __visit_children() ) {
1923                maybe_accept( node, &ReferenceType::base );
1924        }
1925
1926        VISIT_END( Type, node );
1927}
1928
1929//--------------------------------------------------------------------------
1930// QualifiedType
1931template< typename core_t >
1932const ast::Type * ast::Pass< core_t >::visit( const ast::QualifiedType * node ) {
1933        VISIT_START( node );
1934
1935        if ( __visit_children() ) {
1936                maybe_accept( node, &QualifiedType::parent );
1937                maybe_accept( node, &QualifiedType::child );
1938        }
1939
1940        VISIT_END( Type, node );
1941}
1942
1943//--------------------------------------------------------------------------
1944// FunctionType
1945template< typename core_t >
1946const ast::Type * ast::Pass< core_t >::visit( const ast::FunctionType * node ) {
1947        VISIT_START( node );
1948
1949        if ( __visit_children() ) {
1950                // guard_forall_subs forall_guard { *this, node };
1951                // mutate_forall( node );
1952                maybe_accept( node, &FunctionType::assertions );
1953                maybe_accept( node, &FunctionType::returns );
1954                maybe_accept( node, &FunctionType::params  );
1955        }
1956
1957        VISIT_END( Type, node );
1958}
1959
1960//--------------------------------------------------------------------------
1961// StructInstType
1962template< typename core_t >
1963const ast::Type * ast::Pass< core_t >::visit( const ast::StructInstType * node ) {
1964        VISIT_START( node );
1965
1966        __pass::symtab::addStruct( core, 0, node->name );
1967
1968        if ( __visit_children() ) {
1969                guard_symtab guard { *this };
1970                maybe_accept( node, &StructInstType::params );
1971        }
1972
1973        VISIT_END( Type, node );
1974}
1975
1976//--------------------------------------------------------------------------
1977// UnionInstType
1978template< typename core_t >
1979const ast::Type * ast::Pass< core_t >::visit( const ast::UnionInstType * node ) {
1980        VISIT_START( node );
1981
1982        __pass::symtab::addUnion( core, 0, node->name );
1983
1984        if ( __visit_children() ) {
1985                guard_symtab guard { *this };
1986                maybe_accept( node, &UnionInstType::params );
1987        }
1988
1989        VISIT_END( Type, node );
1990}
1991
1992//--------------------------------------------------------------------------
1993// EnumInstType
1994template< typename core_t >
1995const ast::Type * ast::Pass< core_t >::visit( const ast::EnumInstType * node ) {
1996        VISIT_START( node );
1997
1998        if ( __visit_children() ) {
1999                maybe_accept( node, &EnumInstType::params );
2000        }
2001
2002        VISIT_END( Type, node );
2003}
2004
2005//--------------------------------------------------------------------------
2006// TraitInstType
2007template< typename core_t >
2008const ast::Type * ast::Pass< core_t >::visit( const ast::TraitInstType * node ) {
2009        VISIT_START( node );
2010
2011        if ( __visit_children() ) {
2012                maybe_accept( node, &TraitInstType::params );
2013        }
2014
2015        VISIT_END( Type, node );
2016}
2017
2018//--------------------------------------------------------------------------
2019// TypeInstType
2020template< typename core_t >
2021const ast::Type * ast::Pass< core_t >::visit( const ast::TypeInstType * node ) {
2022        VISIT_START( node );
2023
2024        if ( __visit_children() ) {
2025                {
2026                        maybe_accept( node, &TypeInstType::params );
2027                }
2028                // ensure that base re-bound if doing substitution
2029                __pass::forall::replace( core, 0, node );
2030        }
2031
2032        VISIT_END( Type, node );
2033}
2034
2035//--------------------------------------------------------------------------
2036// TupleType
2037template< typename core_t >
2038const ast::Type * ast::Pass< core_t >::visit( const ast::TupleType * node ) {
2039        VISIT_START( node );
2040
2041        if ( __visit_children() ) {
2042                maybe_accept( node, &TupleType::types );
2043                maybe_accept( node, &TupleType::members );
2044        }
2045
2046        VISIT_END( Type, node );
2047}
2048
2049//--------------------------------------------------------------------------
2050// TypeofType
2051template< typename core_t >
2052const ast::Type * ast::Pass< core_t >::visit( const ast::TypeofType * node ) {
2053        VISIT_START( node );
2054
2055        if ( __visit_children() ) {
2056                maybe_accept( node, &TypeofType::expr );
2057        }
2058
2059        VISIT_END( Type, node );
2060}
2061
2062//--------------------------------------------------------------------------
2063// VTableType
2064template< typename core_t >
2065const ast::Type * ast::Pass< core_t >::visit( const ast::VTableType * node ) {
2066        VISIT_START( node );
2067
2068        if ( __visit_children() ) {
2069                maybe_accept( node, &VTableType::base );
2070        }
2071
2072        VISIT_END( Type, node );
2073}
2074
2075//--------------------------------------------------------------------------
2076// VarArgsType
2077template< typename core_t >
2078const ast::Type * ast::Pass< core_t >::visit( const ast::VarArgsType * node ) {
2079        VISIT_START( node );
2080
2081        VISIT_END( Type, node );
2082}
2083
2084//--------------------------------------------------------------------------
2085// ZeroType
2086template< typename core_t >
2087const ast::Type * ast::Pass< core_t >::visit( const ast::ZeroType * node ) {
2088        VISIT_START( node );
2089
2090        VISIT_END( Type, node );
2091}
2092
2093//--------------------------------------------------------------------------
2094// OneType
2095template< typename core_t >
2096const ast::Type * ast::Pass< core_t >::visit( const ast::OneType * node ) {
2097        VISIT_START( node );
2098
2099        VISIT_END( Type, node );
2100}
2101
2102//--------------------------------------------------------------------------
2103// GlobalScopeType
2104template< typename core_t >
2105const ast::Type * ast::Pass< core_t >::visit( const ast::GlobalScopeType * node ) {
2106        VISIT_START( node );
2107
2108        VISIT_END( Type, node );
2109}
2110
2111
2112//--------------------------------------------------------------------------
2113// Designation
2114template< typename core_t >
2115const ast::Designation * ast::Pass< core_t >::visit( const ast::Designation * node ) {
2116        VISIT_START( node );
2117
2118        if ( __visit_children() ) {
2119                maybe_accept( node, &Designation::designators );
2120        }
2121
2122        VISIT_END( Designation, node );
2123}
2124
2125//--------------------------------------------------------------------------
2126// SingleInit
2127template< typename core_t >
2128const ast::Init * ast::Pass< core_t >::visit( const ast::SingleInit * node ) {
2129        VISIT_START( node );
2130
2131        if ( __visit_children() ) {
2132                maybe_accept_top( node, &SingleInit::value );
2133        }
2134
2135        VISIT_END( Init, node );
2136}
2137
2138//--------------------------------------------------------------------------
2139// ListInit
2140template< typename core_t >
2141const ast::Init * ast::Pass< core_t >::visit( const ast::ListInit * node ) {
2142        VISIT_START( node );
2143
2144        if ( __visit_children() ) {
2145                maybe_accept( node, &ListInit::designations );
2146                maybe_accept( node, &ListInit::initializers );
2147        }
2148
2149        VISIT_END( Init, node );
2150}
2151
2152//--------------------------------------------------------------------------
2153// ConstructorInit
2154template< typename core_t >
2155const ast::Init * ast::Pass< core_t >::visit( const ast::ConstructorInit * node ) {
2156        VISIT_START( node );
2157
2158        if ( __visit_children() ) {
2159                maybe_accept( node, &ConstructorInit::ctor );
2160                maybe_accept( node, &ConstructorInit::dtor );
2161                maybe_accept( node, &ConstructorInit::init );
2162        }
2163
2164        VISIT_END( Init, node );
2165}
2166
2167//--------------------------------------------------------------------------
2168// Attribute
2169template< typename core_t >
2170const ast::Attribute * ast::Pass< core_t >::visit( const ast::Attribute * node  )  {
2171        VISIT_START( node );
2172
2173        if ( __visit_children() ) {
2174                maybe_accept( node, &Attribute::params );
2175        }
2176
2177        VISIT_END( Attribute, node );
2178}
2179
2180//--------------------------------------------------------------------------
2181// TypeSubstitution
2182template< typename core_t >
2183const ast::TypeSubstitution * ast::Pass< core_t >::visit( const ast::TypeSubstitution * node ) {
2184        VISIT_START( node );
2185
2186        if ( __visit_children() ) {
2187                bool mutated = false;
2188                ast::TypeSubstitution::TypeMap new_map;
2189                for ( const auto & p : node->typeMap ) {
2190                        guard_symtab guard { *this };
2191                        auto new_node = p.second->accept( *this );
2192                        if (new_node != p.second) mutated = true;
2193                        new_map.insert({ p.first, new_node });
2194                }
2195                if (mutated) {
2196                        auto new_node = __pass::mutate<core_t>( node );
2197                        new_node->typeMap.swap( new_map );
2198                        node = new_node;
2199                }
2200        }
2201
2202        VISIT_END( TypeSubstitution, node );
2203}
2204
2205#undef VISIT_START
2206#undef VISIT_END
Note: See TracBrowser for help on using the repository browser.