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

ADTast-experimentalpthread-emulationqualifiedEnum
Last change on this file since eb5962a was eb5962a, checked in by JiadaL <j82liang@…>, 22 months ago

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

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