Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r62e5546 r141b786  
    1818#include <iterator>
    1919#include <algorithm>
     20#include <unordered_map>
     21#include <unordered_set>
    2022#include "InitTweak.h"
    2123#include "FixInit.h"
     
    3537#include "GenPoly/DeclMutator.h"
    3638#include "SynTree/AddStmtVisitor.h"
    37 #include "CodeGen/GenType.h"  // for warnings
    38 
    39 bool ctordtorp = false;
    40 bool ctorp = false;
    41 bool cpctorp = false;
    42 bool dtorp = false;
     39#include "CodeGen/GenType.h"  // for warning/error messages
     40
     41bool ctordtorp = false; // print all debug
     42bool ctorp = false; // print ctor debug
     43bool cpctorp = false; // print copy ctor debug
     44bool dtorp = false; // print dtor debug
    4345#define PRINT( text ) if ( ctordtorp ) { text }
    4446#define CP_CTOR_PRINT( text ) if ( ctordtorp || cpctorp ) { text }
     
    4749namespace InitTweak {
    4850        namespace {
    49                 const std::list<Label> noLabels;
    50                 const std::list<Expression*> noDesignators;
    51 
    52                 class InsertImplicitCalls final : public GenPoly::PolyMutator {
     51                class InsertImplicitCalls : public GenPoly::PolyMutator {
    5352                public:
    5453                        /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
     
    5655                        static void insert( std::list< Declaration * > & translationUnit );
    5756
    58                         using GenPoly::PolyMutator::mutate;
    59                         virtual Expression * mutate( ApplicationExpr * appExpr ) override;
     57                        virtual Expression * mutate( ApplicationExpr * appExpr );
    6058                };
    6159
    62                 class ResolveCopyCtors final : public SymTab::Indexer {
     60                class ResolveCopyCtors : public SymTab::Indexer {
    6361                public:
    6462                        /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr,
     
    6765                        static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
    6866
    69                         using SymTab::Indexer::visit;
    70                         virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
     67                        typedef SymTab::Indexer Parent;
     68                        using Parent::visit;
     69
     70                        virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr );
     71                        virtual void visit( UniqueExpr * unqExpr );
    7172
    7273                        /// create and resolve ctor/dtor expression: fname(var, [cpArg])
    73                         ApplicationExpr * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );
     74                        Expression * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );
     75                        Expression * makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg = NULL );
    7476                        /// true if type does not need to be copy constructed to ensure correctness
    75                         bool skipCopyConstruct( Type * );
     77                        bool skipCopyConstruct( Type * type );
     78                        void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );
     79                        void destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
    7680                private:
    7781                        TypeSubstitution * env;
     
    8488                        using Parent::visit;
    8589                        typedef std::set< ObjectDecl * > ObjectSet;
    86                         virtual void visit( CompoundStmt *compoundStmt ) override;
    87                         virtual void visit( DeclStmt *stmt ) override;
     90                        virtual void visit( CompoundStmt *compoundStmt );
     91                        virtual void visit( DeclStmt *stmt );
    8892                  protected:
    8993                        ObjectSet curVars;
     
    105109                }
    106110
    107                 class LabelFinder final : public ObjDeclCollector {
     111                class LabelFinder : public ObjDeclCollector {
    108112                  public:
    109113                        typedef ObjDeclCollector Parent;
     
    119123                        // subclasses are added, there is only one place that the code has to be updated, rather than ensure that
    120124                        // every specialized class knows about every new kind of statement that might be added.
    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 ); }
     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 ); }
    138141                };
    139142
    140                 class InsertDtors final : public ObjDeclCollector {
     143                class InsertDtors : public ObjDeclCollector {
    141144                public:
    142145                        /// insert destructor calls at the appropriate places.  must happen before CtorInit nodes are removed
     
    150153                        InsertDtors( LabelFinder & finder ) : labelVars( finder.vars ) {}
    151154
    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;
     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 );
    159160                private:
    160161                        void handleGoto( BranchStmt * stmt );
     
    164165                };
    165166
    166                 class FixInit final : public GenPoly::PolyMutator {
     167                class FixInit : public GenPoly::PolyMutator {
    167168                  public:
    168169                        /// expand each object declaration to use its constructor after it is declared.
    169170                        static void fixInitializers( std::list< Declaration * > &translationUnit );
    170171
    171                         using GenPoly::PolyMutator::mutate;
    172                         virtual DeclarationWithType * mutate( ObjectDecl *objDecl ) override;
     172                        virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
    173173
    174174                        std::list< Declaration * > staticDtorDecls;
    175175                };
    176176
    177                 class FixCopyCtors final : public GenPoly::PolyMutator {
     177                class FixCopyCtors : 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                         using GenPoly::PolyMutator::mutate;
    184                         virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
     183                        virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr );
     184                        virtual Expression * mutate( UniqueExpr * unqExpr );
    185185                };
    186186
    187                 class GenStructMemberCalls final : public SymTab::Indexer {
     187                class GenStructMemberCalls : public SymTab::Indexer {
    188188                  public:
    189189                        typedef Indexer Parent;
     
    193193                        static void generate( std::list< Declaration * > & translationUnit );
    194194
    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;
     195                        virtual void visit( FunctionDecl * funcDecl );
     196
     197                        virtual void visit( MemberExpr * memberExpr );
     198                        virtual void visit( ApplicationExpr * appExpr );
    201199
    202200                        SemanticError errors;
     
    216214                // resolve UntypedExprs that are found within newly
    217215                // generated constructor/destructor calls
    218                 class MutatingResolver final : public Mutator {
     216                class MutatingResolver : public Mutator {
    219217                  public:
    220218                        MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {}
    221219
    222                         using Mutator::mutate;
    223                         virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ) override;
    224                         virtual Expression* mutate( UntypedExpr *untypedExpr ) override;
    225 
    226                   private:
     220                        virtual DeclarationWithType* mutate( ObjectDecl *objectDecl );
     221
     222                        virtual Expression* mutate( UntypedExpr *untypedExpr );
     223                        private:
    227224                        SymTab::Indexer & indexer;
    228225                };
    229226
    230                 class FixCtorExprs final : public GenPoly::DeclMutator {
     227                class FixCtorExprs : public GenPoly::DeclMutator {
    231228                  public:
    232229                        /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
    233230                        static void fix( std::list< Declaration * > & translationUnit );
    234231
    235                         using GenPoly::DeclMutator::mutate;
    236                         virtual Expression * mutate( ConstructorExpr * ctorExpr ) override;
     232                        virtual Expression * mutate( ConstructorExpr * ctorExpr );
    237233                };
    238234        } // namespace
     
    368364                }
    369365
    370                 ApplicationExpr * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
     366                Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
    371367                        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 );
    372373                        UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) );
    373                         untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ) );
     374                        untyped->get_args().push_back( thisArg );
    374375                        if (cpArg) untyped->get_args().push_back( cpArg->clone() );
    375376
     
    378379                        // (VariableExpr and already resolved expression)
    379380                        CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
    380                         ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) );
     381                        Expression * resolved = ResolvExpr::findVoidExpression( untyped, *this );
     382                        assert( resolved );
    381383                        if ( resolved->get_env() ) {
    382384                                env->add( *resolved->get_env() );
    383385                        } // if
    384386
    385                         assert( resolved );
    386387                        delete untyped;
    387388                        return resolved;
    388389                }
    389390
     391                void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {
     392                        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 ) ) {
     409                                // if the chosen constructor is intrinsic, the copy is unnecessary, so
     410                                // don't create the temporary and don't call the copy constructor
     411                                VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
     412                                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
    390426                void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
    391                         static UniqueName tempNamer("_tmp_cp");
    392                         static UniqueName retNamer("_tmp_cp_ret");
    393 
    394427                        CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
    395                         Visitor::visit( impCpCtorExpr );
     428                        Parent::visit( impCpCtorExpr );
    396429                        env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer...
    397430
     
    400433                        // take each argument and attempt to copy construct it.
    401434                        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 
    417                                 // if the chosen constructor is intrinsic, the copy is unnecessary, so
    418                                 // don't create the temporary and don't call the copy constructor
    419                                 VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() );
    420                                 assert( function );
    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
     435                                copyConstructArg( arg, impCpCtorExpr );
    427436                        } // for
    428437
     
    434443                        // level. Trying to pass that environment along.
    435444                        callExpr->set_env( impCpCtorExpr->get_env()->clone() );
    436                         for ( Type * result : appExpr->get_results() ) {
     445                        Type * result = appExpr->get_result();
     446                        if ( ! result->isVoid() ) {
     447                                static UniqueName retNamer("_tmp_cp_ret");
    437448                                result = result->clone();
    438449                                impCpCtorExpr->get_env()->apply( result );
     
    441452                                impCpCtorExpr->get_returnDecls().push_back( ret );
    442453                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    443                                 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
     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                                }
    444458                        } // for
    445459                        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() );
    446482                }
    447483
     
    490526                                // know the result type of the assignment is the type of the LHS (minus the pointer), so
    491527                                // add that onto the assignment expression so that later steps have the necessary information
    492                                 assign->add_result( returnDecl->get_type()->clone() );
     528                                assign->set_result( returnDecl->get_type()->clone() );
    493529
    494530                                Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
    495                                 if ( callExpr->get_results().front()->get_isLvalue() ) {
     531                                if ( callExpr->get_result()->get_isLvalue() ) {
    496532                                        // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning
    497533                                        // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the
     
    500536                                        // an AddressExpr.  Effectively, this turns
    501537                                        //   lvalue T f();
    502                                         //   &*f()
     538                                        //   &*f();
    503539                                        // into
     540                                        //   T * f();
    504541                                        //   T * tmp_cp_retN;
    505                                         //   tmp_cp_ret_N = &*(tmp_cp_ret_N = &*f(), tmp_cp_ret);
     542                                        //   &*(tmp_cp_retN = &*f(), tmp_cp_retN);              // the first * and second & are generated here
    506543                                        // which work out in terms of types, but is pretty messy. It would be nice to find a better way.
    507544                                        assign->get_args().back() = new AddressExpr( assign->get_args().back() );
    508545
    509                                         Type * resultType = returnDecl->get_type()->clone();
    510546                                        returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) );
    511                                         UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
    512                                         deref->get_args().push_back( retExpr );
    513                                         deref->add_result( resultType );
    514                                         retExpr = deref;
     547                                        retExpr->set_result( new PointerType( Type::Qualifiers(), retExpr->get_result() ) );
     548                                        retExpr = UntypedExpr::createDeref( retExpr );
    515549                                } // if
    516550                                retExpr->set_env( env->clone() );
     
    519553                                return callExpr;
    520554                        } // 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;
    521586                }
    522587
     
    9501015                Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) {
    9511016                        static UniqueName tempNamer( "_tmp_ctor_expr" );
    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 );
     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 );
    9541020                        addDeclaration( tmp );
    9551021
     
    9631029                        assign->get_args().push_back( new VariableExpr( tmp ) );
    9641030                        assign->get_args().push_back( firstArg );
    965                         cloneAll( ctorExpr->get_results(), assign->get_results() );
     1031                        assign->set_result( ctorExpr->get_result()->clone() );
    9661032                        firstArg = assign;
    9671033
Note: See TracChangeset for help on using the changeset viewer.