source: src/AST/Pass.impl.hpp @ 08e4e6a

ADTast-experimentalenumpthread-emulationqualifiedEnum
Last change on this file since 08e4e6a was ee918356, checked in by Thierry Delisle <tdelisle@…>, 2 years ago

Some clean-up to remove clang-only warnings

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