source: src/AST/Convert.cpp @ f7496c5

ADTast-experimentalenumpthread-emulationqualifiedEnum
Last change on this file since f7496c5 was 39d8950, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Thread global information through resolution. Non-top-level calls to the resolver have a bit of a hack but improvements would require changes to the Pass helpers.

  • Property mode set to 100644
File size: 80.6 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// Convert.cpp -- Convert between the new and old syntax trees.
8//
9// Author           : Thierry Delisle
10// Created On       : Thu May 09 15::37::05 2019
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Mar 16 15:01:00 2022
13// Update Count     : 42
14//
15
16#include "Convert.hpp"
17
18#include <deque>
19#include <unordered_map>
20
21#include "AST/Attribute.hpp"
22#include "AST/Copy.hpp"
23#include "AST/Decl.hpp"
24#include "AST/Expr.hpp"
25#include "AST/Init.hpp"
26#include "AST/Stmt.hpp"
27#include "AST/TranslationUnit.hpp"
28#include "AST/TypeSubstitution.hpp"
29
30#include "SymTab/Autogen.h"
31#include "SynTree/Attribute.h"
32#include "SynTree/Declaration.h"
33#include "SynTree/TypeSubstitution.h"
34
35#include "Validate/FindSpecialDecls.h"
36
37//================================================================================================
38// Utilities
39template<template <class...> class C>
40struct to {
41        template<typename T>
42        static auto from( T && v ) -> C< typename T::value_type > {
43                C< typename T::value_type > l;
44                std::move(std::begin(v), std::end(v), std::back_inserter(l));
45                return l;
46        }
47};
48
49//================================================================================================
50namespace ast {
51// These are the shared local information used by ConverterNewToOld and
52// ConverterOldToNew to update the global information in the two versions.
53
54static ast::ptr<ast::Type> sizeType = nullptr;
55static const ast::FunctionDecl * dereferenceOperator = nullptr;
56static const ast::StructDecl   * dtorStruct = nullptr;
57static const ast::FunctionDecl * dtorStructDestroy = nullptr;
58
59}
60
61//================================================================================================
62class ConverterNewToOld : public ast::Visitor {
63        BaseSyntaxNode * node = nullptr;
64        using Cache = std::unordered_map< const ast::Node *, BaseSyntaxNode * >;
65        Cache cache;
66
67        // Statements can no longer be shared.
68        // however, since StmtExprResult is now implemented, need to still maintain
69        // readonly references.
70        Cache readonlyCache;
71
72        template<typename T>
73        struct Getter {
74                ConverterNewToOld & visitor;
75
76                template<typename U, enum ast::Node::ref_type R>
77                T * accept1( const ast::ptr_base<U, R> & ptr ) {
78                        if ( ! ptr ) return nullptr;
79                        ptr->accept( visitor );
80                        T * ret = strict_dynamic_cast< T * >( visitor.node );
81                        visitor.node = nullptr;
82                        return ret;
83                }
84
85                template<typename U>
86                std::list< T * > acceptL( const U & container ) {
87                        std::list< T * > ret;
88                        for ( auto ptr : container ) {
89                                ret.emplace_back( accept1( ptr ) );
90                        }
91                        return ret;
92                }
93        };
94
95    template<typename T>
96    Getter<T> get() {
97        return Getter<T>{ *this };
98    }
99
100        Label makeLabel(Statement * labelled, const ast::Label& label) {
101                // This probably will leak memory, but only until we get rid of the old tree.
102                if ( nullptr == labelled && label.location.isSet() ) {
103                        labelled = new NullStmt();
104                        labelled->location = label.location;
105                }
106                return Label(
107                        label.name,
108                        labelled,
109                        get<Attribute>().acceptL(label.attributes)
110                );
111        }
112
113        template<template <class...> class C>
114        std::list<Label> makeLabelL(Statement * labelled, const C<ast::Label>& labels) {
115                std::list<Label> ret;
116                for (auto label : labels) {
117                        ret.push_back( makeLabel(labelled, label) );
118                }
119                return ret;
120        }
121
122        /// get new qualifiers from old type
123        Type::Qualifiers cv( const ast::Type * ty ) { return { ty->qualifiers.val }; }
124
125        /// returns true and sets `node` if in cache
126        bool inCache( const ast::Node * node ) {
127                auto it = cache.find( node );
128                if ( it == cache.end() ) return false;
129                this->node = it->second;
130                return true;
131        }
132
133public:
134        Declaration * decl( const ast::Decl * declNode ) {
135                return get<Declaration>().accept1( ast::ptr<ast::Decl>( declNode ) );
136        }
137
138private:
139        void declPostamble( Declaration * decl, const ast::Decl * node ) {
140                decl->location = node->location;
141                // name comes from constructor
142                // linkage comes from constructor
143                decl->extension = node->extension;
144                decl->uniqueId = node->uniqueId;
145                // storageClasses comes from constructor
146                this->node = decl;
147        }
148
149        const ast::DeclWithType * declWithTypePostamble (
150                        DeclarationWithType * decl, const ast::DeclWithType * node ) {
151                cache.emplace( node, decl );
152                decl->mangleName = node->mangleName;
153                decl->scopeLevel = node->scopeLevel;
154                decl->asmName = get<Expression>().accept1( node->asmName );
155                // attributes comes from constructor
156                decl->isDeleted = node->isDeleted;
157                // fs comes from constructor
158                declPostamble( decl, node );
159                return nullptr;
160        }
161
162        const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {       
163                if ( inCache( node ) ) {
164                        return nullptr;
165                }
166                auto bfwd = get<Expression>().accept1( node->bitfieldWidth );
167                auto type = get<Type>().accept1( node->type );
168                auto attr = get<Attribute>().acceptL( node->attributes );
169
170                auto decl = new ObjectDecl(
171                        node->name,
172                        Type::StorageClasses( node->storage.val ),
173                        LinkageSpec::Spec( node->linkage.val ),
174                        bfwd,
175                        type->clone(),
176                        nullptr, // prevent infinite loop
177                        attr,
178                        Type::FuncSpecifiers( node->funcSpec.val )
179                );
180
181                // handles the case where node->init references itself
182                // xxx - does it really happen?
183                declWithTypePostamble(decl, node);
184                auto init = get<Initializer>().accept1( node->init );
185                decl->init = init;
186
187                this->node = decl;
188                return nullptr;
189        }
190
191        const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final {
192                if ( inCache( node ) ) return nullptr;
193
194                // function decl contains real variables that the type must use.
195                // the structural change means function type in and out of decl
196                // must be handled **differently** on convert back to old.
197                auto ftype = new FunctionType(
198                        cv(node->type),
199                        (bool)node->type->isVarArgs
200                );
201                ftype->returnVals = get<DeclarationWithType>().acceptL(node->returns);
202                ftype->parameters = get<DeclarationWithType>().acceptL(node->params);
203
204                ftype->forall = get<TypeDecl>().acceptL( node->type_params );
205                if (!node->assertions.empty()) {
206                        assert(!ftype->forall.empty());
207                        // find somewhere to place assertions back, for convenience it is the last slot
208                        ftype->forall.back()->assertions = get<DeclarationWithType>().acceptL(node->assertions);
209                }
210
211                visitType(node->type, ftype);
212
213                auto decl = new FunctionDecl(
214                        node->name,
215                        Type::StorageClasses( node->storage.val ),
216                        LinkageSpec::Spec( node->linkage.val ),
217                        ftype,
218                        //get<FunctionType>().accept1( node->type ),
219                        {},
220                        get<Attribute>().acceptL( node->attributes ),
221                        Type::FuncSpecifiers( node->funcSpec.val )
222                );
223                cache.emplace( node, decl );
224                decl->statements = get<CompoundStmt>().accept1( node->stmts );
225                decl->withExprs = get<Expression>().acceptL( node->withExprs );
226                if ( ast::dereferenceOperator == node ) {
227                        Validate::dereferenceOperator = decl;
228                }
229                if ( ast::dtorStructDestroy == node ) {
230                        Validate::dtorStructDestroy = decl;
231                }
232                return declWithTypePostamble( decl, node );
233        }
234
235        const ast::Decl * namedTypePostamble( NamedTypeDecl * decl, const ast::NamedTypeDecl * node ) {
236                // base comes from constructor
237                decl->assertions = get<DeclarationWithType>().acceptL( node->assertions );
238                declPostamble( decl, node );
239                return nullptr;
240        }
241
242        const ast::Decl * visit( const ast::TypeDecl * node ) override final {
243                if ( inCache( node ) ) return nullptr;
244                auto decl = new TypeDecl(
245                        node->name,
246                        Type::StorageClasses( node->storage.val ),
247                        get<Type>().accept1( node->base ),
248                        (TypeDecl::Kind)(unsigned)node->kind,
249                        node->sized,
250                        get<Type>().accept1( node->init )
251                );
252                cache.emplace( node, decl );
253                return namedTypePostamble( decl, node );
254        }
255
256        const ast::Decl * visit( const ast::TypedefDecl * node ) override final {
257                auto decl = new TypedefDecl(
258                        node->name,
259                        node->location,
260                        Type::StorageClasses( node->storage.val ),
261            get<Type>().accept1( node->base ),
262                        LinkageSpec::Spec( node->linkage.val )
263                );
264                return namedTypePostamble( decl, node );
265        }
266
267        const ast::Decl * aggregatePostamble( AggregateDecl * decl, const ast::AggregateDecl * node ) {
268                cache.emplace( node, decl );
269                decl->members = get<Declaration>().acceptL( node->members );
270                decl->parameters = get<TypeDecl>().acceptL( node->params );
271                decl->body = node->body;
272                // attributes come from constructor
273                decl->parent = get<AggregateDecl>().accept1( node->parent );
274                declPostamble( decl, node );
275                return nullptr;
276        }
277
278        const ast::Decl * visit( const ast::StructDecl * node ) override final {
279                if ( inCache( node ) ) return nullptr;
280                auto decl = new StructDecl(
281                        node->name,
282                        (AggregateDecl::Aggregate)node->kind,
283                        get<Attribute>().acceptL( node->attributes ),
284                        LinkageSpec::Spec( node->linkage.val )
285                );
286
287                if ( ast::dtorStruct == node ) {
288                        Validate::dtorStruct = decl;
289                }
290
291                return aggregatePostamble( decl, node );
292        }
293
294        const ast::Decl * visit( const ast::UnionDecl * node ) override final {
295                if ( inCache( node ) ) return nullptr;
296                auto decl = new UnionDecl(
297                        node->name,
298                        get<Attribute>().acceptL( node->attributes ),
299                        LinkageSpec::Spec( node->linkage.val )
300                );
301                return aggregatePostamble( decl, node );
302        }
303
304        const ast::Decl * visit( const ast::EnumDecl * node ) override final {
305                if ( inCache( node ) ) return nullptr;
306                auto decl = new EnumDecl(
307                        node->name,
308                        get<Attribute>().acceptL( node->attributes ),
309                        LinkageSpec::Spec( node->linkage.val )
310                );
311                return aggregatePostamble( decl, node );
312        }
313
314        const ast::Decl * visit( const ast::TraitDecl * node ) override final {
315                if ( inCache( node ) ) return nullptr;
316                auto decl = new TraitDecl(
317                        node->name,
318                        {},
319                        LinkageSpec::Spec( node->linkage.val )
320                );
321                return aggregatePostamble( decl, node );
322        }
323
324        const ast::AsmDecl * visit( const ast::AsmDecl * node ) override final {
325                auto decl = new AsmDecl( get<AsmStmt>().accept1( node->stmt ) );
326                declPostamble( decl, node );
327                return nullptr;
328        }
329
330        const ast::DirectiveDecl * visit( const ast::DirectiveDecl * node ) override final {
331                auto decl = new DirectiveDecl( get<DirectiveStmt>().accept1( node->stmt ) );
332                declPostamble( decl, node );
333                return nullptr;
334        }
335
336        const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) override final {
337                auto decl = new StaticAssertDecl(
338                        get<Expression>().accept1( node->cond ),
339                        get<ConstantExpr>().accept1( node->msg )
340                );
341                declPostamble( decl, node );
342                return nullptr;
343        }
344
345        const ast::Stmt * stmtPostamble( Statement * stmt, const ast::Stmt * node ) {
346                // force statements in old tree to be unique.
347                // cache.emplace( node, stmt );
348                readonlyCache.emplace( node, stmt );
349                stmt->location = node->location;
350                stmt->labels = makeLabelL( stmt, node->labels );
351                this->node = stmt;
352                return nullptr;
353        }
354
355        const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
356                if ( inCache( node ) ) return nullptr;
357                auto stmt = new CompoundStmt( get<Statement>().acceptL( node->kids ) );
358                stmtPostamble( stmt, node );
359                return nullptr;
360        }
361
362        const ast::Stmt * visit( const ast::ExprStmt * node ) override final {
363                if ( inCache( node ) ) return nullptr;
364                auto stmt = new ExprStmt( nullptr );
365                stmt->expr = get<Expression>().accept1( node->expr );
366                return stmtPostamble( stmt, node );
367        }
368
369        const ast::Stmt * visit( const ast::AsmStmt * node ) override final {
370                if ( inCache( node ) ) return nullptr;
371                auto stmt = new AsmStmt(
372                        node->isVolatile,
373                        get<Expression>().accept1( node->instruction ),
374                        get<Expression>().acceptL( node->output ),
375                        get<Expression>().acceptL( node->input ),
376                        get<ConstantExpr>().acceptL( node->clobber ),
377                        makeLabelL( nullptr, node->gotoLabels ) // What are these labelling?
378                );
379                return stmtPostamble( stmt, node );
380        }
381
382        const ast::Stmt * visit( const ast::DirectiveStmt * node ) override final {
383                if ( inCache( node ) ) return nullptr;
384                auto stmt = new DirectiveStmt( node->directive );
385                return stmtPostamble( stmt, node );
386        }
387
388        const ast::Stmt * visit( const ast::IfStmt * node ) override final {
389                if ( inCache( node ) ) return nullptr;
390                auto stmt = new IfStmt(
391                        get<Expression>().accept1( node->cond ),
392                        get<Statement>().accept1( node->then ),
393                        get<Statement>().accept1( node->else_ ),
394                        get<Statement>().acceptL( node->inits )
395                );
396                return stmtPostamble( stmt, node );
397        }
398
399        const ast::Stmt * visit( const ast::SwitchStmt * node ) override final {
400                if ( inCache( node ) ) return nullptr;
401                auto stmt = new SwitchStmt(
402                        get<Expression>().accept1( node->cond ),
403                        get<Statement>().acceptL( node->stmts )
404                );
405                return stmtPostamble( stmt, node );
406        }
407
408        const ast::Stmt * visit( const ast::CaseStmt * node ) override final {
409                if ( inCache( node ) ) return nullptr;
410                auto stmt = new CaseStmt(
411                        get<Expression>().accept1( node->cond ),
412                        get<Statement>().acceptL( node->stmts ),
413                        node->isDefault()
414                );
415                return stmtPostamble( stmt, node );
416        }
417
418        const ast::Stmt * visit( const ast::WhileDoStmt * node ) override final {
419                if ( inCache( node ) ) return nullptr;
420                auto inits = get<Statement>().acceptL( node->inits );
421                auto stmt = new WhileDoStmt(
422                        get<Expression>().accept1( node->cond ),
423                        get<Statement>().accept1( node->body ),
424                        get<Statement>().accept1( node->else_ ),
425                        inits,
426                        node->isDoWhile
427                );
428                return stmtPostamble( stmt, node );
429        }
430
431        const ast::Stmt * visit( const ast::ForStmt * node ) override final {
432                if ( inCache( node ) ) return nullptr;
433                auto stmt = new ForStmt(
434                        get<Statement>().acceptL( node->inits ),
435                        get<Expression>().accept1( node->cond ),
436                        get<Expression>().accept1( node->inc ),
437                        get<Statement>().accept1( node->body ),
438                        get<Statement>().accept1( node->else_ )
439                );
440                return stmtPostamble( stmt, node );
441        }
442
443        const ast::Stmt * visit( const ast::BranchStmt * node ) override final {
444                if ( inCache( node ) ) return nullptr;
445                BranchStmt * stmt;
446                if (node->computedTarget) {
447                        stmt = new BranchStmt( get<Expression>().accept1( node->computedTarget ),
448                                BranchStmt::Goto );
449                } else {
450                        BranchStmt::Type type;
451                        switch (node->kind) {
452                        #define CASE(n) \
453                        case ast::BranchStmt::n: \
454                                type = BranchStmt::n; \
455                                break
456                        CASE(Goto);
457                        CASE(Break);
458                        CASE(Continue);
459                        CASE(FallThrough);
460                        CASE(FallThroughDefault);
461                        #undef CASE
462                        default:
463                                assertf(false, "Invalid ast::BranchStmt::Kind: %d\n", node->kind);
464                        }
465
466                        // The labels here are also weird.
467                        stmt = new BranchStmt( makeLabel( nullptr, node->originalTarget ), type );
468                        stmt->target = makeLabel( stmt, node->target );
469                }
470                return stmtPostamble( stmt, node );
471        }
472
473        const ast::Stmt * visit( const ast::ReturnStmt * node ) override final {
474                if ( inCache( node ) ) return nullptr;
475                auto stmt = new ReturnStmt( get<Expression>().accept1( node->expr ) );
476                return stmtPostamble( stmt, node );
477        }
478
479        const ast::Stmt * visit( const ast::ThrowStmt * node ) override final {
480                if ( inCache( node ) ) return nullptr;
481                ThrowStmt::Kind kind;
482                switch (node->kind) {
483                case ast::ExceptionKind::Terminate:
484                        kind = ThrowStmt::Terminate;
485                        break;
486                case ast::ExceptionKind::Resume:
487                        kind = ThrowStmt::Resume;
488                        break;
489                default:
490                        assertf(false, "Invalid ast::ThrowStmt::Kind: %d\n", node->kind);
491                }
492                auto stmt = new ThrowStmt(
493                        kind,
494                        get<Expression>().accept1( node->expr ),
495                        get<Expression>().accept1( node->target )
496                );
497                return stmtPostamble( stmt, node );
498        }
499
500        const ast::Stmt * visit( const ast::TryStmt * node ) override final {
501                if ( inCache( node ) ) return nullptr;
502                auto handlers = get<CatchStmt>().acceptL( node->handlers );
503                auto stmt = new TryStmt(
504                        get<CompoundStmt>().accept1( node->body ),
505                        handlers,
506                        get<FinallyStmt>().accept1( node->finally )
507                );
508                return stmtPostamble( stmt, node );
509        }
510
511        const ast::Stmt * visit( const ast::CatchStmt * node ) override final {
512                if ( inCache( node ) ) return nullptr;
513                CatchStmt::Kind kind;
514                switch (node->kind) {
515                case ast::ExceptionKind::Terminate:
516                        kind = CatchStmt::Terminate;
517                        break;
518                case ast::ExceptionKind::Resume:
519                        kind = CatchStmt::Resume;
520                        break;
521                default:
522                        assertf(false, "Invalid ast::CatchStmt::Kind: %d\n", node->kind);
523                }
524                auto stmt = new CatchStmt(
525                        kind,
526                        get<Declaration>().accept1( node->decl ),
527                        get<Expression>().accept1( node->cond ),
528                        get<Statement>().accept1( node->body )
529                );
530                return stmtPostamble( stmt, node );
531        }
532
533        const ast::Stmt * visit( const ast::FinallyStmt * node ) override final {
534                if ( inCache( node ) ) return nullptr;
535                auto stmt = new FinallyStmt( get<CompoundStmt>().accept1( node->body ) );
536                return stmtPostamble( stmt, node );
537        }
538
539        const ast::Stmt * visit(const ast::SuspendStmt * node ) override final {
540                if ( inCache( node ) ) return nullptr;
541                auto stmt = new SuspendStmt();
542                stmt->then   = get<CompoundStmt>().accept1( node->then   );
543                switch(node->type) {
544                        case ast::SuspendStmt::None     : stmt->type = SuspendStmt::None     ; break;
545                        case ast::SuspendStmt::Coroutine: stmt->type = SuspendStmt::Coroutine; break;
546                        case ast::SuspendStmt::Generator: stmt->type = SuspendStmt::Generator; break;
547                }
548                return stmtPostamble( stmt, node );
549        }
550
551        const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
552                if ( inCache( node ) ) return nullptr;
553                auto stmt = new WaitForStmt;
554                stmt->clauses.reserve( node->clauses.size() );
555                for ( auto clause : node->clauses ) {
556                        stmt->clauses.push_back({{
557                                        get<Expression>().accept1( clause.target.func ),
558                                        get<Expression>().acceptL( clause.target.args ),
559                                },
560                                get<Statement>().accept1( clause.stmt ),
561                                get<Expression>().accept1( clause.cond ),
562                        });
563                }
564                stmt->timeout = {
565                        get<Expression>().accept1( node->timeout.time ),
566                        get<Statement>().accept1( node->timeout.stmt ),
567                        get<Expression>().accept1( node->timeout.cond ),
568                };
569                stmt->orelse = {
570                        get<Statement>().accept1( node->orElse.stmt ),
571                        get<Expression>().accept1( node->orElse.cond ),
572                };
573                return stmtPostamble( stmt, node );
574        }
575
576        const ast::Decl * visit( const ast::WithStmt * node ) override final {
577                if ( inCache( node ) ) return nullptr;
578                auto stmt = new WithStmt(
579                        get<Expression>().acceptL( node->exprs ),
580                        get<Statement>().accept1( node->stmt )
581                );
582                declPostamble( stmt, node );
583                return nullptr;
584        }
585
586        const ast::NullStmt * visit( const ast::NullStmt * node ) override final {
587                if ( inCache( node ) ) return nullptr;
588                auto stmt = new NullStmt();
589                stmtPostamble( stmt, node );
590                return nullptr;
591        }
592
593        const ast::Stmt * visit( const ast::DeclStmt * node ) override final {
594                if ( inCache( node ) ) return nullptr;
595                auto stmt = new DeclStmt( get<Declaration>().accept1( node->decl ) );
596                return stmtPostamble( stmt, node );
597        }
598
599        const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) override final {
600                if ( inCache( node ) ) return nullptr;
601                auto stmt = new ImplicitCtorDtorStmt{
602                        get<Statement>().accept1( node->callStmt )
603                };
604                return stmtPostamble( stmt, node );
605        }
606
607        const ast::Stmt * visit( const ast::MutexStmt * node ) override final {
608                if ( inCache( node ) ) return nullptr;
609                 auto stmt = new MutexStmt(
610                        get<Statement>().accept1( node->stmt ),
611                        get<Expression>().acceptL( node->mutexObjs )
612                );
613                return stmtPostamble( stmt, node );
614        }
615
616        TypeSubstitution * convertTypeSubstitution(const ast::TypeSubstitution * src) {
617
618                if (!src) return nullptr;
619
620                TypeSubstitution *rslt = new TypeSubstitution();
621
622                for (decltype(src->begin()) src_i = src->begin(); src_i != src->end(); src_i++) {
623                        rslt->add( src_i->first.typeString(),
624                                   get<Type>().accept1(src_i->second) );
625                }
626
627                return rslt;
628        }
629
630        void convertInferUnion(std::map<UniqueId,ParamEntry> &tgtInferParams,
631                                                   std::vector<UniqueId>         &tgtResnSlots,
632                                                   const ast::Expr::InferUnion   &srcInferred ) {
633
634                assert( tgtInferParams.empty() );
635                assert( tgtResnSlots.empty() );
636
637                if ( srcInferred.data.inferParams ) {
638                        const ast::InferredParams &srcParams = srcInferred.inferParams();
639                        for (auto & srcParam : srcParams) {
640                                auto res = tgtInferParams.emplace(srcParam.first, ParamEntry(
641                                        srcParam.second.decl,
642                                        get<Declaration>().accept1(srcParam.second.declptr),
643                                        get<Type>().accept1(srcParam.second.actualType)->clone(),
644                                        get<Type>().accept1(srcParam.second.formalType)->clone(),
645                                        get<Expression>().accept1(srcParam.second.expr)->clone()
646                                ));
647                                assert(res.second);
648                        }
649                }
650                if ( srcInferred.data.resnSlots ) {
651                        const ast::ResnSlots &srcSlots = srcInferred.resnSlots();
652                        for (auto srcSlot : srcSlots) {
653                                tgtResnSlots.push_back(srcSlot);
654                        }
655                }
656        }
657
658        Expression * visitBaseExpr_skipResultType(const ast::Expr * src, Expression * tgt) {
659
660                tgt->location  = src->location;
661                tgt->env       = convertTypeSubstitution(src->env);
662                tgt->extension = src->extension;
663
664                convertInferUnion(tgt->inferParams, tgt->resnSlots, src->inferred);
665                return tgt;
666        }
667
668        Expression * visitBaseExpr(const ast::Expr * src, Expression * tgt) {
669
670                tgt->result = get<Type>().accept1(src->result);
671                // Unconditionally use a clone of the result type.
672                // We know this will leak some objects: much of the immediate conversion result.
673                // In some cases, using the conversion result directly gives unintended object sharing.
674                // A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache.
675                // But tgt->result must be fully owned privately by tgt.
676                // Applying these conservative copies here means
677                // - weak references point at the declaration's copy, not these expr.result copies (good)
678                // - we copy more objects than really needed (bad, tolerated)
679                if (tgt->result) {
680                        tgt->result = tgt->result->clone();
681                }
682                return visitBaseExpr_skipResultType(src, tgt);
683        }
684
685        const ast::Expr * visit( const ast::ApplicationExpr * node ) override final {
686                auto expr = visitBaseExpr( node,
687                        new ApplicationExpr(
688                                get<Expression>().accept1(node->func),
689                                get<Expression>().acceptL(node->args)
690                        )
691                );
692                this->node = expr;
693                return nullptr;
694        }
695
696        const ast::Expr * visit( const ast::UntypedExpr * node ) override final {
697                auto expr = visitBaseExpr( node,
698                        new UntypedExpr(
699                                get<Expression>().accept1(node->func),
700                                get<Expression>().acceptL(node->args)
701                        )
702                );
703                this->node = expr;
704                return nullptr;
705        }
706
707        const ast::Expr * visit( const ast::NameExpr * node ) override final {
708                auto expr = visitBaseExpr( node,
709                        new NameExpr(
710                                node->name
711                        )
712                );
713                this->node = expr;
714                return nullptr;
715        }
716
717        const ast::Expr * visit( const ast::AddressExpr * node ) override final {
718                auto expr = visitBaseExpr( node,
719                        new AddressExpr(
720                                get<Expression>().accept1(node->arg)
721                        )
722                );
723                this->node = expr;
724                return nullptr;
725        }
726
727        const ast::Expr * visit( const ast::LabelAddressExpr * node ) override final {
728                auto expr = visitBaseExpr( node,
729                        new LabelAddressExpr(
730                                makeLabel(nullptr, node->arg)
731                        )
732                );
733                this->node = expr;
734                return nullptr;
735        }
736
737        const ast::Expr * visit( const ast::CastExpr * node ) override final {
738                auto expr = visitBaseExpr( node,
739                        new CastExpr(
740                                get<Expression>().accept1(node->arg),
741                                (node->isGenerated == ast::GeneratedCast)
742                        )
743                );
744                this->node = expr;
745                return nullptr;
746        }
747
748        const ast::Expr * visit( const ast::KeywordCastExpr * node ) override final {
749                AggregateDecl::Aggregate castTarget = (AggregateDecl::Aggregate)node->target;
750                assert( AggregateDecl::Generator <= castTarget && castTarget <= AggregateDecl::Thread );
751                auto expr = visitBaseExpr( node,
752                        new KeywordCastExpr(
753                                get<Expression>().accept1(node->arg),
754                                castTarget,
755                                {node->concrete_target.field, node->concrete_target.getter}
756                        )
757                );
758                this->node = expr;
759                return nullptr;
760        }
761
762        const ast::Expr * visit( const ast::VirtualCastExpr * node ) override final {
763                auto expr = visitBaseExpr_skipResultType( node,
764                        new VirtualCastExpr(
765                                get<Expression>().accept1(node->arg),
766                                get<Type>().accept1(node->result)
767                        )
768                );
769                this->node = expr;
770                return nullptr;
771        }
772
773        const ast::Expr * visit( const ast::UntypedMemberExpr * node ) override final {
774                auto expr = visitBaseExpr( node,
775                        new UntypedMemberExpr(
776                                get<Expression>().accept1(node->member),
777                                get<Expression>().accept1(node->aggregate)
778                        )
779                );
780                this->node = expr;
781                return nullptr;
782        }
783
784        const ast::Expr * visit( const ast::MemberExpr * node ) override final {
785                auto expr = visitBaseExpr( node,
786                        new MemberExpr(
787                                get<DeclarationWithType>().accept1(node->member),
788                                get<Expression>().accept1(node->aggregate)
789                        )
790                );
791                this->node = expr;
792                return nullptr;
793        }
794
795        const ast::Expr * visit( const ast::VariableExpr * node ) override final {
796                auto expr = new VariableExpr();
797                expr->var = get<DeclarationWithType>().accept1(node->var);
798                visitBaseExpr( node, expr );
799                this->node = expr;
800                return nullptr;
801        }
802
803        const ast::Expr * visit( const ast::ConstantExpr * node ) override final {
804                // Old world:   two types: rslt->constant.type, rslt->result
805                // New workd:   one public type: node->result, plus node->underlyer only to support roundtrip conversion
806                //              preserving underlyer because the correct type for string literals is complicated to construct,
807            //              and distinguishing a string from other literals using the type is hard to do accurately
808                // Both worlds: the outer, expression-level type can change during resolution
809                //              for a string, that's char[k] before-resolve and char * after
810                // Old world:   the inner Constant type stays what it was built with
811                //              for a string, that's char[k] always
812                // Both worlds: the "rep" field of a constant is the C source file fragment that compiles to the desired value
813        //              for a string, that includes outer quotes, backslashes, et al cases from the Literals test
814                ConstantExpr *rslt = new ConstantExpr(Constant(
815                        get<Type>().accept1(node->underlyer),
816                        node->rep,
817                        node->ival));
818                auto expr = visitBaseExpr( node, rslt );
819                this->node = expr;
820                return nullptr;
821        }
822
823        const ast::Expr * visit( const ast::SizeofExpr * node ) override final {
824                assert (node->expr || node->type);
825                assert (! (node->expr && node->type));
826                SizeofExpr *rslt;
827                if (node->expr) {
828                        rslt = new SizeofExpr(
829                                get<Expression>().accept1(node->expr)
830                        );
831                        assert (!rslt->isType);
832                }
833                else {
834                        assert(node->type);
835                        rslt = new SizeofExpr(
836                                get<Type>().accept1(node->type)
837                        );
838                        assert (rslt->isType);
839                }
840                auto expr = visitBaseExpr( node, rslt );
841                this->node = expr;
842                return nullptr;
843        }
844
845        const ast::Expr * visit( const ast::AlignofExpr * node ) override final {
846                assert (node->expr || node->type);
847                assert (! (node->expr && node->type));
848                AlignofExpr *rslt;
849                if (node->expr) {
850                        rslt = new AlignofExpr(
851                                get<Expression>().accept1(node->expr)
852                        );
853                        assert (!rslt->isType);
854                }
855                else {
856                        assert(node->type);
857                        rslt = new AlignofExpr(
858                                get<Type>().accept1(node->type)
859                        );
860                        assert (rslt->isType);
861                }
862                auto expr = visitBaseExpr( node, rslt );
863                this->node = expr;
864                return nullptr;
865        }
866
867        const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) override final {
868                auto expr = visitBaseExpr( node,
869                        new UntypedOffsetofExpr(
870                                get<Type>().accept1(node->type),
871                                node->member
872                        )
873                );
874                this->node = expr;
875                return nullptr;
876        }
877
878        const ast::Expr * visit( const ast::OffsetofExpr * node ) override final {
879                auto expr = visitBaseExpr( node,
880                        new OffsetofExpr(
881                                get<Type>().accept1(node->type),
882                                get<DeclarationWithType>().accept1(node->member)
883                        )
884                );
885                this->node = expr;
886                return nullptr;
887        }
888
889        const ast::Expr * visit( const ast::OffsetPackExpr * node ) override final {
890                auto expr = visitBaseExpr( node,
891                        new OffsetPackExpr(
892                                get<StructInstType>().accept1(node->type)
893                        )
894                );
895                this->node = expr;
896                return nullptr;
897        }
898
899        const ast::Expr * visit( const ast::LogicalExpr * node ) override final {
900                assert (node->isAnd == ast::LogicalFlag::AndExpr ||
901                                node->isAnd == ast::LogicalFlag::OrExpr );
902                auto expr = visitBaseExpr( node,
903                        new LogicalExpr(
904                                get<Expression>().accept1(node->arg1),
905                                get<Expression>().accept1(node->arg2),
906                                (node->isAnd == ast::LogicalFlag::AndExpr)
907                        )
908                );
909                this->node = expr;
910                return nullptr;
911        }
912
913        const ast::Expr * visit( const ast::ConditionalExpr * node ) override final {
914                auto expr = visitBaseExpr( node,
915                        new ConditionalExpr(
916                                get<Expression>().accept1(node->arg1),
917                                get<Expression>().accept1(node->arg2),
918                                get<Expression>().accept1(node->arg3)
919                        )
920                );
921                this->node = expr;
922                return nullptr;
923        }
924
925        const ast::Expr * visit( const ast::CommaExpr * node ) override final {
926                auto expr = visitBaseExpr( node,
927                        new CommaExpr(
928                                get<Expression>().accept1(node->arg1),
929                                get<Expression>().accept1(node->arg2)
930                        )
931                );
932                this->node = expr;
933                return nullptr;
934        }
935
936        const ast::Expr * visit( const ast::TypeExpr * node ) override final {
937                auto expr = visitBaseExpr( node,
938                        new TypeExpr(
939                                get<Type>().accept1(node->type)
940                        )
941                );
942                this->node = expr;
943                return nullptr;
944        }
945
946        const ast::Expr * visit( const ast::AsmExpr * node ) override final {
947                auto expr = visitBaseExpr( node,
948                        new AsmExpr(
949                                new std::string(node->inout),
950                                get<Expression>().accept1(node->constraint),
951                                get<Expression>().accept1(node->operand)
952                        )
953                );
954                this->node = expr;
955                return nullptr;
956        }
957
958        const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) override final {
959                auto rslt = new ImplicitCopyCtorExpr(
960                        get<ApplicationExpr>().accept1(node->callExpr)
961                );
962
963                auto expr = visitBaseExpr( node, rslt );
964                this->node = expr;
965                return nullptr;
966        }
967
968        const ast::Expr * visit( const ast::ConstructorExpr * node ) override final {
969                auto expr = visitBaseExpr( node,
970                        new ConstructorExpr(
971                                get<Expression>().accept1(node->callExpr)
972                        )
973                );
974                this->node = expr;
975                return nullptr;
976        }
977
978        const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) override final {
979                auto expr = visitBaseExpr_skipResultType( node,
980                        new CompoundLiteralExpr(
981                                get<Type>().accept1(node->result),
982                                get<Initializer>().accept1(node->init)
983                        )
984                );
985                this->node = expr;
986                return nullptr;
987        }
988
989        const ast::Expr * visit( const ast::RangeExpr * node ) override final {
990                auto expr = visitBaseExpr( node,
991                        new RangeExpr(
992                                get<Expression>().accept1(node->low),
993                                get<Expression>().accept1(node->high)
994                        )
995                );
996                this->node = expr;
997                return nullptr;
998        }
999
1000        const ast::Expr * visit( const ast::UntypedTupleExpr * node ) override final {
1001                auto expr = visitBaseExpr( node,
1002                        new UntypedTupleExpr(
1003                                get<Expression>().acceptL(node->exprs)
1004                        )
1005                );
1006                this->node = expr;
1007                return nullptr;
1008        }
1009
1010        const ast::Expr * visit( const ast::TupleExpr * node ) override final {
1011                auto expr = visitBaseExpr( node,
1012                        new TupleExpr(
1013                                get<Expression>().acceptL(node->exprs)
1014                        )
1015                );
1016                this->node = expr;
1017                return nullptr;
1018        }
1019
1020        const ast::Expr * visit( const ast::TupleIndexExpr * node ) override final {
1021                auto expr = visitBaseExpr( node,
1022                        new TupleIndexExpr(
1023                                get<Expression>().accept1(node->tuple),
1024                                node->index
1025                        )
1026                );
1027                this->node = expr;
1028                return nullptr;
1029        }
1030
1031        const ast::Expr * visit( const ast::TupleAssignExpr * node ) override final {
1032                auto expr = visitBaseExpr( node,
1033                        new TupleAssignExpr(
1034                                get<StmtExpr>().accept1(node->stmtExpr)
1035                        )
1036                );
1037                this->node = expr;
1038                return nullptr;
1039        }
1040
1041        const ast::Expr * visit( const ast::StmtExpr * node ) override final {
1042                auto rslt = new StmtExpr(
1043                        get<CompoundStmt>().accept1(node->stmts)
1044                );
1045
1046                rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
1047                rslt->dtors       = get<Expression>().acceptL(node->dtors);
1048
1049                // is this even used after convert?
1050                //if (tmp->resultExpr) {
1051                //      // this MUST be found by children visit
1052                //      rslt->resultExpr  = strict_dynamic_cast<ExprStmt *>(readonlyCache.at(tmp->resultExpr));
1053                //}
1054
1055                auto expr = visitBaseExpr( node, rslt );
1056                this->node = expr;
1057                return nullptr;
1058        }
1059
1060        const ast::Expr * visit( const ast::UniqueExpr * node ) override final {
1061                auto rslt = new UniqueExpr(
1062                        get<Expression>().accept1(node->expr),
1063                        node->id
1064                );
1065
1066                rslt->object = get<ObjectDecl>  ().accept1(node->object);
1067                rslt->var    = get<VariableExpr>().accept1(node->var);
1068
1069                auto expr = visitBaseExpr( node, rslt );
1070                this->node = expr->clone();
1071                return nullptr;
1072        }
1073
1074        const ast::Expr * visit( const ast::UntypedInitExpr * node ) override final {
1075                std::list<InitAlternative> initAlts;
1076                for (auto ia : node->initAlts) {
1077                        initAlts.push_back(InitAlternative(
1078                                get<Type>       ().accept1(ia.type),
1079                                get<Designation>().accept1(ia.designation)
1080                        ));
1081                }
1082                auto expr = visitBaseExpr( node,
1083                        new UntypedInitExpr(
1084                                get<Expression>().accept1(node->expr),
1085                                initAlts
1086                        )
1087                );
1088                this->node = expr;
1089                return nullptr;
1090        }
1091
1092        const ast::Expr * visit( const ast::InitExpr * node ) override final {
1093                auto expr = visitBaseExpr( node,
1094                        new InitExpr(
1095                                get<Expression>().accept1(node->expr),
1096                                get<Designation>().accept1(node->designation)
1097                        )
1098                );
1099                this->node = expr;
1100                return nullptr;
1101        }
1102
1103        const ast::Expr * visit( const ast::DeletedExpr * node ) override final {
1104                auto expr = visitBaseExpr( node,
1105                        new DeletedExpr(
1106                                get<Expression>().accept1(node->expr),
1107                                inCache(node->deleteStmt) ?
1108                                        strict_dynamic_cast<Declaration*>(this->node) :
1109                                        get<Declaration>().accept1(node->deleteStmt)
1110                        )
1111                );
1112                this->node = expr;
1113                return nullptr;
1114        }
1115
1116        const ast::Expr * visit( const ast::DefaultArgExpr * node ) override final {
1117                auto expr = visitBaseExpr( node,
1118                        new DefaultArgExpr(
1119                                get<Expression>().accept1(node->expr)
1120                        )
1121                );
1122                this->node = expr;
1123                return nullptr;
1124        }
1125
1126        const ast::Expr * visit( const ast::GenericExpr * node ) override final {
1127                std::list<GenericExpr::Association> associations;
1128                for (auto association : node->associations) {
1129                        associations.push_back(GenericExpr::Association(
1130                                get<Type>      ().accept1(association.type),
1131                                get<Expression>().accept1(association.expr)
1132                        ));
1133                }
1134                auto expr = visitBaseExpr( node,
1135                        new GenericExpr(
1136                                get<Expression>().accept1(node->control),
1137                                associations
1138                        )
1139                );
1140                this->node = expr;
1141                return nullptr;
1142        }
1143
1144        const ast::Type * visitType( const ast::Type * node, Type * type ) {
1145                // Some types do this in their constructor so add a check.
1146                if ( !node->attributes.empty() && type->attributes.empty() ) {
1147                        type->attributes = get<Attribute>().acceptL( node->attributes );
1148                }
1149                this->node = type;
1150                return nullptr;
1151        }
1152
1153        const ast::Type * visit( const ast::VoidType * node ) override final {
1154                return visitType( node, new VoidType{ cv( node ) } );
1155        }
1156
1157        const ast::Type * visit( const ast::BasicType * node ) override final {
1158                auto type = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind };
1159                // I believe this should always be a BasicType.
1160                if ( ast::sizeType == node ) {
1161                        Validate::SizeType = type;
1162                }
1163                return visitType( node, type );
1164        }
1165
1166        const ast::Type * visit( const ast::PointerType * node ) override final {
1167                return visitType( node, new PointerType{
1168                        cv( node ),
1169                        get<Type>().accept1( node->base ),
1170                        get<Expression>().accept1( node->dimension ),
1171                        (bool)node->isVarLen,
1172                        (bool)node->isStatic
1173                } );
1174        }
1175
1176        const ast::Type * visit( const ast::ArrayType * node ) override final {
1177                return visitType( node, new ArrayType{
1178                        cv( node ),
1179                        get<Type>().accept1( node->base ),
1180                        get<Expression>().accept1( node->dimension ),
1181                        (bool)node->isVarLen,
1182                        (bool)node->isStatic
1183                } );
1184        }
1185
1186        const ast::Type * visit( const ast::ReferenceType * node ) override final {
1187                return visitType( node, new ReferenceType{
1188                        cv( node ),
1189                        get<Type>().accept1( node->base )
1190                } );
1191        }
1192
1193        const ast::Type * visit( const ast::QualifiedType * node ) override final {
1194                return visitType( node, new QualifiedType{
1195                        cv( node ),
1196                        get<Type>().accept1( node->parent ),
1197                        get<Type>().accept1( node->child )
1198                } );
1199        }
1200
1201        const ast::Type * visit( const ast::FunctionType * node ) override final {
1202                static std::string dummy_paramvar_prefix = "__param_";
1203                static std::string dummy_returnvar_prefix = "__retval_";
1204
1205                auto ty = new FunctionType {
1206                        cv( node ),
1207                        (bool)node->isVarArgs
1208                };
1209                auto returns = get<Type>().acceptL(node->returns);
1210                auto params = get<Type>().acceptL(node->params);
1211
1212                int ret_index = 0;
1213                for (auto t: returns) {
1214                        // xxx - LinkageSpec shouldn't matter but needs to be something
1215                        ObjectDecl * dummy = new ObjectDecl(dummy_returnvar_prefix + std::to_string(ret_index++), {}, LinkageSpec::C, nullptr, t, nullptr);
1216                        ty->returnVals.push_back(dummy);
1217                }
1218                int param_index = 0;
1219                for (auto t: params) {
1220                        ObjectDecl * dummy = new ObjectDecl(dummy_paramvar_prefix + std::to_string(param_index++), {}, LinkageSpec::C, nullptr, t, nullptr);
1221                        ty->parameters.push_back(dummy);
1222                }
1223
1224                // ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
1225                // ty->parameters = get<DeclarationWithType>().acceptL( node->params );
1226
1227                auto types = get<TypeInstType>().acceptL( node->forall );
1228                for (auto t : types) {
1229                        auto newT = new TypeDecl(*t->baseType);
1230                        newT->name = t->name; // converted by typeString()
1231                        for (auto asst : newT->assertions) delete asst;
1232                        newT->assertions.clear();
1233                        ty->forall.push_back(newT);
1234                }
1235                auto assts = get<VariableExpr>().acceptL( node->assertions );
1236                if (!assts.empty()) {
1237                        assert(!types.empty());
1238                        for (auto asst : assts) {
1239                                auto newDecl = new ObjectDecl(*strict_dynamic_cast<ObjectDecl*>(asst->var));
1240                                delete newDecl->type;
1241                                newDecl->type = asst->result->clone();
1242                                newDecl->storageClasses.is_extern = true; // hack
1243                                ty->forall.back()->assertions.push_back(newDecl);
1244                        }
1245                }
1246
1247                return visitType( node, ty );
1248        }
1249
1250        const ast::Type * postvisit( const ast::BaseInstType * old, ReferenceToType * ty ) {
1251                ty->parameters = get<Expression>().acceptL( old->params );
1252                ty->hoistType = old->hoistType;
1253                return visitType( old, ty );
1254        }
1255
1256        const ast::Type * visit( const ast::StructInstType * node ) override final {
1257                StructInstType * ty;
1258                if ( node->base ) {
1259                        ty = new StructInstType{
1260                                cv( node ),
1261                                get<StructDecl>().accept1( node->base ),
1262                                get<Attribute>().acceptL( node->attributes )
1263                        };
1264                } else {
1265                        ty = new StructInstType{
1266                                cv( node ),
1267                                node->name,
1268                                get<Attribute>().acceptL( node->attributes )
1269                        };
1270                }
1271                return postvisit( node, ty );
1272        }
1273
1274        const ast::Type * visit( const ast::UnionInstType * node ) override final {
1275                UnionInstType * ty;
1276                if ( node->base ) {
1277                        ty = new UnionInstType{
1278                                cv( node ),
1279                                get<UnionDecl>().accept1( node->base ),
1280                                get<Attribute>().acceptL( node->attributes )
1281                        };
1282                } else {
1283                        ty = new UnionInstType{
1284                                cv( node ),
1285                                node->name,
1286                                get<Attribute>().acceptL( node->attributes )
1287                        };
1288                }
1289                return postvisit( node, ty );
1290        }
1291
1292        const ast::Type * visit( const ast::EnumInstType * node ) override final {
1293                EnumInstType * ty;
1294                if ( node->base ) {
1295                        ty = new EnumInstType{
1296                                cv( node ),
1297                                get<EnumDecl>().accept1( node->base ),
1298                                get<Attribute>().acceptL( node->attributes )
1299                        };
1300                } else {
1301                        ty = new EnumInstType{
1302                                cv( node ),
1303                                node->name,
1304                                get<Attribute>().acceptL( node->attributes )
1305                        };
1306                }
1307                return postvisit( node, ty );
1308        }
1309
1310        const ast::Type * visit( const ast::TraitInstType * node ) override final {
1311                TraitInstType * ty;
1312                if ( node->base ) {
1313                        ty = new TraitInstType{
1314                                cv( node ),
1315                                get<TraitDecl>().accept1( node->base ),
1316                                get<Attribute>().acceptL( node->attributes )
1317                        };
1318                } else {
1319                        ty = new TraitInstType{
1320                                cv( node ),
1321                                node->name,
1322                                get<Attribute>().acceptL( node->attributes )
1323                        };
1324                }
1325                return postvisit( node, ty );
1326        }
1327
1328        const ast::Type * visit( const ast::TypeInstType * node ) override final {
1329                TypeInstType * ty;
1330                if ( node->base ) {
1331                        ty = new TypeInstType{
1332                                cv( node ),
1333                                node->typeString(),
1334                                get<TypeDecl>().accept1( node->base ),
1335                                get<Attribute>().acceptL( node->attributes )
1336                        };
1337                } else {
1338                        ty = new TypeInstType{
1339                                cv( node ),
1340                                node->typeString(),
1341                                node->kind == ast::TypeDecl::Ftype,
1342                                get<Attribute>().acceptL( node->attributes )
1343                        };
1344                }
1345                return postvisit( node, ty );
1346        }
1347
1348        const ast::Type * visit( const ast::TupleType * node ) override final {
1349                return visitType( node, new TupleType{
1350                        cv( node ),
1351                        get<Type>().acceptL( node->types )
1352                        // members generated by TupleType c'tor
1353                } );
1354        }
1355
1356        const ast::Type * visit( const ast::TypeofType * node ) override final {
1357                return visitType( node, new TypeofType{
1358                        cv( node ),
1359                        get<Expression>().accept1( node->expr ),
1360                        (bool)node->kind
1361                } );
1362        }
1363
1364        const ast::Type * visit( const ast::VTableType * node ) override final {
1365                return visitType( node, new VTableType{
1366                        cv( node ),
1367                        get<Type>().accept1( node->base )
1368                } );
1369        }
1370
1371        const ast::Type * visit( const ast::VarArgsType * node ) override final {
1372                return visitType( node, new VarArgsType{ cv( node ) } );
1373        }
1374
1375        const ast::Type * visit( const ast::ZeroType * node ) override final {
1376                return visitType( node, new ZeroType{ cv( node ) } );
1377        }
1378
1379        const ast::Type * visit( const ast::OneType * node ) override final {
1380                return visitType( node, new OneType{ cv( node ) } );
1381        }
1382
1383        const ast::Type * visit( const ast::GlobalScopeType * node ) override final {
1384                return visitType( node, new GlobalScopeType{} );
1385        }
1386
1387        const ast::Designation * visit( const ast::Designation * node ) override final {
1388                auto designation = new Designation( get<Expression>().acceptL( node->designators ) );
1389                designation->location = node->location;
1390                this->node = designation;
1391                return nullptr;
1392        }
1393
1394        const ast::Init * visit( const ast::SingleInit * node ) override final {
1395                auto init = new SingleInit(
1396                        get<Expression>().accept1( node->value ),
1397                        ast::MaybeConstruct == node->maybeConstructed
1398                );
1399                init->location = node->location;
1400                this->node = init;
1401                return nullptr;
1402        }
1403
1404        const ast::Init * visit( const ast::ListInit * node ) override final {
1405                auto init = new ListInit(
1406                        get<Initializer>().acceptL( node->initializers ),
1407                        get<Designation>().acceptL( node->designations ),
1408                        ast::MaybeConstruct == node->maybeConstructed
1409                );
1410                init->location = node->location;
1411                this->node = init;
1412                return nullptr;
1413        }
1414
1415        const ast::Init * visit( const ast::ConstructorInit * node ) override final {
1416                auto init = new ConstructorInit(
1417                        get<Statement>().accept1( node->ctor ),
1418                        get<Statement>().accept1( node->dtor ),
1419                        get<Initializer>().accept1( node->init )
1420                );
1421                init->location = node->location;
1422                this->node = init;
1423                return nullptr;
1424        }
1425
1426        const ast::Attribute * visit( const ast::Attribute * node ) override final {
1427                auto attr = new Attribute(
1428                        node->name,
1429                        get<Expression>().acceptL(node->params)
1430                );
1431                this->node = attr;
1432                return nullptr;
1433        }
1434
1435        const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) override final {
1436                // Handled by convertTypeSubstitution helper instead.
1437                // TypeSubstitution is not a node in the old model, so the conversion result wouldn't fit in this->node.
1438                assert( 0 );
1439                (void)node;
1440                return nullptr;
1441        }
1442};
1443
1444std::list< Declaration * > convert( const ast::TranslationUnit && translationUnit ) {
1445        // Copy values from the global store to the local static variables.
1446        ast::sizeType = translationUnit.global.sizeType;
1447        ast::dereferenceOperator = translationUnit.global.dereference;
1448        ast::dtorStruct = translationUnit.global.dtorStruct;
1449        ast::dtorStructDestroy = translationUnit.global.dtorDestroy;
1450
1451        ConverterNewToOld c;
1452        std::list< Declaration * > decls;
1453        for(auto d : translationUnit.decls) {
1454                decls.emplace_back( c.decl( d ) );
1455        }
1456        return decls;
1457}
1458
1459//================================================================================================
1460
1461class ConverterOldToNew : public Visitor {
1462public:
1463        ast::Decl * decl() {
1464                return strict_dynamic_cast< ast::Decl * >( node );
1465        }
1466
1467        ConverterOldToNew() = default;
1468        ConverterOldToNew(const ConverterOldToNew &) = delete;
1469        ConverterOldToNew(ConverterOldToNew &&) = delete;
1470private:
1471        /// conversion output
1472        ast::Node * node = nullptr;
1473        /// cache of nodes that might be referenced by readonly<> for de-duplication
1474        /// in case that some nodes are dropped by conversion (due to possible structural change)
1475        /// use smart pointers in cache value to prevent accidental invalidation.
1476        /// at conversion stage, all created nodes are guaranteed to be unique, therefore
1477        /// const_casting out of smart pointers is permitted.
1478        std::unordered_map< const BaseSyntaxNode *, ast::readonly<ast::Node> > cache = {};
1479
1480        // Local Utilities:
1481
1482        template<typename NewT, typename OldT>
1483        NewT * getAccept1( OldT old ) {
1484                if ( ! old ) return nullptr;
1485                old->accept(*this);
1486                ast::Node * ret = node;
1487                node = nullptr;
1488                return strict_dynamic_cast< NewT * >( ret );
1489        }
1490
1491#       define GET_ACCEPT_1(child, type) \
1492                getAccept1< ast::type, decltype( old->child ) >( old->child )
1493
1494        template<typename NewT, typename OldC>
1495        std::vector< ast::ptr<NewT> > getAcceptV( const OldC& old ) {
1496                std::vector< ast::ptr<NewT> > ret;
1497                ret.reserve( old.size() );
1498                for ( auto a : old ) {
1499                        a->accept( *this );
1500                        ret.emplace_back( strict_dynamic_cast< NewT * >(node) );
1501                        node = nullptr;
1502                }
1503                return ret;
1504        }
1505
1506#       define GET_ACCEPT_V(child, type) \
1507                getAcceptV< ast::type, decltype( old->child ) >( old->child )
1508
1509        template<typename NewT, typename OldC>
1510        std::deque< ast::ptr<NewT> > getAcceptD( const OldC& old ) {
1511                std::deque< ast::ptr<NewT> > ret;
1512                for ( auto a : old ) {
1513                        a->accept( *this );
1514                        ret.emplace_back( strict_dynamic_cast< NewT * >(node) );
1515                        node = nullptr;
1516                }
1517                return ret;
1518        }
1519
1520#       define GET_ACCEPT_D(child, type) \
1521                getAcceptD< ast::type, decltype( old->child ) >( old->child )
1522
1523        ast::Label make_label(const Label* old) {
1524                CodeLocation const & location =
1525                    ( old->labelled ) ? old->labelled->location : CodeLocation();
1526                return ast::Label(
1527                        location,
1528                        old->name,
1529                        GET_ACCEPT_V(attributes, Attribute)
1530                );
1531        }
1532
1533        template<template <class...> class C>
1534        C<ast::Label> make_labels(C<Label> olds) {
1535                C<ast::Label> ret;
1536                for (auto oldn : olds) {
1537                        ret.push_back( make_label( &oldn ) );
1538                }
1539                return ret;
1540        }
1541
1542#       define GET_LABELS_V(labels) \
1543                to<std::vector>::from( make_labels( std::move( labels ) ) )
1544
1545        static ast::CV::Qualifiers cv( const Type * ty ) { return { ty->tq.val }; }
1546
1547        /// returns true and sets `node` if in cache
1548        bool inCache( const BaseSyntaxNode * old ) {
1549                auto it = cache.find( old );
1550                if ( it == cache.end() ) return false;
1551                node = const_cast<ast::Node *>(it->second.get());
1552                return true;
1553        }
1554
1555        // Now all the visit functions:
1556
1557        virtual void visit( const ObjectDecl * old ) override final {
1558                auto&& type = GET_ACCEPT_1(type, Type);
1559                auto&& init = GET_ACCEPT_1(init, Init);
1560                auto&& bfwd = GET_ACCEPT_1(bitfieldWidth, Expr);
1561                auto&& attr = GET_ACCEPT_V(attributes, Attribute);
1562                if ( inCache( old ) ) {
1563                        return;
1564                }
1565                auto decl = new ast::ObjectDecl(
1566                        old->location,
1567                        old->name,
1568                        type,
1569                        init,
1570                        { old->get_storageClasses().val },
1571                        { old->linkage.val },
1572                        bfwd,
1573                        std::move(attr),
1574                        { old->get_funcSpec().val }
1575                );
1576                cache.emplace(old, decl);
1577                assert(cache.find( old ) != cache.end());
1578                decl->scopeLevel = old->scopeLevel;
1579                decl->mangleName = old->mangleName;
1580                decl->isDeleted  = old->isDeleted;
1581                decl->asmName    = GET_ACCEPT_1(asmName, Expr);
1582                decl->uniqueId   = old->uniqueId;
1583                decl->extension  = old->extension;
1584
1585                this->node = decl;
1586        }
1587
1588        virtual void visit( const FunctionDecl * old ) override final {
1589                if ( inCache( old ) ) return;
1590                auto paramVars = GET_ACCEPT_V(type->parameters, DeclWithType);
1591                auto returnVars = GET_ACCEPT_V(type->returnVals, DeclWithType);
1592                auto forall = GET_ACCEPT_V(type->forall, TypeDecl);
1593
1594                // function type is now derived from parameter decls instead of storing them
1595
1596                /*
1597                auto ftype = new ast::FunctionType((ast::ArgumentFlag)old->type->isVarArgs, cv(old->type));
1598                ftype->params.reserve(paramVars.size());
1599                ftype->returns.reserve(returnVars.size());
1600
1601                for (auto & v: paramVars) {
1602                        ftype->params.emplace_back(v->get_type());
1603                }
1604                for (auto & v: returnVars) {
1605                        ftype->returns.emplace_back(v->get_type());
1606                }
1607                ftype->forall = std::move(forall);
1608                */
1609
1610                // can function type have attributes? seems not to be the case.
1611                // visitType(old->type, ftype);
1612
1613                // collect assertions and put directly in FunctionDecl
1614                std::vector<ast::ptr<ast::DeclWithType>> assertions;
1615                for (auto & param: forall) {
1616                        for (auto & asst: param->assertions) {
1617                                assertf(asst->unique(), "newly converted decl must be unique");
1618                                assertions.emplace_back(asst);
1619                        }
1620                        auto mut = param.get_and_mutate();
1621                        assertf(mut == param, "newly converted decl must be unique");
1622                        mut->assertions.clear();
1623                }
1624
1625                auto decl = new ast::FunctionDecl{
1626                        old->location,
1627                        old->name,
1628                        // GET_ACCEPT_1(type, FunctionType),
1629                        std::move(forall),
1630                        std::move(paramVars),
1631                        std::move(returnVars),
1632                        {},
1633                        { old->storageClasses.val },
1634                        { old->linkage.val },
1635                        GET_ACCEPT_V(attributes, Attribute),
1636                        { old->get_funcSpec().val },
1637                        old->type->isVarArgs
1638                };
1639
1640                // decl->type = ftype;
1641                cache.emplace( old, decl );
1642
1643                decl->assertions = std::move(assertions);
1644                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
1645                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
1646                decl->scopeLevel = old->scopeLevel;
1647                decl->mangleName = old->mangleName;
1648                decl->isDeleted  = old->isDeleted;
1649                decl->asmName    = GET_ACCEPT_1(asmName, Expr);
1650                decl->uniqueId   = old->uniqueId;
1651                decl->extension  = old->extension;
1652
1653                this->node = decl;
1654
1655                if ( Validate::dereferenceOperator == old ) {
1656                        ast::dereferenceOperator = decl;
1657                }
1658
1659                if ( Validate::dtorStructDestroy == old ) {
1660                        ast::dtorStructDestroy = decl;
1661                }
1662        }
1663
1664        virtual void visit( const StructDecl * old ) override final {
1665                if ( inCache( old ) ) return;
1666                auto decl = new ast::StructDecl(
1667                        old->location,
1668                        old->name,
1669                        (ast::AggregateDecl::Aggregate)old->kind,
1670                        GET_ACCEPT_V(attributes, Attribute),
1671                        { old->linkage.val }
1672                );
1673                cache.emplace( old, decl );
1674                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
1675                decl->body   = old->body;
1676                decl->params = GET_ACCEPT_V(parameters, TypeDecl);
1677                decl->members    = GET_ACCEPT_V(members, Decl);
1678                decl->extension  = old->extension;
1679                decl->uniqueId   = old->uniqueId;
1680                decl->storage    = { old->storageClasses.val };
1681
1682                this->node = decl;
1683
1684                if ( Validate::dtorStruct == old ) {
1685                        ast::dtorStruct = decl;
1686                }
1687        }
1688
1689        virtual void visit( const UnionDecl * old ) override final {
1690                if ( inCache( old ) ) return;
1691                auto decl = new ast::UnionDecl(
1692                        old->location,
1693                        old->name,
1694                        GET_ACCEPT_V(attributes, Attribute),
1695                        { old->linkage.val }
1696                );
1697                cache.emplace( old, decl );
1698                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
1699                decl->body   = old->body;
1700                decl->params = GET_ACCEPT_V(parameters, TypeDecl);
1701                decl->members    = GET_ACCEPT_V(members, Decl);
1702                decl->extension  = old->extension;
1703                decl->uniqueId   = old->uniqueId;
1704                decl->storage    = { old->storageClasses.val };
1705
1706                this->node = decl;
1707        }
1708
1709        virtual void visit( const EnumDecl * old ) override final {
1710                if ( inCache( old ) ) return;
1711                auto decl = new ast::EnumDecl(
1712                        old->location,
1713                        old->name,
1714                        GET_ACCEPT_V(attributes, Attribute),
1715                        { old->linkage.val }
1716                );
1717                cache.emplace( old, decl );
1718                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
1719                decl->body   = old->body;
1720                decl->params = GET_ACCEPT_V(parameters, TypeDecl);
1721                decl->members    = GET_ACCEPT_V(members, Decl);
1722                decl->extension  = old->extension;
1723                decl->uniqueId   = old->uniqueId;
1724                decl->storage    = { old->storageClasses.val };
1725
1726                this->node = decl;
1727        }
1728
1729        virtual void visit( const TraitDecl * old ) override final {
1730                if ( inCache( old ) ) return;
1731                auto decl = new ast::TraitDecl(
1732                        old->location,
1733                        old->name,
1734                        GET_ACCEPT_V(attributes, Attribute),
1735                        { old->linkage.val }
1736                );
1737                cache.emplace( old, decl );
1738                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
1739                decl->body   = old->body;
1740                decl->params = GET_ACCEPT_V(parameters, TypeDecl);
1741                decl->members    = GET_ACCEPT_V(members, Decl);
1742                decl->extension  = old->extension;
1743                decl->uniqueId   = old->uniqueId;
1744                decl->storage    = { old->storageClasses.val };
1745
1746                this->node = decl;
1747        }
1748
1749        virtual void visit( const TypeDecl * old ) override final {
1750                if ( inCache( old ) ) return;
1751                auto decl = new ast::TypeDecl{
1752                        old->location,
1753                        old->name,
1754                        { old->storageClasses.val },
1755                        GET_ACCEPT_1(base, Type),
1756                        (ast::TypeDecl::Kind)(unsigned)old->kind,
1757                        old->sized,
1758                        GET_ACCEPT_1(init, Type)
1759                };
1760                cache.emplace( old, decl );
1761                decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
1762                decl->extension  = old->extension;
1763                decl->uniqueId   = old->uniqueId;
1764
1765                this->node = decl;
1766        }
1767
1768        virtual void visit( const TypedefDecl * old ) override final {
1769                auto decl = new ast::TypedefDecl(
1770                        old->location,
1771                        old->name,
1772                        { old->storageClasses.val },
1773                        GET_ACCEPT_1(base, Type),
1774                        { old->linkage.val }
1775                );
1776                decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
1777                decl->extension  = old->extension;
1778                decl->uniqueId   = old->uniqueId;
1779                decl->storage    = { old->storageClasses.val };
1780
1781                this->node = decl;
1782        }
1783
1784        virtual void visit( const AsmDecl * old ) override final {
1785                auto decl = new ast::AsmDecl{
1786                        old->location,
1787                        GET_ACCEPT_1(stmt, AsmStmt)
1788                };
1789                decl->extension  = old->extension;
1790                decl->uniqueId   = old->uniqueId;
1791                decl->storage    = { old->storageClasses.val };
1792
1793                this->node = decl;
1794        }
1795
1796        virtual void visit( const DirectiveDecl * old ) override final {
1797                auto decl = new ast::DirectiveDecl{
1798                        old->location,
1799                        GET_ACCEPT_1(stmt, DirectiveStmt)
1800                };
1801                decl->extension  = old->extension;
1802                decl->uniqueId   = old->uniqueId;
1803                decl->storage    = { old->storageClasses.val };
1804
1805                this->node = decl;
1806        }
1807
1808        virtual void visit( const StaticAssertDecl * old ) override final {
1809                auto decl = new ast::StaticAssertDecl{
1810                        old->location,
1811                        GET_ACCEPT_1(condition, Expr),
1812                        GET_ACCEPT_1(message, ConstantExpr)
1813                };
1814                decl->extension  = old->extension;
1815                decl->uniqueId   = old->uniqueId;
1816                decl->storage    = { old->storageClasses.val };
1817
1818                this->node = decl;
1819        }
1820
1821        virtual void visit( const CompoundStmt * old ) override final {
1822                if ( inCache( old ) ) return;
1823                auto stmt = new ast::CompoundStmt(
1824                        old->location,
1825                        to<std::list>::from( GET_ACCEPT_V(kids, Stmt) ),
1826                        GET_LABELS_V(old->labels)
1827                );
1828
1829                this->node = stmt;
1830                cache.emplace( old, this->node );
1831        }
1832
1833        virtual void visit( const ExprStmt * old ) override final {
1834                if ( inCache( old ) ) return;
1835                this->node = new ast::ExprStmt(
1836                        old->location,
1837                        GET_ACCEPT_1(expr, Expr),
1838                        GET_LABELS_V(old->labels)
1839                );
1840                cache.emplace( old, this->node );
1841        }
1842
1843        virtual void visit( const AsmStmt * old ) override final {
1844                if ( inCache( old ) ) return;
1845                this->node = new ast::AsmStmt(
1846                        old->location,
1847                        old->voltile,
1848                        GET_ACCEPT_1(instruction, Expr),
1849                        GET_ACCEPT_V(output, Expr),
1850                        GET_ACCEPT_V(input, Expr),
1851                        GET_ACCEPT_V(clobber, ConstantExpr),
1852                        GET_LABELS_V(old->gotolabels),
1853                        GET_LABELS_V(old->labels)
1854                );
1855                cache.emplace( old, this->node );
1856        }
1857
1858        virtual void visit( const DirectiveStmt * old ) override final {
1859                if ( inCache( old ) ) return;
1860                this->node = new ast::DirectiveStmt(
1861                        old->location,
1862                        old->directive,
1863                        GET_LABELS_V(old->labels)
1864                );
1865                cache.emplace( old, this->node );
1866        }
1867
1868        virtual void visit( const IfStmt * old ) override final {
1869                if ( inCache( old ) ) return;
1870                this->node = new ast::IfStmt(
1871                        old->location,
1872                        GET_ACCEPT_1(condition, Expr),
1873                        GET_ACCEPT_1(then, Stmt),
1874                        GET_ACCEPT_1(else_, Stmt),
1875                        GET_ACCEPT_V(initialization, Stmt),
1876                        GET_LABELS_V(old->labels)
1877                );
1878                cache.emplace( old, this->node );
1879        }
1880
1881        virtual void visit( const SwitchStmt * old ) override final {
1882                if ( inCache( old ) ) return;
1883                this->node = new ast::SwitchStmt(
1884                        old->location,
1885                        GET_ACCEPT_1(condition, Expr),
1886                        GET_ACCEPT_V(statements, Stmt),
1887                        GET_LABELS_V(old->labels)
1888                );
1889                cache.emplace( old, this->node );
1890        }
1891
1892        virtual void visit( const CaseStmt * old ) override final {
1893                if ( inCache( old ) ) return;
1894                this->node = new ast::CaseStmt(
1895                        old->location,
1896                        GET_ACCEPT_1(condition, Expr),
1897                        GET_ACCEPT_V(stmts, Stmt),
1898                        GET_LABELS_V(old->labels)
1899                );
1900                cache.emplace( old, this->node );
1901        }
1902
1903        virtual void visit( const WhileDoStmt * old ) override final {
1904                if ( inCache( old ) ) return;
1905                this->node = new ast::WhileDoStmt(
1906                        old->location,
1907                        GET_ACCEPT_1(condition, Expr),
1908                        GET_ACCEPT_1(body, Stmt),
1909                        GET_ACCEPT_1(else_, Stmt),
1910                        GET_ACCEPT_V(initialization, Stmt),
1911                        old->isDoWhile,
1912                        GET_LABELS_V(old->labels)
1913                );
1914                cache.emplace( old, this->node );
1915        }
1916
1917        virtual void visit( const ForStmt * old ) override final {
1918                if ( inCache( old ) ) return;
1919                this->node = new ast::ForStmt(
1920                        old->location,
1921                        GET_ACCEPT_V(initialization, Stmt),
1922                        GET_ACCEPT_1(condition, Expr),
1923                        GET_ACCEPT_1(increment, Expr),
1924                        GET_ACCEPT_1(body, Stmt),
1925                        GET_ACCEPT_1(else_, Stmt),
1926                        GET_LABELS_V(old->labels)
1927                );
1928                cache.emplace( old, this->node );
1929        }
1930
1931        virtual void visit( const BranchStmt * old ) override final {
1932                if ( inCache( old ) ) return;
1933                if (old->computedTarget) {
1934                        this->node = new ast::BranchStmt(
1935                                old->location,
1936                                GET_ACCEPT_1(computedTarget, Expr),
1937                                GET_LABELS_V(old->labels)
1938                        );
1939                } else {
1940                        ast::BranchStmt::Kind kind;
1941                        switch (old->type) {
1942                        #define CASE(n) \
1943                        case BranchStmt::n: \
1944                                kind = ast::BranchStmt::n; \
1945                                break
1946                        CASE(Goto);
1947                        CASE(Break);
1948                        CASE(Continue);
1949                        CASE(FallThrough);
1950                        CASE(FallThroughDefault);
1951                        #undef CASE
1952                        default:
1953                                assertf(false, "Invalid BranchStmt::Type %d\n", old->type);
1954                        }
1955
1956                        auto stmt = new ast::BranchStmt(
1957                                old->location,
1958                                kind,
1959                                make_label(&old->originalTarget),
1960                                GET_LABELS_V(old->labels)
1961                        );
1962                        stmt->target = make_label(&old->target);
1963                        this->node = stmt;
1964                }
1965                cache.emplace( old, this->node );
1966        }
1967
1968        virtual void visit( const ReturnStmt * old ) override final {
1969                if ( inCache( old ) ) return;
1970                this->node = new ast::ReturnStmt(
1971                        old->location,
1972                        GET_ACCEPT_1(expr, Expr),
1973                        GET_LABELS_V(old->labels)
1974                );
1975                cache.emplace( old, this->node );
1976        }
1977
1978        virtual void visit( const ThrowStmt * old ) override final {
1979                if ( inCache( old ) ) return;
1980                ast::ExceptionKind kind;
1981                switch (old->kind) {
1982                case ThrowStmt::Terminate:
1983                        kind = ast::ExceptionKind::Terminate;
1984                        break;
1985                case ThrowStmt::Resume:
1986                        kind = ast::ExceptionKind::Resume;
1987                        break;
1988                default:
1989                        assertf(false, "Invalid ThrowStmt::Kind %d\n", old->kind);
1990                }
1991
1992                this->node = new ast::ThrowStmt(
1993                        old->location,
1994                        kind,
1995                        GET_ACCEPT_1(expr, Expr),
1996                        GET_ACCEPT_1(target, Expr),
1997                        GET_LABELS_V(old->labels)
1998                );
1999                cache.emplace( old, this->node );
2000        }
2001
2002        virtual void visit( const TryStmt * old ) override final {
2003                if ( inCache( old ) ) return;
2004                this->node = new ast::TryStmt(
2005                        old->location,
2006                        GET_ACCEPT_1(block, CompoundStmt),
2007                        GET_ACCEPT_V(handlers, CatchStmt),
2008                        GET_ACCEPT_1(finallyBlock, FinallyStmt),
2009                        GET_LABELS_V(old->labels)
2010                );
2011                cache.emplace( old, this->node );
2012        }
2013
2014        virtual void visit( const CatchStmt * old ) override final {
2015                if ( inCache( old ) ) return;
2016                ast::ExceptionKind kind;
2017                switch (old->kind) {
2018                case CatchStmt::Terminate:
2019                        kind = ast::ExceptionKind::Terminate;
2020                        break;
2021                case CatchStmt::Resume:
2022                        kind = ast::ExceptionKind::Resume;
2023                        break;
2024                default:
2025                        assertf(false, "Invalid CatchStmt::Kind %d\n", old->kind);
2026                }
2027
2028                this->node = new ast::CatchStmt(
2029                        old->location,
2030                        kind,
2031                        GET_ACCEPT_1(decl, Decl),
2032                        GET_ACCEPT_1(cond, Expr),
2033                        GET_ACCEPT_1(body, Stmt),
2034                        GET_LABELS_V(old->labels)
2035                );
2036                cache.emplace( old, this->node );
2037        }
2038
2039        virtual void visit( const FinallyStmt * old ) override final {
2040                if ( inCache( old ) ) return;
2041                this->node = new ast::FinallyStmt(
2042                        old->location,
2043                        GET_ACCEPT_1(block, CompoundStmt),
2044                        GET_LABELS_V(old->labels)
2045                );
2046                cache.emplace( old, this->node );
2047        }
2048
2049        virtual void visit( const SuspendStmt * old ) override final {
2050                if ( inCache( old ) ) return;
2051                ast::SuspendStmt::Type type;
2052                switch (old->type) {
2053                        case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break;
2054                        case SuspendStmt::Generator: type = ast::SuspendStmt::Generator; break;
2055                        case SuspendStmt::None     : type = ast::SuspendStmt::None     ; break;
2056                        default: abort();
2057                }
2058                this->node = new ast::SuspendStmt(
2059                        old->location,
2060                        GET_ACCEPT_1(then  , CompoundStmt),
2061                        type,
2062                        GET_LABELS_V(old->labels)
2063                );
2064                cache.emplace( old, this->node );
2065        }
2066
2067        virtual void visit( const WaitForStmt * old ) override final {
2068                if ( inCache( old ) ) return;
2069                ast::WaitForStmt * stmt = new ast::WaitForStmt(
2070                        old->location,
2071                        GET_LABELS_V(old->labels)
2072                );
2073
2074                stmt->clauses.reserve( old->clauses.size() );
2075                for (size_t i = 0 ; i < old->clauses.size() ; ++i) {
2076                        stmt->clauses.push_back({
2077                                ast::WaitForStmt::Target{
2078                                        GET_ACCEPT_1(clauses[i].target.function, Expr),
2079                                        GET_ACCEPT_V(clauses[i].target.arguments, Expr)
2080                                },
2081                                GET_ACCEPT_1(clauses[i].statement, Stmt),
2082                                GET_ACCEPT_1(clauses[i].condition, Expr)
2083                        });
2084                }
2085                stmt->timeout = {
2086                        GET_ACCEPT_1(timeout.time, Expr),
2087                        GET_ACCEPT_1(timeout.statement, Stmt),
2088                        GET_ACCEPT_1(timeout.condition, Expr),
2089                };
2090                stmt->orElse = {
2091                        GET_ACCEPT_1(orelse.statement, Stmt),
2092                        GET_ACCEPT_1(orelse.condition, Expr),
2093                };
2094
2095                this->node = stmt;
2096                cache.emplace( old, this->node );
2097        }
2098
2099        virtual void visit( const WithStmt * old ) override final {
2100                if ( inCache( old ) ) return;
2101                this->node = new ast::WithStmt(
2102                        old->location,
2103                        GET_ACCEPT_V(exprs, Expr),
2104                        GET_ACCEPT_1(stmt, Stmt)
2105                );
2106                cache.emplace( old, this->node );
2107        }
2108
2109        virtual void visit( const NullStmt * old ) override final {
2110                if ( inCache( old ) ) return;
2111                this->node = new ast::NullStmt(
2112                        old->location,
2113                        GET_LABELS_V(old->labels)
2114                );
2115                cache.emplace( old, this->node );
2116        }
2117
2118        virtual void visit( const DeclStmt * old ) override final {
2119                if ( inCache( old ) ) return;
2120                this->node = new ast::DeclStmt(
2121                        old->location,
2122                        GET_ACCEPT_1(decl, Decl),
2123                        GET_LABELS_V(old->labels)
2124                );
2125                cache.emplace( old, this->node );
2126        }
2127
2128        virtual void visit( const ImplicitCtorDtorStmt * old ) override final {
2129                if ( inCache( old ) ) return;
2130                auto stmt = new ast::ImplicitCtorDtorStmt(
2131                        old->location,
2132                        nullptr,
2133                        GET_LABELS_V(old->labels)
2134                );
2135                cache.emplace( old, stmt );
2136                stmt->callStmt = GET_ACCEPT_1(callStmt, Stmt);
2137                this->node = stmt;
2138        }
2139
2140        virtual void visit( const MutexStmt * old ) override final {
2141                if ( inCache( old ) ) return;
2142                this->node = new ast::MutexStmt(
2143                        old->location,
2144                        GET_ACCEPT_1(stmt, Stmt),
2145                        GET_ACCEPT_V(mutexObjs, Expr)
2146                );
2147                cache.emplace( old, this->node );
2148        }
2149
2150        // TypeSubstitution shouldn't exist yet in old.
2151        ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) {
2152               
2153                if (!old) return nullptr;
2154                if (old->empty()) return nullptr;
2155                assert(false);
2156
2157                /*
2158                ast::TypeSubstitution *rslt = new ast::TypeSubstitution();
2159
2160                for (decltype(old->begin()) old_i = old->begin(); old_i != old->end(); old_i++) {
2161                        rslt->add( old_i->first,
2162                                   getAccept1<ast::Type>(old_i->second) );
2163                }
2164
2165                return rslt;
2166                */
2167        }
2168
2169        void convertInferUnion(ast::Expr::InferUnion               &newInferred,
2170                                                   const std::map<UniqueId,ParamEntry> &oldInferParams,
2171                                                   const std::vector<UniqueId>         &oldResnSlots) {
2172
2173                assert( oldInferParams.empty() || oldResnSlots.empty() );
2174                // assert( newInferred.mode == ast::Expr::InferUnion::Empty );
2175
2176                if ( !oldInferParams.empty() ) {
2177                        ast::InferredParams &tgt = newInferred.inferParams();
2178                        for (auto & old : oldInferParams) {
2179                                tgt[old.first] = ast::ParamEntry(
2180                                        old.second.decl,
2181                                        getAccept1<ast::Decl>(old.second.declptr),
2182                                        getAccept1<ast::Type>(old.second.actualType),
2183                                        getAccept1<ast::Type>(old.second.formalType),
2184                                        getAccept1<ast::Expr>(old.second.expr)
2185                                );
2186                        }
2187                } else if ( !oldResnSlots.empty() ) {
2188                        ast::ResnSlots &tgt = newInferred.resnSlots();
2189                        for (auto old : oldResnSlots) {
2190                                tgt.push_back(old);
2191                        }
2192                }
2193        }
2194
2195        ast::Expr * visitBaseExpr_SkipResultType( const Expression * old, ast::Expr * nw) {
2196
2197                nw->env    = convertTypeSubstitution(old->env);
2198
2199                nw->extension = old->extension;
2200                convertInferUnion(nw->inferred, old->inferParams, old->resnSlots);
2201
2202                return nw;
2203        }
2204
2205        ast::Expr * visitBaseExpr( const Expression * old, ast::Expr * nw) {
2206
2207                nw->result = GET_ACCEPT_1(result, Type);
2208                return visitBaseExpr_SkipResultType(old, nw);;
2209        }
2210
2211        virtual void visit( const ApplicationExpr * old ) override final {
2212                this->node = visitBaseExpr( old,
2213                        new ast::ApplicationExpr(
2214                                old->location,
2215                                GET_ACCEPT_1(function, Expr),
2216                                GET_ACCEPT_V(args, Expr)
2217                        )
2218                );
2219        }
2220
2221        virtual void visit( const UntypedExpr * old ) override final {
2222                this->node = visitBaseExpr( old,
2223                        new ast::UntypedExpr(
2224                                old->location,
2225                                GET_ACCEPT_1(function, Expr),
2226                                GET_ACCEPT_V(args, Expr)
2227                        )
2228                );
2229        }
2230
2231        virtual void visit( const NameExpr * old ) override final {
2232                this->node = visitBaseExpr( old,
2233                        new ast::NameExpr(
2234                                old->location,
2235                                old->get_name()
2236                        )
2237                );
2238        }
2239
2240        virtual void visit( const CastExpr * old ) override final {
2241                this->node = visitBaseExpr( old,
2242                        new ast::CastExpr(
2243                                old->location,
2244                                GET_ACCEPT_1(arg, Expr),
2245                                old->isGenerated ? ast::GeneratedCast : ast::ExplicitCast
2246                        )
2247                );
2248        }
2249
2250        virtual void visit( const KeywordCastExpr * old ) override final {
2251                ast::AggregateDecl::Aggregate castTarget = (ast::AggregateDecl::Aggregate)old->target;
2252                assert( ast::AggregateDecl::Generator <= castTarget && castTarget <= ast::AggregateDecl::Thread );
2253                this->node = visitBaseExpr( old,
2254                        new ast::KeywordCastExpr(
2255                                old->location,
2256                                GET_ACCEPT_1(arg, Expr),
2257                                castTarget,
2258                                {old->concrete_target.field, old->concrete_target.getter}
2259                        )
2260                );
2261        }
2262
2263        virtual void visit( const VirtualCastExpr * old ) override final {
2264                this->node = visitBaseExpr_SkipResultType( old,
2265                        new ast::VirtualCastExpr(
2266                                old->location,
2267                                GET_ACCEPT_1(arg, Expr),
2268                                GET_ACCEPT_1(result, Type)
2269                        )
2270                );
2271        }
2272
2273        virtual void visit( const AddressExpr * old ) override final {
2274                this->node = visitBaseExpr( old,
2275                        new ast::AddressExpr(
2276                                old->location,
2277                                GET_ACCEPT_1(arg, Expr)
2278                        )
2279                );
2280        }
2281
2282        virtual void visit( const LabelAddressExpr * old ) override final {
2283                this->node = visitBaseExpr( old,
2284                        new ast::LabelAddressExpr(
2285                                old->location,
2286                                make_label(&old->arg)
2287                        )
2288                );
2289        }
2290
2291        virtual void visit( const UntypedMemberExpr * old ) override final {
2292                this->node = visitBaseExpr( old,
2293                        new ast::UntypedMemberExpr(
2294                                old->location,
2295                                GET_ACCEPT_1(member, Expr),
2296                                GET_ACCEPT_1(aggregate, Expr)
2297                        )
2298                );
2299        }
2300
2301        virtual void visit( const MemberExpr * old ) override final {
2302                this->node = visitBaseExpr( old,
2303                        new ast::MemberExpr(
2304                                old->location,
2305                                GET_ACCEPT_1(member, DeclWithType),
2306                                GET_ACCEPT_1(aggregate, Expr),
2307                                ast::MemberExpr::NoOpConstructionChosen
2308                        )
2309                );
2310        }
2311
2312        virtual void visit( const VariableExpr * old ) override final {
2313                auto expr = new ast::VariableExpr(
2314                        old->location
2315                );
2316
2317                expr->var = GET_ACCEPT_1(var, DeclWithType);
2318                visitBaseExpr( old, expr );
2319
2320                this->node = expr;
2321        }
2322
2323        virtual void visit( const ConstantExpr * old ) override final {
2324                ast::ConstantExpr *rslt = new ast::ConstantExpr(
2325                        old->location,
2326                        GET_ACCEPT_1(result, Type),
2327                        old->constant.rep,
2328                        old->constant.ival
2329                );
2330                rslt->underlyer = getAccept1< ast::Type, Type* >( old->constant.type );
2331                this->node = visitBaseExpr( old, rslt );
2332        }
2333
2334        virtual void visit( const SizeofExpr * old ) override final {
2335                assert (old->expr || old->type);
2336                assert (! (old->expr && old->type));
2337                ast::SizeofExpr *rslt;
2338                if (old->expr) {
2339                        assert(!old->isType);
2340                        rslt = new ast::SizeofExpr(
2341                                old->location,
2342                                GET_ACCEPT_1(expr, Expr)
2343                        );
2344                }
2345                if (old->type) {
2346                        assert(old->isType);
2347                        rslt = new ast::SizeofExpr(
2348                                old->location,
2349                                GET_ACCEPT_1(type, Type)
2350                        );
2351                }
2352                this->node = visitBaseExpr( old, rslt );
2353        }
2354
2355        virtual void visit( const AlignofExpr * old ) override final {
2356                assert (old->expr || old->type);
2357                assert (! (old->expr && old->type));
2358                ast::AlignofExpr *rslt;
2359                if (old->expr) {
2360                        assert(!old->isType);
2361                        rslt = new ast::AlignofExpr(
2362                                old->location,
2363                                GET_ACCEPT_1(expr, Expr)
2364                        );
2365                }
2366                if (old->type) {
2367                        assert(old->isType);
2368                        rslt = new ast::AlignofExpr(
2369                                old->location,
2370                                GET_ACCEPT_1(type, Type)
2371                        );
2372                }
2373                this->node = visitBaseExpr( old, rslt );
2374        }
2375
2376        virtual void visit( const UntypedOffsetofExpr * old ) override final {
2377                this->node = visitBaseExpr( old,
2378                        new ast::UntypedOffsetofExpr(
2379                                old->location,
2380                                GET_ACCEPT_1(type, Type),
2381                                old->member
2382                        )
2383                );
2384        }
2385
2386        virtual void visit( const OffsetofExpr * old ) override final {
2387                this->node = visitBaseExpr( old,
2388                        new ast::OffsetofExpr(
2389                                old->location,
2390                                GET_ACCEPT_1(type, Type),
2391                                GET_ACCEPT_1(member, DeclWithType)
2392                        )
2393                );
2394        }
2395
2396        virtual void visit( const OffsetPackExpr * old ) override final {
2397                this->node = visitBaseExpr( old,
2398                        new ast::OffsetPackExpr(
2399                                old->location,
2400                                GET_ACCEPT_1(type, StructInstType)
2401                        )
2402                );
2403        }
2404
2405        virtual void visit( const LogicalExpr * old ) override final {
2406                this->node = visitBaseExpr( old,
2407                        new ast::LogicalExpr(
2408                                old->location,
2409                                GET_ACCEPT_1(arg1, Expr),
2410                                GET_ACCEPT_1(arg2, Expr),
2411                                old->get_isAnd() ?
2412                                        ast::LogicalFlag::AndExpr :
2413                                        ast::LogicalFlag::OrExpr
2414                        )
2415                );
2416        }
2417
2418        virtual void visit( const ConditionalExpr * old ) override final {
2419                this->node = visitBaseExpr( old,
2420                        new ast::ConditionalExpr(
2421                                old->location,
2422                                GET_ACCEPT_1(arg1, Expr),
2423                                GET_ACCEPT_1(arg2, Expr),
2424                                GET_ACCEPT_1(arg3, Expr)
2425                        )
2426                );
2427        }
2428
2429        virtual void visit( const CommaExpr * old ) override final {
2430                this->node = visitBaseExpr( old,
2431                        new ast::CommaExpr(
2432                                old->location,
2433                                GET_ACCEPT_1(arg1, Expr),
2434                                GET_ACCEPT_1(arg2, Expr)
2435                        )
2436                );
2437        }
2438
2439        virtual void visit( const TypeExpr * old ) override final {
2440                this->node = visitBaseExpr( old,
2441                        new ast::TypeExpr(
2442                                old->location,
2443                                GET_ACCEPT_1(type, Type)
2444                        )
2445                );
2446        }
2447
2448        virtual void visit( const DimensionExpr * old ) override final {
2449                // DimensionExpr gets desugared away in Validate.
2450                // As long as new-AST passes don't use it, this cheap-cheerful error
2451                // detection helps ensure that these occurrences have been compiled
2452                // away, as expected.  To move the DimensionExpr boundary downstream
2453                // or move the new-AST translation boundary upstream, implement
2454                // DimensionExpr in the new AST and implement a conversion.
2455                (void) old;
2456                assert(false && "DimensionExpr should not be present at new-AST boundary");
2457        }
2458
2459        virtual void visit( const AsmExpr * old ) override final {
2460                this->node = visitBaseExpr( old,
2461                        new ast::AsmExpr(
2462                                old->location,
2463                                old->inout,
2464                                GET_ACCEPT_1(constraint, Expr),
2465                                GET_ACCEPT_1(operand, Expr)
2466                        )
2467                );
2468        }
2469
2470        virtual void visit( const ImplicitCopyCtorExpr * old ) override final {
2471                auto rslt = new ast::ImplicitCopyCtorExpr(
2472                        old->location,
2473                        GET_ACCEPT_1(callExpr, ApplicationExpr)
2474                );
2475
2476                this->node = visitBaseExpr( old, rslt );
2477        }
2478
2479        virtual void visit( const ConstructorExpr * old ) override final {
2480                this->node = visitBaseExpr( old,
2481                        new ast::ConstructorExpr(
2482                                old->location,
2483                                GET_ACCEPT_1(callExpr, Expr)
2484                        )
2485                );
2486        }
2487
2488        virtual void visit( const CompoundLiteralExpr * old ) override final {
2489                this->node = visitBaseExpr_SkipResultType( old,
2490                        new ast::CompoundLiteralExpr(
2491                                old->location,
2492                                GET_ACCEPT_1(result, Type),
2493                                GET_ACCEPT_1(initializer, Init)
2494                        )
2495                );
2496        }
2497
2498        virtual void visit( const RangeExpr * old ) override final {
2499                this->node = visitBaseExpr( old,
2500                        new ast::RangeExpr(
2501                                old->location,
2502                                GET_ACCEPT_1(low, Expr),
2503                                GET_ACCEPT_1(high, Expr)
2504                        )
2505                );
2506        }
2507
2508        virtual void visit( const UntypedTupleExpr * old ) override final {
2509                this->node = visitBaseExpr( old,
2510                        new ast::UntypedTupleExpr(
2511                                old->location,
2512                                GET_ACCEPT_V(exprs, Expr)
2513                        )
2514                );
2515        }
2516
2517        virtual void visit( const TupleExpr * old ) override final {
2518                this->node = visitBaseExpr( old,
2519                        new ast::TupleExpr(
2520                                old->location,
2521                                GET_ACCEPT_V(exprs, Expr)
2522                        )
2523                );
2524        }
2525
2526        virtual void visit( const TupleIndexExpr * old ) override final {
2527                this->node = visitBaseExpr( old,
2528                        new ast::TupleIndexExpr(
2529                                old->location,
2530                                GET_ACCEPT_1(tuple, Expr),
2531                                old->index
2532                        )
2533                );
2534        }
2535
2536        virtual void visit( const TupleAssignExpr * old ) override final {
2537                this->node = visitBaseExpr_SkipResultType( old,
2538                        new ast::TupleAssignExpr(
2539                                old->location,
2540                                GET_ACCEPT_1(result, Type),
2541                                GET_ACCEPT_1(stmtExpr, StmtExpr)
2542                        )
2543                );
2544        }
2545
2546        virtual void visit( const StmtExpr * old ) override final {
2547                auto rslt = new ast::StmtExpr(
2548                        old->location,
2549                        GET_ACCEPT_1(statements, CompoundStmt)
2550                );
2551                rslt->returnDecls = GET_ACCEPT_V(returnDecls, ObjectDecl);
2552                rslt->dtors       = GET_ACCEPT_V(dtors      , Expr);
2553
2554                this->node = visitBaseExpr_SkipResultType( old, rslt );
2555        }
2556
2557        virtual void visit( const UniqueExpr * old ) override final {
2558                auto rslt = new ast::UniqueExpr(
2559                        old->location,
2560                        GET_ACCEPT_1(expr, Expr),
2561                        old->get_id()
2562                );
2563                rslt->object = GET_ACCEPT_1(object, ObjectDecl);
2564                rslt->var    = GET_ACCEPT_1(var   , VariableExpr);
2565
2566                this->node = visitBaseExpr( old, rslt );
2567        }
2568
2569        virtual void visit( const UntypedInitExpr * old ) override final {
2570                std::deque<ast::InitAlternative> initAlts;
2571                for (auto ia : old->initAlts) {
2572                        initAlts.push_back(ast::InitAlternative(
2573                                getAccept1< ast::Type, Type * >( ia.type ),
2574                                getAccept1< ast::Designation, Designation * >( ia.designation )
2575                        ));
2576                }
2577                this->node = visitBaseExpr( old,
2578                        new ast::UntypedInitExpr(
2579                                old->location,
2580                                GET_ACCEPT_1(expr, Expr),
2581                                std::move(initAlts)
2582                        )
2583                );
2584        }
2585
2586        virtual void visit( const InitExpr * old ) override final {
2587                this->node = visitBaseExpr( old,
2588                        new ast::InitExpr(
2589                                old->location,
2590                                GET_ACCEPT_1(expr, Expr),
2591                                GET_ACCEPT_1(designation, Designation)
2592                        )
2593                );
2594        }
2595
2596        virtual void visit( const DeletedExpr * old ) override final {
2597                this->node = visitBaseExpr( old,
2598                        new ast::DeletedExpr(
2599                                old->location,
2600                                GET_ACCEPT_1(expr, Expr),
2601                                inCache(old->deleteStmt) ?
2602                                        strict_dynamic_cast<ast::Decl*>(this->node) :
2603                                        GET_ACCEPT_1(deleteStmt, Decl)
2604                        )
2605                );
2606        }
2607
2608        virtual void visit( const DefaultArgExpr * old ) override final {
2609                this->node = visitBaseExpr( old,
2610                        new ast::DefaultArgExpr(
2611                                old->location,
2612                                GET_ACCEPT_1(expr, Expr)
2613                        )
2614                );
2615        }
2616
2617        virtual void visit( const GenericExpr * old ) override final {
2618                std::vector<ast::GenericExpr::Association> associations;
2619                for (auto association : old->associations) {
2620                        associations.push_back(ast::GenericExpr::Association(
2621                                getAccept1< ast::Type, Type * >( association.type ),
2622                                getAccept1< ast::Expr, Expression * >( association.expr )
2623                        ));
2624                }
2625                this->node = visitBaseExpr( old,
2626                        new ast::GenericExpr(
2627                                old->location,
2628                                GET_ACCEPT_1(control, Expr),
2629                                std::move(associations)
2630                        )
2631                );
2632        }
2633
2634        void visitType( const Type * old, ast::Type * type ) {
2635                // Some types do this in their constructor so add a check.
2636                if ( !old->attributes.empty() && type->attributes.empty() ) {
2637                        type->attributes = GET_ACCEPT_V(attributes, Attribute);
2638                }
2639                this->node = type;
2640        }
2641
2642        virtual void visit( const VoidType * old ) override final {
2643                visitType( old, new ast::VoidType{ cv( old ) } );
2644        }
2645
2646        virtual void visit( const BasicType * old ) override final {
2647                auto type = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind, cv( old ) };
2648                // I believe this should always be a BasicType.
2649                if ( Validate::SizeType == old ) {
2650                        ast::sizeType = type;
2651                }
2652                visitType( old, type );
2653        }
2654
2655        virtual void visit( const PointerType * old ) override final {
2656                visitType( old, new ast::PointerType{
2657                        GET_ACCEPT_1( base, Type ),
2658                        GET_ACCEPT_1( dimension, Expr ),
2659                        (ast::LengthFlag)old->isVarLen,
2660                        (ast::DimensionFlag)old->isStatic,
2661                        cv( old )
2662                } );
2663        }
2664
2665        virtual void visit( const ArrayType * old ) override final {
2666                visitType( old, new ast::ArrayType{
2667                        GET_ACCEPT_1( base, Type ),
2668                        GET_ACCEPT_1( dimension, Expr ),
2669                        (ast::LengthFlag)old->isVarLen,
2670                        (ast::DimensionFlag)old->isStatic,
2671                        cv( old )
2672                } );
2673        }
2674
2675        virtual void visit( const ReferenceType * old ) override final {
2676                visitType( old, new ast::ReferenceType{
2677                        GET_ACCEPT_1( base, Type ),
2678                        cv( old )
2679                } );
2680        }
2681
2682        virtual void visit( const QualifiedType * old ) override final {
2683                visitType( old, new ast::QualifiedType{
2684                        GET_ACCEPT_1( parent, Type ),
2685                        GET_ACCEPT_1( child, Type ),
2686                        cv( old )
2687                } );
2688        }
2689
2690        virtual void visit( const FunctionType * old ) override final {
2691                auto ty = new ast::FunctionType {
2692                        (ast::ArgumentFlag)old->isVarArgs,
2693                        cv( old )
2694                };
2695                auto returnVars = GET_ACCEPT_V(returnVals, DeclWithType);
2696                auto paramVars = GET_ACCEPT_V(parameters, DeclWithType);
2697                // ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
2698                // ty->params = GET_ACCEPT_V( parameters, DeclWithType );
2699                for (auto & v: returnVars) {
2700                        ty->returns.emplace_back(v->get_type());
2701                }
2702                for (auto & v: paramVars) {
2703                        ty->params.emplace_back(v->get_type());
2704                }
2705                // xxx - when will this be non-null?
2706                // will have to create dangling (no-owner) decls to be pointed to
2707                auto foralls = GET_ACCEPT_V( forall, TypeDecl );
2708
2709                for (auto & param : foralls) {
2710                        ty->forall.emplace_back(new ast::TypeInstType(param->name, param));
2711                        for (auto asst : param->assertions) {
2712                                ty->assertions.emplace_back(new ast::VariableExpr({}, asst));
2713                        }
2714                }
2715                visitType( old, ty );
2716        }
2717
2718        void postvisit( const ReferenceToType * old, ast::BaseInstType * ty ) {
2719                ty->params = GET_ACCEPT_V( parameters, Expr );
2720                ty->hoistType = old->hoistType;
2721                visitType( old, ty );
2722        }
2723
2724        virtual void visit( const StructInstType * old ) override final {
2725                ast::StructInstType * ty;
2726                if ( old->baseStruct ) {
2727                        ty = new ast::StructInstType{
2728                                GET_ACCEPT_1( baseStruct, StructDecl ),
2729                                cv( old ),
2730                                GET_ACCEPT_V( attributes, Attribute )
2731                        };
2732                } else {
2733                        ty = new ast::StructInstType{
2734                                old->name,
2735                                cv( old ),
2736                                GET_ACCEPT_V( attributes, Attribute )
2737                        };
2738                }
2739                postvisit( old, ty );
2740        }
2741
2742        virtual void visit( const UnionInstType * old ) override final {
2743                ast::UnionInstType * ty;
2744                if ( old->baseUnion ) {
2745                        ty = new ast::UnionInstType{
2746                                GET_ACCEPT_1( baseUnion, UnionDecl ),
2747                                cv( old ),
2748                                GET_ACCEPT_V( attributes, Attribute )
2749                        };
2750                } else {
2751                        ty = new ast::UnionInstType{
2752                                old->name,
2753                                cv( old ),
2754                                GET_ACCEPT_V( attributes, Attribute )
2755                        };
2756                }
2757                postvisit( old, ty );
2758        }
2759
2760        virtual void visit( const EnumInstType * old ) override final {
2761                ast::EnumInstType * ty;
2762                if ( old->baseEnum ) {
2763                        ty = new ast::EnumInstType{
2764                                GET_ACCEPT_1( baseEnum, EnumDecl ),
2765                                cv( old ),
2766                                GET_ACCEPT_V( attributes, Attribute )
2767                        };
2768                } else {
2769                        ty = new ast::EnumInstType{
2770                                old->name,
2771                                cv( old ),
2772                                GET_ACCEPT_V( attributes, Attribute )
2773                        };
2774                }
2775                postvisit( old, ty );
2776        }
2777
2778        virtual void visit( const TraitInstType * old ) override final {
2779                ast::TraitInstType * ty;
2780                if ( old->baseTrait ) {
2781                        ty = new ast::TraitInstType{
2782                                GET_ACCEPT_1( baseTrait, TraitDecl ),
2783                                cv( old ),
2784                                GET_ACCEPT_V( attributes, Attribute )
2785                        };
2786                } else {
2787                        ty = new ast::TraitInstType{
2788                                old->name,
2789                                cv( old ),
2790                                GET_ACCEPT_V( attributes, Attribute )
2791                        };
2792                }
2793                postvisit( old, ty );
2794        }
2795
2796        virtual void visit( const TypeInstType * old ) override final {
2797                ast::TypeInstType * ty;
2798                if ( old->baseType ) {
2799                        ty = new ast::TypeInstType{
2800                                old->name,
2801                                GET_ACCEPT_1( baseType, TypeDecl ),
2802                                cv( old ),
2803                                GET_ACCEPT_V( attributes, Attribute )
2804                        };
2805                } else {
2806                        ty = new ast::TypeInstType{
2807                                old->name,
2808                                old->isFtype ? ast::TypeDecl::Ftype : ast::TypeDecl::Dtype,
2809                                cv( old ),
2810                                GET_ACCEPT_V( attributes, Attribute )
2811                        };
2812                }
2813                postvisit( old, ty );
2814        }
2815
2816        virtual void visit( const TupleType * old ) override final {
2817                visitType( old, new ast::TupleType{
2818                        GET_ACCEPT_V( types, Type ),
2819                        // members generated by TupleType c'tor
2820                        cv( old )
2821                } );
2822        }
2823
2824        virtual void visit( const TypeofType * old ) override final {
2825                visitType( old, new ast::TypeofType{
2826                        GET_ACCEPT_1( expr, Expr ),
2827                        (ast::TypeofType::Kind)old->is_basetypeof,
2828                        cv( old )
2829                } );
2830        }
2831
2832        virtual void visit( const VTableType * old ) override final {
2833                visitType( old, new ast::VTableType{
2834                        GET_ACCEPT_1( base, Type ),
2835                        cv( old )
2836                } );
2837        }
2838
2839        virtual void visit( const AttrType * ) override final {
2840                assertf( false, "AttrType deprecated in new AST." );
2841        }
2842
2843        virtual void visit( const VarArgsType * old ) override final {
2844                visitType( old, new ast::VarArgsType{ cv( old ) } );
2845        }
2846
2847        virtual void visit( const ZeroType * old ) override final {
2848                visitType( old, new ast::ZeroType{ cv( old ) } );
2849        }
2850
2851        virtual void visit( const OneType * old ) override final {
2852                visitType( old, new ast::OneType{ cv( old ) } );
2853        }
2854
2855        virtual void visit( const GlobalScopeType * old ) override final {
2856                visitType( old, new ast::GlobalScopeType{} );
2857        }
2858
2859        virtual void visit( const Designation * old ) override final {
2860                this->node = new ast::Designation(
2861                        old->location,
2862                        GET_ACCEPT_D(designators, Expr)
2863                );
2864        }
2865
2866        virtual void visit( const SingleInit * old ) override final {
2867                this->node = new ast::SingleInit(
2868                        old->location,
2869                        GET_ACCEPT_1(value, Expr),
2870                        (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::NoConstruct
2871                );
2872        }
2873
2874        virtual void visit( const ListInit * old ) override final {
2875                this->node = new ast::ListInit(
2876                        old->location,
2877                        GET_ACCEPT_V(initializers, Init),
2878                        GET_ACCEPT_V(designations, Designation),
2879                        (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::NoConstruct
2880                );
2881        }
2882
2883        virtual void visit( const ConstructorInit * old ) override final {
2884                this->node = new ast::ConstructorInit(
2885                        old->location,
2886                        GET_ACCEPT_1(ctor, Stmt),
2887                        GET_ACCEPT_1(dtor, Stmt),
2888                        GET_ACCEPT_1(init, Init)
2889                );
2890        }
2891
2892        virtual void visit( const Constant * ) override final {
2893                // Handled in visit( ConstantEpxr * ).
2894                // In the new tree, Constant fields are inlined into containing ConstantExpression.
2895                assert( 0 );
2896        }
2897
2898        virtual void visit( const Attribute * old ) override final {
2899                this->node = new ast::Attribute(
2900                        old->name,
2901                        GET_ACCEPT_V( parameters, Expr )
2902                );
2903        }
2904};
2905
2906#undef GET_LABELS_V
2907#undef GET_ACCEPT_V
2908#undef GET_ACCEPT_1
2909
2910ast::TranslationUnit convert( const std::list< Declaration * > && translationUnit ) {
2911        ConverterOldToNew c;
2912        ast::TranslationUnit unit;
2913        if (Validate::SizeType) {
2914                // this should be a BasicType.
2915                auto old = strict_dynamic_cast<BasicType *>(Validate::SizeType);
2916                ast::sizeType = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind };
2917        }
2918
2919        for(auto d : translationUnit) {
2920                d->accept( c );
2921                unit.decls.emplace_back( c.decl() );
2922        }
2923        deleteAll(translationUnit);
2924
2925        // Load the local static varables into the global store.
2926        unit.global.sizeType = ast::sizeType;
2927        unit.global.dereference = ast::dereferenceOperator;
2928        unit.global.dtorStruct = ast::dtorStruct;
2929        unit.global.dtorDestroy = ast::dtorStructDestroy;
2930
2931        return unit;
2932}
Note: See TracBrowser for help on using the repository browser.