source: src/AST/Pass.impl.hpp @ 85e49a6

ADTast-experimental
Last change on this file since 85e49a6 was 6e1e2d0, checked in by caparsons <caparson@…>, 19 months ago

resolved merge conflicts

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