Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r141b786 r62e5546  
    1818#include <iterator>
    1919#include <algorithm>
    20 #include <unordered_map>
    21 #include <unordered_set>
    2220#include "InitTweak.h"
    2321#include "FixInit.h"
     
    3735#include "GenPoly/DeclMutator.h"
    3836#include "SynTree/AddStmtVisitor.h"
    39 #include "CodeGen/GenType.h"  // for warning/error messages
    40 
    41 bool ctordtorp = false; // print all debug
    42 bool ctorp = false; // print ctor debug
    43 bool cpctorp = false; // print copy ctor debug
    44 bool dtorp = false; // print dtor debug
     37#include "CodeGen/GenType.h"  // for warnings
     38
     39bool ctordtorp = false;
     40bool ctorp = false;
     41bool cpctorp = false;
     42bool dtorp = false;
    4543#define PRINT( text ) if ( ctordtorp ) { text }
    4644#define CP_CTOR_PRINT( text ) if ( ctordtorp || cpctorp ) { text }
     
    4947namespace InitTweak {
    5048        namespace {
    51                 class InsertImplicitCalls : public GenPoly::PolyMutator {
     49                const std::list<Label> noLabels;
     50                const std::list<Expression*> noDesignators;
     51
     52                class InsertImplicitCalls final : public GenPoly::PolyMutator {
    5253                public:
    5354                        /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
     
    5556                        static void insert( std::list< Declaration * > & translationUnit );
    5657
    57                         virtual Expression * mutate( ApplicationExpr * appExpr );
    58                 };
    59 
    60                 class ResolveCopyCtors : public SymTab::Indexer {
     58                        using GenPoly::PolyMutator::mutate;
     59                        virtual Expression * mutate( ApplicationExpr * appExpr ) override;
     60                };
     61
     62                class ResolveCopyCtors final : public SymTab::Indexer {
    6163                public:
    6264                        /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr,
     
    6567                        static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
    6668
    67                         typedef SymTab::Indexer Parent;
    68                         using Parent::visit;
    69 
    70                         virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr );
    71                         virtual void visit( UniqueExpr * unqExpr );
     69                        using SymTab::Indexer::visit;
     70                        virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
    7271
    7372                        /// create and resolve ctor/dtor expression: fname(var, [cpArg])
    74                         Expression * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );
    75                         Expression * makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg = NULL );
     73                        ApplicationExpr * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );
    7674                        /// true if type does not need to be copy constructed to ensure correctness
    77                         bool skipCopyConstruct( Type * type );
    78                         void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );
    79                         void destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
     75                        bool skipCopyConstruct( Type * );
    8076                private:
    8177                        TypeSubstitution * env;
     
    8884                        using Parent::visit;
    8985                        typedef std::set< ObjectDecl * > ObjectSet;
    90                         virtual void visit( CompoundStmt *compoundStmt );
    91                         virtual void visit( DeclStmt *stmt );
     86                        virtual void visit( CompoundStmt *compoundStmt ) override;
     87                        virtual void visit( DeclStmt *stmt ) override;
    9288                  protected:
    9389                        ObjectSet curVars;
     
    109105                }
    110106
    111                 class LabelFinder : public ObjDeclCollector {
     107                class LabelFinder final : public ObjDeclCollector {
    112108                  public:
    113109                        typedef ObjDeclCollector Parent;
     
    123119                        // subclasses are added, there is only one place that the code has to be updated, rather than ensure that
    124120                        // every specialized class knows about every new kind of statement that might be added.
    125                         virtual void visit( CompoundStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    126                         virtual void visit( ExprStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    127                         virtual void visit( AsmStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    128                         virtual void visit( IfStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    129                         virtual void visit( WhileStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    130                         virtual void visit( ForStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    131                         virtual void visit( SwitchStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    132                         virtual void visit( CaseStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    133                         virtual void visit( BranchStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    134                         virtual void visit( ReturnStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    135                         virtual void visit( TryStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    136                         virtual void visit( CatchStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    137                         virtual void visit( FinallyStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    138                         virtual void visit( NullStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    139                         virtual void visit( DeclStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    140                         virtual void visit( ImplicitCtorDtorStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    141                 };
    142 
    143                 class InsertDtors : public ObjDeclCollector {
     121                        using Parent::visit;
     122                        virtual void visit( CompoundStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     123                        virtual void visit( ExprStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     124                        virtual void visit( AsmStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     125                        virtual void visit( IfStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     126                        virtual void visit( WhileStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     127                        virtual void visit( ForStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     128                        virtual void visit( SwitchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     129                        virtual void visit( CaseStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     130                        virtual void visit( BranchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     131                        virtual void visit( ReturnStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     132                        virtual void visit( TryStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     133                        virtual void visit( CatchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     134                        virtual void visit( FinallyStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     135                        virtual void visit( NullStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     136                        virtual void visit( DeclStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     137                        virtual void visit( ImplicitCtorDtorStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     138                };
     139
     140                class InsertDtors final : public ObjDeclCollector {
    144141                public:
    145142                        /// insert destructor calls at the appropriate places.  must happen before CtorInit nodes are removed
     
    153150                        InsertDtors( LabelFinder & finder ) : labelVars( finder.vars ) {}
    154151
    155                         virtual void visit( ObjectDecl * objDecl );
    156 
    157                         virtual void visit( CompoundStmt * compoundStmt );
    158                         virtual void visit( ReturnStmt * returnStmt );
    159                         virtual void visit( BranchStmt * stmt );
     152                        using Parent::visit;
     153
     154                        virtual void visit( ObjectDecl * objDecl ) override;
     155
     156                        virtual void visit( CompoundStmt * compoundStmt ) override;
     157                        virtual void visit( ReturnStmt * returnStmt ) override;
     158                        virtual void visit( BranchStmt * stmt ) override;
    160159                private:
    161160                        void handleGoto( BranchStmt * stmt );
     
    165164                };
    166165
    167                 class FixInit : public GenPoly::PolyMutator {
     166                class FixInit final : public GenPoly::PolyMutator {
    168167                  public:
    169168                        /// expand each object declaration to use its constructor after it is declared.
    170169                        static void fixInitializers( std::list< Declaration * > &translationUnit );
    171170
    172                         virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
     171                        using GenPoly::PolyMutator::mutate;
     172                        virtual DeclarationWithType * mutate( ObjectDecl *objDecl ) override;
    173173
    174174                        std::list< Declaration * > staticDtorDecls;
    175175                };
    176176
    177                 class FixCopyCtors : public GenPoly::PolyMutator {
     177                class FixCopyCtors final : public GenPoly::PolyMutator {
    178178                  public:
    179179                        /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, call expression,
     
    181181                        static void fixCopyCtors( std::list< Declaration * > &translationUnit );
    182182
    183                         virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr );
    184                         virtual Expression * mutate( UniqueExpr * unqExpr );
    185                 };
    186 
    187                 class GenStructMemberCalls : public SymTab::Indexer {
     183                        using GenPoly::PolyMutator::mutate;
     184                        virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
     185                };
     186
     187                class GenStructMemberCalls final : public SymTab::Indexer {
    188188                  public:
    189189                        typedef Indexer Parent;
     
    193193                        static void generate( std::list< Declaration * > & translationUnit );
    194194
    195                         virtual void visit( FunctionDecl * funcDecl );
    196 
    197                         virtual void visit( MemberExpr * memberExpr );
    198                         virtual void visit( ApplicationExpr * appExpr );
     195                        using Parent::visit;
     196
     197                        virtual void visit( FunctionDecl * funcDecl ) override;
     198
     199                        virtual void visit( MemberExpr * memberExpr ) override;
     200                        virtual void visit( ApplicationExpr * appExpr ) override;
    199201
    200202                        SemanticError errors;
     
    214216                // resolve UntypedExprs that are found within newly
    215217                // generated constructor/destructor calls
    216                 class MutatingResolver : public Mutator {
     218                class MutatingResolver final : public Mutator {
    217219                  public:
    218220                        MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {}
    219221
    220                         virtual DeclarationWithType* mutate( ObjectDecl *objectDecl );
    221 
    222                         virtual Expression* mutate( UntypedExpr *untypedExpr );
    223                         private:
     222                        using Mutator::mutate;
     223                        virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ) override;
     224                        virtual Expression* mutate( UntypedExpr *untypedExpr ) override;
     225
     226                  private:
    224227                        SymTab::Indexer & indexer;
    225228                };
    226229
    227                 class FixCtorExprs : public GenPoly::DeclMutator {
     230                class FixCtorExprs final : public GenPoly::DeclMutator {
    228231                  public:
    229232                        /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
    230233                        static void fix( std::list< Declaration * > & translationUnit );
    231234
    232                         virtual Expression * mutate( ConstructorExpr * ctorExpr );
     235                        using GenPoly::DeclMutator::mutate;
     236                        virtual Expression * mutate( ConstructorExpr * ctorExpr ) override;
    233237                };
    234238        } // namespace
     
    364368                }
    365369
    366                 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
     370                ApplicationExpr * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
    367371                        assert( var );
    368                         return makeCtorDtor( fname, new AddressExpr( new VariableExpr( var ) ), cpArg );
    369                 }
    370 
    371                 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg ) {
    372                         assert( thisArg );
    373372                        UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) );
    374                         untyped->get_args().push_back( thisArg );
     373                        untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ) );
    375374                        if (cpArg) untyped->get_args().push_back( cpArg->clone() );
    376375
     
    379378                        // (VariableExpr and already resolved expression)
    380379                        CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
    381                         Expression * resolved = ResolvExpr::findVoidExpression( untyped, *this );
    382                         assert( resolved );
     380                        ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) );
    383381                        if ( resolved->get_env() ) {
    384382                                env->add( *resolved->get_env() );
    385383                        } // if
    386384
     385                        assert( resolved );
    387386                        delete untyped;
    388387                        return resolved;
    389388                }
    390389
    391                 void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {
     390                void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
    392391                        static UniqueName tempNamer("_tmp_cp");
    393                         CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; )
    394                         assert( arg->has_result() );
    395                         Type * result = arg->get_result();
    396                         if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types
    397 
    398                         // type may involve type variables, so apply type substitution to get temporary variable's actual type
    399                         result = result->clone();
    400                         impCpCtorExpr->get_env()->apply( result );
    401                         ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
    402                         tmp->get_type()->set_isConst( false );
    403 
    404                         // create and resolve copy constructor
    405                         CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; )
    406                         Expression * cpCtor = makeCtorDtor( "?{}", tmp, arg );
    407 
    408                         if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( cpCtor ) ) {
     392                        static UniqueName retNamer("_tmp_cp_ret");
     393
     394                        CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
     395                        Visitor::visit( impCpCtorExpr );
     396                        env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer...
     397
     398                        ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr();
     399
     400                        // take each argument and attempt to copy construct it.
     401                        for ( Expression * & arg : appExpr->get_args() ) {
     402                                CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; )
     403                                // xxx - need to handle tuple arguments
     404                                assert( ! arg->get_results().empty() );
     405                                Type * result = arg->get_results().front();
     406                                if ( skipCopyConstruct( result ) ) continue; // skip certain non-copyable types
     407                                // type may involve type variables, so apply type substitution to get temporary variable's actual type
     408                                result = result->clone();
     409                                impCpCtorExpr->get_env()->apply( result );
     410                                ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
     411                                tmp->get_type()->set_isConst( false );
     412
     413                                // create and resolve copy constructor
     414                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; )
     415                                ApplicationExpr * cpCtor = makeCtorDtor( "?{}", tmp, arg );
     416
    409417                                // if the chosen constructor is intrinsic, the copy is unnecessary, so
    410418                                // don't create the temporary and don't call the copy constructor
    411                                 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
     419                                VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() );
    412420                                assert( function );
    413                                 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
    414                         }
    415 
    416                         // replace argument to function call with temporary
    417                         arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
    418                         impCpCtorExpr->get_tempDecls().push_back( tmp );
    419                         impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
    420                 }
    421 
    422                 void ResolveCopyCtors::destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr ) {
    423                         impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", new AddressExpr( ret ) ) );
    424                 }
    425 
    426                 void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
    427                         CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
    428                         Parent::visit( impCpCtorExpr );
    429                         env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer...
    430 
    431                         ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr();
    432 
    433                         // take each argument and attempt to copy construct it.
    434                         for ( Expression * & arg : appExpr->get_args() ) {
    435                                 copyConstructArg( arg, impCpCtorExpr );
     421                                if ( function->get_var()->get_linkage() != LinkageSpec::Intrinsic ) {
     422                                        // replace argument to function call with temporary
     423                                        arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
     424                                        impCpCtorExpr->get_tempDecls().push_back( tmp );
     425                                        impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
     426                                } // if
    436427                        } // for
    437428
     
    443434                        // level. Trying to pass that environment along.
    444435                        callExpr->set_env( impCpCtorExpr->get_env()->clone() );
    445                         Type * result = appExpr->get_result();
    446                         if ( ! result->isVoid() ) {
    447                                 static UniqueName retNamer("_tmp_cp_ret");
     436                        for ( Type * result : appExpr->get_results() ) {
    448437                                result = result->clone();
    449438                                impCpCtorExpr->get_env()->apply( result );
     
    452441                                impCpCtorExpr->get_returnDecls().push_back( ret );
    453442                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    454                                 if ( ! result->get_isLvalue() ) {
    455                                         // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    456                                         destructRet( new VariableExpr( ret ), impCpCtorExpr );
    457                                 }
     443                                impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
    458444                        } // for
    459445                        CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; )
    460                 }
    461 
    462                 void ResolveCopyCtors::visit( UniqueExpr * unqExpr ) {
    463                         static std::unordered_set< int > vars;
    464                         if ( vars.count( unqExpr->get_id() ) ) {
    465                                 // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
    466                                 return;
    467                         }
    468 
    469                         Parent::visit( unqExpr );
    470                         // it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought
    471                         assert( unqExpr->get_result() );
    472                         if ( ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast<ImplicitCopyCtorExpr*>( unqExpr->get_expr() ) ) {
    473                                 // note the variable used as the result from the call
    474                                 assert( impCpCtorExpr->get_result() && impCpCtorExpr->get_returnDecls().size() == 1 );
    475                                 unqExpr->set_var( new VariableExpr( impCpCtorExpr->get_returnDecls().front() ) );
    476                         } else {
    477                                 // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
    478                                 unqExpr->set_object( new ObjectDecl( toString("_unq_expr_", unqExpr->get_id()), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) );
    479                                 unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) );
    480                         }
    481                         vars.insert( unqExpr->get_id() );
    482446                }
    483447
     
    526490                                // know the result type of the assignment is the type of the LHS (minus the pointer), so
    527491                                // add that onto the assignment expression so that later steps have the necessary information
    528                                 assign->set_result( returnDecl->get_type()->clone() );
     492                                assign->add_result( returnDecl->get_type()->clone() );
    529493
    530494                                Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
    531                                 if ( callExpr->get_result()->get_isLvalue() ) {
     495                                if ( callExpr->get_results().front()->get_isLvalue() ) {
    532496                                        // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning
    533497                                        // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the
     
    536500                                        // an AddressExpr.  Effectively, this turns
    537501                                        //   lvalue T f();
    538                                         //   &*f();
     502                                        //   &*f()
    539503                                        // into
    540                                         //   T * f();
    541504                                        //   T * tmp_cp_retN;
    542                                         //   &*(tmp_cp_retN = &*f(), tmp_cp_retN);              // the first * and second & are generated here
     505                                        //   tmp_cp_ret_N = &*(tmp_cp_ret_N = &*f(), tmp_cp_ret);
    543506                                        // which work out in terms of types, but is pretty messy. It would be nice to find a better way.
    544507                                        assign->get_args().back() = new AddressExpr( assign->get_args().back() );
    545508
     509                                        Type * resultType = returnDecl->get_type()->clone();
    546510                                        returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) );
    547                                         retExpr->set_result( new PointerType( Type::Qualifiers(), retExpr->get_result() ) );
    548                                         retExpr = UntypedExpr::createDeref( retExpr );
     511                                        UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
     512                                        deref->get_args().push_back( retExpr );
     513                                        deref->add_result( resultType );
     514                                        retExpr = deref;
    549515                                } // if
    550516                                retExpr->set_env( env->clone() );
     
    553519                                return callExpr;
    554520                        } // if
    555                 }
    556 
    557                 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
    558                         static std::unordered_map< int, UniqueExpr * > unqMap;
    559                         static std::unordered_set< int > addDeref;
    560                         // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes
    561                         unqExpr = safe_dynamic_cast< UniqueExpr * >( Parent::mutate( unqExpr ) );
    562                         if ( unqMap.count( unqExpr->get_id() ) ) {
    563                                 // take data from other UniqueExpr to ensure consistency
    564                                 delete unqExpr->get_expr();
    565                                 unqExpr->set_expr( unqMap[unqExpr->get_id()]->get_expr()->clone() );
    566                                 delete unqExpr->get_result();
    567                                 unqExpr->set_result( maybeClone( unqExpr->get_expr()->get_result() ) );
    568                                 if ( addDeref.count( unqExpr->get_id() ) ) {
    569                                         // other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too
    570                                         return UntypedExpr::createDeref( unqExpr );
    571                                 }
    572                                 return unqExpr;
    573                         }
    574                         unqMap[unqExpr->get_id()] = unqExpr;
    575                         if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) {
    576                                 // unique expression is now a dereference, because the inner expression is an lvalue returning function call.
    577                                 // Normalize the expression by dereferencing the unique expression, rather than the inner expression
    578                                 // (i.e. move the dereference out a level)
    579                                 assert( getFunctionName( deref ) == "*?" );
    580                                 unqExpr->set_expr( getCallArg( deref, 0 ) );
    581                                 getCallArg( deref, 0 ) = unqExpr;
    582                                 addDeref.insert( unqExpr->get_id() );
    583                                 return deref;
    584                         }
    585                         return unqExpr;
    586521                }
    587522
     
    1015950                Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) {
    1016951                        static UniqueName tempNamer( "_tmp_ctor_expr" );
    1017                         // xxx - is the size check necessary?
    1018                         assert( ctorExpr->has_result() && ctorExpr->get_result()->size() == 1 );
    1019                         ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr );
     952                        assert( ctorExpr->get_results().size() == 1 );
     953                        ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, ctorExpr->get_results().front()->clone(), nullptr );
    1020954                        addDeclaration( tmp );
    1021955
     
    1029963                        assign->get_args().push_back( new VariableExpr( tmp ) );
    1030964                        assign->get_args().push_back( firstArg );
    1031                         assign->set_result( ctorExpr->get_result()->clone() );
     965                        cloneAll( ctorExpr->get_results(), assign->get_results() );
    1032966                        firstArg = assign;
    1033967
Note: See TracChangeset for help on using the changeset viewer.