source: src/AST/Pass.impl.hpp@ 90ce35aa

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 90ce35aa was c570806, checked in by Michael Brooks <mlbrooks@…>, 6 years ago

Changing new AST's ImplicitCtorDtorStatement to _own_ its reference to the underlying ctor/dtor call statement.

This change fixes a new-AST-resolver bug in which bootloader output lacks constructor/destructor calls surrounding overt declarations. (Constructor/destructor calls on temporaries were already working.)

This fix addresses the last bootloader output difference: now new-AST's bootloader output equals old AST's.

ImplicitCtorDtorStatement's reference to the underlying ctor/dtor call statement changes from readonly<...> to ptr<...>. Accordingly, the visitor framework changes, now proceeding across this reference. Old-AST deletes across this reference on ~ImplicitCtorDtorStatement and old-AST's visitor framework proceeds across this reference. Old AST's declaration of this reference had an incorrect comment saying the reference was non-owning; adjusting this comment.

Future issues with the ownership details of this reference may occur, e.g. when trying to port FixInit to new-AST. In the new-AST modeling, we need to ensure that re-parenting works properly, i.e. we don't delete in a transition state where the ref count falls to zero. The lifecycle of the underlying ctor/dtor statement is only partially understood. I believe, but have only partly tested, that for overt declarations:

This change has been tested for a clean convert-convert difference (vs no new-AST at all), for convert-convert at: pre-resolve, post-resolve, post-parse.

This change has been tested for, and causes a small regression of, cfa-cpp speed of compiling bootloader. Old AST = 4.72 s, New AST before this change = 3.74 s, New ast after this change 3.79 s. All numbers are mean of middle 3, among 5 samples, with 5-sample SDs <= 0.16 sec and mid-3 SDs <= 0.012 sec. New-AST improvement before this fix = 20.8%, new-AST improvement after this fix = 19.7%, a loss of 5.3% of the improvement.

The performance loss makes sense because more constructor calls are being exposed to the resolver. Constructor calls are generally most expensive to resolve, because of their high number of function-name matches.

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