source: src/AST/Pass.impl.hpp @ def751f

ADTast-experimentalpthread-emulationqualifiedEnum
Last change on this file since def751f was ffec1bf, checked in by Fangren Yu <f37yu@…>, 2 years ago

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

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