Ignore:
Timestamp:
Nov 8, 2017, 5:43:33 PM (8 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
954908d
Parents:
78315272 (diff), e35f30a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r78315272 r3f7e12cb  
    3636#include "FixGlobalInit.h"             // for fixGlobalInit
    3737#include "GenInit.h"                   // for genCtorDtor
    38 #include "GenPoly/DeclMutator.h"       // for DeclMutator
    3938#include "GenPoly/GenPoly.h"           // for getFunctionType
    40 #include "GenPoly/PolyMutator.h"       // for PolyMutator
    4139#include "InitTweak.h"                 // for getFunctionName, getCallArg
    4240#include "Parser/LinkageSpec.h"        // for C, Spec, Cforall, isBuiltin
     
    4644#include "SymTab/Indexer.h"            // for Indexer
    4745#include "SymTab/Mangler.h"            // for Mangler
    48 #include "SynTree/AddStmtVisitor.h"    // for AddStmtVisitor
    4946#include "SynTree/Attribute.h"         // for Attribute
    5047#include "SynTree/Constant.h"          // for Constant
     
    5855#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution, operator<<
    5956#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
    60 #include "Tuples/Tuples.h"             // for isTtype
    6157
    6258bool ctordtorp = false; // print all debug
     
    9793                        /// true if type does not need to be copy constructed to ensure correctness
    9894                        bool skipCopyConstruct( Type * type );
    99                         void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );
     95                        void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal );
    10096                        void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
    10197
     
    187183                };
    188184
    189                 class FixCopyCtors final : public GenPoly::PolyMutator {
     185                class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> {
    190186                  public:
    191187                        FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
     
    194190                        static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount );
    195191
    196                         typedef GenPoly::PolyMutator Parent;
    197                         using Parent::mutate;
    198                         virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
    199                         virtual Expression * mutate( UniqueExpr * unqExpr ) override;
    200                         virtual Expression * mutate( StmtExpr * stmtExpr ) override;
     192                        Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr );
     193                        void premutate( StmtExpr * stmtExpr );
     194                        void premutate( UniqueExpr * unqExpr );
    201195
    202196                        UnqCount & unqCount;
     
    220214                        void emit( CodeLocation, const Params &... params );
    221215
    222                         FunctionDecl * function = 0;
     216                        FunctionDecl * function = nullptr;
    223217                        std::set< DeclarationWithType * > unhandled;
    224218                        std::map< DeclarationWithType *, CodeLocation > usedUninit;
    225                         ObjectDecl * thisParam = 0;
     219                        ObjectDecl * thisParam = nullptr;
    226220                        bool isCtor = false; // true if current function is a constructor
    227                         StructDecl * structDecl = 0;
     221                        StructDecl * structDecl = nullptr;
    228222                };
    229223
     
    243237                };
    244238
    245                 class FixCtorExprs final : public GenPoly::DeclMutator {
    246                   public:
     239                struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer {
    247240                        /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
    248241                        static void fix( std::list< Declaration * > & translationUnit );
    249242
    250                         using GenPoly::DeclMutator::mutate;
    251                         virtual Expression * mutate( ConstructorExpr * ctorExpr ) override;
     243                        Expression * postmutate( ConstructorExpr * ctorExpr );
    252244                };
    253245        } // namespace
     
    268260
    269261                GenStructMemberCalls::generate( translationUnit );
     262
    270263                // xxx - ctor expansion currently has to be after FixCopyCtors, because there is currently a
    271264                // hack in the way untyped assignments are generated, where the first argument cannot have
     
    297290                        for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    298291                                try {
    299                                         *i = maybeMutate( *i, fixer );
     292                                        maybeMutate( *i, fixer );
    300293                                        translationUnit.splice( i, fixer.pass.staticDtorDecls );
    301294                                } catch( SemanticError &e ) {
     
    316309
    317310                void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
    318                         FixCopyCtors fixer( unqCount );
     311                        PassVisitor<FixCopyCtors> fixer( unqCount );
    319312                        mutateAll( translationUnit, fixer );
    320313                }
     
    326319
    327320                void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) {
    328                         FixCtorExprs fixer;
    329                         fixer.mutateDeclarationList( translationUnit );
     321                        PassVisitor<FixCtorExprs> fixer;
     322                        mutateAll( translationUnit, fixer );
    330323                }
    331324
    332325                Expression * InsertImplicitCalls::postmutate( ApplicationExpr * appExpr ) {
    333                         assert( appExpr );
    334 
    335326                        if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) {
    336                                 if ( LinkageSpec::isBuiltin( function->get_var()->get_linkage() ) ) {
     327                                if ( function->var->linkage.is_builtin ) {
    337328                                        // optimization: don't need to copy construct in order to call intrinsic functions
    338329                                        return appExpr;
    339330                                } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) {
    340331                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    341                                         assert( ftype );
    342                                         if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
    343                                                 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    344                                                 Type * t2 = ftype->get_parameters().back()->get_type();
     332                                        assertf( ftype, "Function call without function type: %s", toString( funcDecl ).c_str() );
     333                                        if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->parameters.size() == 2 ) {
     334                                                Type * t1 = getPointerBase( ftype->parameters.front()->get_type() );
     335                                                Type * t2 = ftype->parameters.back()->get_type();
    345336                                                assert( t1 );
    346337
     
    368359                }
    369360
    370                 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
    371                         return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
    372                 }
     361                bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { return ! isConstructable( type ); }
    373362
    374363                Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
     
    377366                        ImplicitCtorDtorStmt * stmt = genCtorDtor( fname, var, cpArg );
    378367                        ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->get_callStmt() );
    379                         Expression * untyped = exprStmt->get_expr();
     368                        Expression * resolved = exprStmt->expr;
     369                        exprStmt->expr = nullptr; // take ownership of expr
    380370
    381371                        // resolve copy constructor
    382372                        // should only be one alternative for copy ctor and dtor expressions, since all arguments are fixed
    383373                        // (VariableExpr and already resolved expression)
    384                         CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
    385                         Expression * resolved = ResolvExpr::findVoidExpression( untyped, indexer );
     374                        CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << resolved << std::endl; )
     375                        ResolvExpr::findVoidExpression( resolved, indexer );
    386376                        assert( resolved );
    387377                        if ( resolved->get_env() ) {
     
    391381                                resolved->set_env( nullptr );
    392382                        } // if
    393 
    394383                        delete stmt;
    395384                        return resolved;
    396385                }
    397386
    398                 void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {
     387                void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal ) {
    399388                        static UniqueName tempNamer("_tmp_cp");
    400389                        assert( env );
    401390                        CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; )
    402                         assert( arg->has_result() );
    403                         Type * result = arg->get_result();
     391                        assert( arg->result );
     392                        Type * result = arg->result;
    404393                        if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types
    405394
    406                         // type may involve type variables, so apply type substitution to get temporary variable's actual type
     395                        // type may involve type variables, so apply type substitution to get temporary variable's actual type.
     396                        // Use applyFree so that types bound in function pointers are not substituted, e.g. in forall(dtype T) void (*)(T).
    407397                        result = result->clone();
    408                         env->apply( result );
    409                         ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     398                        env->applyFree( result );
     399                        ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr );
    410400                        tmp->get_type()->set_const( false );
    411401
     
    417407                                // if the chosen constructor is intrinsic, the copy is unnecessary, so
    418408                                // don't create the temporary and don't call the copy constructor
    419                                 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
    420                                 assert( function );
    421                                 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
    422                         }
     409                                VariableExpr * function = strict_dynamic_cast< VariableExpr * >( appExpr->function );
     410                                if ( function->var->linkage == LinkageSpec::Intrinsic ) {
     411                                        // arguments that need to be boxed need a temporary regardless of whether the copy constructor is intrinsic,
     412                                        // so that the object isn't changed inside of the polymorphic function
     413                                        if ( ! GenPoly::needsBoxing( formal, result, impCpCtorExpr->callExpr, env ) ) return;
     414                                }
     415                        }
     416
     417                        // set a unique name for the temporary once it's certain the call is necessary
     418                        tmp->name = tempNamer.newName();
    423419
    424420                        // replace argument to function call with temporary
    425421                        arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
    426                         impCpCtorExpr->get_tempDecls().push_back( tmp );
    427                         impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
     422                        impCpCtorExpr->tempDecls.push_back( tmp );
     423                        impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) );
    428424                }
    429425
     
    435431                        CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
    436432
    437                         ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr();
     433                        ApplicationExpr * appExpr = impCpCtorExpr->callExpr;
    438434
    439435                        // take each argument and attempt to copy construct it.
    440                         for ( Expression * & arg : appExpr->get_args() ) {
    441                                 copyConstructArg( arg, impCpCtorExpr );
     436                        FunctionType * ftype = GenPoly::getFunctionType( appExpr->function->result );
     437                        assert( ftype );
     438                        auto & params = ftype->parameters;
     439                        auto iter = params.begin();
     440                        for ( Expression * & arg : appExpr->args ) {
     441                                Type * formal = nullptr;
     442                                if ( iter != params.end() ) {
     443                                        DeclarationWithType * param = *iter++;
     444                                        formal = param->get_type();
     445                                }
     446
     447                                copyConstructArg( arg, impCpCtorExpr, formal );
    442448                        } // for
    443449
     
    445451                        // initialized with the return value and is destructed later
    446452                        // xxx - handle named return values?
    447                         Type * result = appExpr->get_result();
     453                        Type * result = appExpr->result;
    448454                        if ( ! result->isVoid() ) {
    449455                                static UniqueName retNamer("_tmp_cp_ret");
    450456                                result = result->clone();
    451457                                env->apply( result );
    452                                 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
    453                                 ret->get_type()->set_const( false );
    454                                 impCpCtorExpr->get_returnDecls().push_back( ret );
     458                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
     459                                ret->type->set_const( false );
     460                                impCpCtorExpr->returnDecls.push_back( ret );
    455461                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    456462                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
    457                                         // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
     463                                        // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    458464                                        destructRet( ret, impCpCtorExpr );
    459465                                }
     
    472478                                result = result->clone();
    473479                                env->apply( result );
    474                                 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     480                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    475481                                ret->get_type()->set_const( false );
    476482                                stmtExpr->get_returnDecls().push_front( ret );
     
    493499                                visit_children = false;
    494500                        }
     501                }
     502
     503                // to prevent warnings (‘_unq0’ may be used uninitialized in this function),
     504                // insert an appropriate zero initializer for UniqueExpr temporaries.
     505                Initializer * makeInit( Type * t ) {
     506                        if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) {
     507                                // initizer for empty struct must be empty
     508                                if ( inst->baseStruct->members.empty() ) return new ListInit({});
     509                        } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) {
     510                                // initizer for empty union must be empty
     511                                if ( inst->baseUnion->members.empty() ) return new ListInit({});
     512                        }
     513
     514                        return new ListInit( { new SingleInit( new ConstantExpr( Constant::from_int( 0 ) ) ) } );
    495515                }
    496516
     
    509529                        } else {
    510530                                // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
    511                                 unqExpr->set_object( new ObjectDecl( toString("_unq", unqExpr->get_id()), Type::StorageClasses(), LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) );
     531                                unqExpr->set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), makeInit( unqExpr->get_result() ) ) );
    512532                                unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) );
    513533                        }
     
    515535                }
    516536
    517                 Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
     537                Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    518538                        CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; )
    519539
    520                         impCpCtorExpr = strict_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) );
    521540                        std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls();
    522541                        std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls();
     
    525544                        // add all temporary declarations and their constructors
    526545                        for ( ObjectDecl * obj : tempDecls ) {
    527                                 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     546                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    528547                        } // for
    529548                        for ( ObjectDecl * obj : returnDecls ) {
    530                                 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     549                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    531550                        } // for
    532551
     
    536555                        } // for
    537556
    538                         // xxx - update to work with multiple return values
    539557                        ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front();
    540558                        Expression * callExpr = impCpCtorExpr->get_callExpr();
     
    561579                                Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
    562580                                // move env from callExpr to retExpr
    563                                 retExpr->set_env( callExpr->get_env() );
    564                                 callExpr->set_env( nullptr );
     581                                std::swap( retExpr->env, callExpr->env );
    565582                                return retExpr;
    566583                        } else {
     
    569586                }
    570587
    571                 Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) {
     588                void FixCopyCtors::premutate( StmtExpr * stmtExpr ) {
    572589                        // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
    573590                        // since temporaries can be shared across sub-expressions, e.g.
    574591                        //   [A, A] f();
    575592                        //   g([A] x, [A] y);
    576                         //   f(g());
     593                        //   g(f());
    577594                        // f is executed once, so the return temporary is shared across the tuple constructors for x and y.
     595                        // Explicitly mutating children instead of mutating the inner compound statment forces the temporaries to be added
     596                        // to the outer context, rather than inside of the statement expression.
     597                        visit_children = false;
    578598                        std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
    579599                        for ( Statement *& stmt : stmts ) {
    580                                 stmt = stmt->acceptMutator( *this );
     600                                stmt = stmt->acceptMutator( *visitor );
    581601                        } // for
    582                         // stmtExpr = strict_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) );
    583602                        assert( stmtExpr->get_result() );
    584603                        Type * result = stmtExpr->get_result();
    585604                        if ( ! result->isVoid() ) {
    586605                                for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) {
    587                                         stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     606                                        stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    588607                                } // for
    589608                                // add destructors after current statement
     
    592611                                } // for
    593612                                // must have a non-empty body, otherwise it wouldn't have a result
    594                                 CompoundStmt * body = stmtExpr->get_statements();
    595                                 assert( ! body->get_kids().empty() );
     613                                assert( ! stmts.empty() );
    596614                                assert( ! stmtExpr->get_returnDecls().empty() );
    597                                 body->get_kids().push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
     615                                stmts.push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
    598616                                stmtExpr->get_returnDecls().clear();
    599617                                stmtExpr->get_dtors().clear();
     
    601619                        assert( stmtExpr->get_returnDecls().empty() );
    602620                        assert( stmtExpr->get_dtors().empty() );
    603                         return stmtExpr;
    604                 }
    605 
    606                 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
     621                }
     622
     623                void FixCopyCtors::premutate( UniqueExpr * unqExpr ) {
     624                        visit_children = false;
    607625                        unqCount[ unqExpr->get_id() ]--;
    608626                        static std::unordered_map< int, std::list< Statement * > > dtors;
    609627                        static std::unordered_map< int, UniqueExpr * > unqMap;
    610                         static std::unordered_set< int > addDeref;
    611628                        // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes
    612629                        if ( unqMap.count( unqExpr->get_id() ) ) {
     
    619636                                        stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    620637                                }
    621                                 if ( addDeref.count( unqExpr->get_id() ) ) {
    622                                         // other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too
    623                                         return UntypedExpr::createDeref( unqExpr );
    624                                 }
    625                                 return unqExpr;
    626                         }
    627                         FixCopyCtors fixer( unqCount );
     638                                return;
     639                        }
     640                        PassVisitor<FixCopyCtors> fixer( unqCount );
    628641                        unqExpr->set_expr( unqExpr->get_expr()->acceptMutator( fixer ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup
    629                         stmtsToAdd.splice( stmtsToAdd.end(), fixer.stmtsToAdd );
     642                        stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore );
    630643                        unqMap[unqExpr->get_id()] = unqExpr;
    631644                        if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
    632645                                stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    633646                        } else { // remember dtors for last instance of unique expr
    634                                 dtors[ unqExpr->get_id() ] = fixer.stmtsToAddAfter;
    635                         }
    636                         if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) {
    637                                 // unique expression is now a dereference, because the inner expression is an lvalue returning function call.
    638                                 // Normalize the expression by dereferencing the unique expression, rather than the inner expression
    639                                 // (i.e. move the dereference out a level)
    640                                 assert( getFunctionName( deref ) == "*?" );
    641                                 unqExpr->set_expr( getCallArg( deref, 0 ) );
    642                                 getCallArg( deref, 0 ) = unqExpr;
    643                                 addDeref.insert( unqExpr->get_id() );
    644                                 return deref;
    645                         }
    646                         return unqExpr;
    647                 }
    648 
    649                 DeclarationWithType *FixInit::postmutate( ObjectDecl *objDecl ) {
     647                                dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter;
     648                        }
     649                        return;
     650                }
     651
     652                DeclarationWithType * FixInit::postmutate( ObjectDecl *objDecl ) {
    650653                        // since this removes the init field from objDecl, it must occur after children are mutated (i.e. postmutate)
    651654                        if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
     
    745748                                        } else {
    746749                                                ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * > ( ctor );
    747                                                 ExprStmt * ctorStmt = dynamic_cast< ExprStmt * >( implicit->get_callStmt() );
     750                                                ExprStmt * ctorStmt = dynamic_cast< ExprStmt * >( implicit->callStmt );
    748751                                                ApplicationExpr * ctorCall = nullptr;
    749                                                 if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt->get_expr() )) && ctorCall->get_args().size() == 2 ) {
     752                                                if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt->expr )) && ctorCall->get_args().size() == 2 ) {
    750753                                                        // clean up intrinsic copy constructor calls by making them into SingleInits
    751                                                         objDecl->set_init( new SingleInit( ctorCall->get_args().back() ) );
    752                                                         ctorCall->get_args().pop_back();
     754                                                        Expression * ctorArg = ctorCall->args.back();
     755                                                        std::swap( ctorArg->env, ctorCall->env );
     756                                                        objDecl->init = new SingleInit( ctorArg );
     757
     758                                                        ctorCall->args.pop_back();
    753759                                                } else {
    754760                                                        stmtsToAddAfter.push_back( ctor );
    755                                                         objDecl->set_init( nullptr );
    756                                                         ctorInit->set_ctor( nullptr );
     761                                                        objDecl->init = nullptr;
     762                                                        ctorInit->ctor = nullptr;
    757763                                                }
    758764                                        } // if
    759                                 } else if ( Initializer * init = ctorInit->get_init() ) {
    760                                         objDecl->set_init( init );
    761                                         ctorInit->set_init( nullptr );
     765                                } else if ( Initializer * init = ctorInit->init ) {
     766                                        objDecl->init = init;
     767                                        ctorInit->init = nullptr;
    762768                                } else {
    763769                                        // no constructor and no initializer, which is okay
    764                                         objDecl->set_init( nullptr );
     770                                        objDecl->init = nullptr;
    765771                                } // if
    766772                                delete ctorInit;
     
    819825                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    820826                                        Statement * dtor = ctorInit->get_dtor();
     827                                        // don't need to call intrinsic dtor, because it does nothing, but
     828                                        // non-intrinsic dtors must be called
    821829                                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    822                                                 // don't need to call intrinsic dtor, because it does nothing, but
    823                                                 // non-intrinsic dtors must be called
     830                                                // set dtor location to the object's location for error messages
     831                                                ctorInit->dtor->location = objDecl->location;
    824832                                                reverseDeclOrder.front().push_front( objDecl );
    825833                                        } // if
     
    832840                        GuardValue( labelVars );
    833841                        labelVars.clear();
     842                        // LabelFinder does not recurse into FunctionDecl, so need to visit
     843                        // its children manually.
    834844                        maybeAccept( funcDecl->type, finder );
    835845                        maybeAccept( funcDecl->statements, finder );
     
    933943                }
    934944
     945                void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) {
     946                        for ( auto d : decls ) {
     947                                indexer.addId( d );
     948                        }
     949                }
     950
     951                void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) {
     952                        for ( auto td : tds ) {
     953                                indexer.addType( td );
     954                                addIds( indexer, td->assertions );
     955                        }
     956                }
     957
    935958                void GenStructMemberCalls::previsit( FunctionDecl * funcDecl ) {
    936                         GuardValue( funcDecl );
     959                        GuardValue( function );
    937960                        GuardValue( unhandled );
    938961                        GuardValue( usedUninit );
     
    967990                }
    968991
    969                 void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) {
    970                         for ( auto d : decls ) {
    971                                 indexer.addId( d );
    972                         }
    973                 }
    974 
    975                 void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) {
    976                         for ( auto td : tds ) {
    977                                 indexer.addType( td );
    978                                 addIds( indexer, td->assertions );
    979                         }
    980                 }
    981 
    982992                void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) {
    983993                        // remove the unhandled objects from usedUninit, because a call is inserted
     
    10121022                                        // skip non-DWT members
    10131023                                        if ( ! field ) continue;
     1024                                        // skip non-constructable members
     1025                                        if ( ! tryConstruct( field ) ) continue;
    10141026                                        // skip handled members
    10151027                                        if ( ! unhandled.count( field ) ) continue;
     
    11301142                }
    11311143
    1132                 DeclarationWithType * MutatingResolver::mutate( ObjectDecl *objectDecl ) {
     1144                DeclarationWithType * MutatingResolver::mutate( ObjectDecl * objectDecl ) {
    11331145                        // add object to the indexer assumes that there will be no name collisions
    11341146                        // in generated code. If this changes, add mutate methods for entities with
     
    11381150                }
    11391151
    1140                 Expression* MutatingResolver::mutate( UntypedExpr *untypedExpr ) {
    1141                         return strict_dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untypedExpr, indexer ) );
    1142                 }
    1143 
    1144                 Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) {
     1152                Expression * MutatingResolver::mutate( UntypedExpr * untypedExpr ) {
     1153                        Expression * newExpr = untypedExpr;
     1154                        ResolvExpr::findVoidExpression( newExpr, indexer );
     1155                        return newExpr;
     1156                }
     1157
     1158                Expression * FixCtorExprs::postmutate( ConstructorExpr * ctorExpr ) {
    11451159                        static UniqueName tempNamer( "_tmp_ctor_expr" );
    11461160                        // xxx - is the size check necessary?
    1147                         assert( ctorExpr->has_result() && ctorExpr->get_result()->size() == 1 );
     1161                        assert( ctorExpr->result && ctorExpr->get_result()->size() == 1 );
    11481162
    11491163                        // xxx - ideally we would reuse the temporary generated from the copy constructor passes from within firstArg if it exists and not generate a temporary if it's unnecessary.
    1150                         ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr );
    1151                         addDeclaration( tmp );
     1164                        ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), ctorExpr->get_result()->clone(), nullptr );
     1165                        declsToAddBefore.push_back( tmp );
    11521166
    11531167                        // xxx - this can be TupleAssignExpr now. Need to properly handle this case.
     
    11581172                        delete ctorExpr;
    11591173
     1174                        // build assignment and replace constructor's first argument with new temporary
    11601175                        Expression *& firstArg = callExpr->get_args().front();
    1161 
    1162                         // xxx - hack in 'fake' assignment operator until resolver can easily be called in this pass. Once the resolver can be used in PassVisitor, this hack goes away.
    1163 
    1164                         // generate the type of assignment operator using the type of tmp minus any reference types
    1165                         Type * type = tmp->get_type()->stripReferences();
    1166                         FunctionType * ftype = SymTab::genAssignType( type );
    1167 
    1168                         // generate fake assignment decl and call it using &tmp and &firstArg
    1169                         // since tmp is guaranteed to be a reference and we want to assign pointers
    1170                         FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr );
    1171                         ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) );
    1172                         assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) );
    1173                         Expression * addrArg = new AddressExpr( firstArg );
    1174                         // if firstArg has type T&&, then &firstArg has type T*&.
    1175                         // Cast away the reference to a value type so that the argument
    1176                         // matches the assignment's parameter types
    1177                         if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) {
    1178                                 addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() );
    1179                         }
    1180                         assign->get_args().push_back( addrArg );
     1176                        Expression * assign = new UntypedExpr( new NameExpr( "?=?" ), { new AddressExpr( new VariableExpr( tmp ) ), new AddressExpr( firstArg ) } );
    11811177                        firstArg = new VariableExpr( tmp );
     1178
     1179                        // resolve assignment and dispose of new env
     1180                        ResolvExpr::findVoidExpression( assign, indexer );
     1181                        delete assign->env;
     1182                        assign->env = nullptr;
    11821183
    11831184                        // for constructor expr:
Note: See TracChangeset for help on using the changeset viewer.