Changes in / [596f987b:66f8528]


Ignore:
Location:
src
Files:
8 added
63 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    r596f987b r66f8528  
    179179                        output << aggDecl->get_name();
    180180
    181                 std::list< Declaration * > & memb = aggDecl->get_members();
    182                 if ( ! memb.empty() ) {
    183 //              if ( aggDecl->has_body() ) {
    184 //                      std::list< Declaration * > & memb = aggDecl->get_members();
     181                // std::list< Declaration * > & memb = aggDecl->get_members();
     182                // if ( ! memb.empty() ) {
     183                if ( aggDecl->has_body() ) {
     184                        std::list< Declaration * > & memb = aggDecl->get_members();
    185185                        output << " {" << endl;
    186186
     
    291291                } // if
    292292                output << " }";
     293        }
     294
     295        void CodeGenerator::visit( ConstructorInit * init ){
     296                assertf( false, "ConstructorInit nodes should not make it to CodeGen." );
    293297        }
    294298
     
    917921                } // switch
    918922        }
     923
     924        std::string genName( DeclarationWithType * decl ) {
     925                CodeGen::OperatorInfo opInfo;
     926                if ( operatorLookup( decl->get_name(), opInfo ) ) {
     927                        return opInfo.outputName;
     928                } else {
     929                        return decl->get_name();
     930                } // if
     931        }
    919932} // namespace CodeGen
    920933
  • src/CodeGen/CodeGenerator.h

    r596f987b r66f8528  
    4747                virtual void visit( SingleInit * );
    4848                virtual void visit( ListInit * );
     49                virtual void visit( ConstructorInit * );
    4950
    5051                //*** Constant
     
    144145                return true;
    145146        }
     147
     148        /// returns C-compatible name of declaration
     149        std::string genName( DeclarationWithType * decl );
    146150} // namespace CodeGen
    147151
  • src/GenPoly/Box.cc

    r596f987b r66f8528  
    5555#include "Common/utility.h"
    5656
     57#include "InitTweak/InitTweak.h"
     58
    5759#include <ext/functional> // temporary
    5860
     
    98100                        void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes );
    99101                        /// passes extra type parameters into a polymorphic function application
    100                         void passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
     102                        void passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    101103                        /// wraps a function application with a new temporary for the out-parameter return value
    102104                        Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg );
     
    107109                        Type *replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone = true );
    108110                        /// wraps a function application returning a polymorphic type with a new temporary for the out-parameter return value
    109                         Expression *addDynRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg );
     111                        Expression *addDynRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *polyType, std::list< Expression *>::iterator &arg );
    110112                        Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    111113                        void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars );
     
    113115                        void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars );
    114116                        /// Stores assignment operators from assertion list in local map of assignment operations
    115                         void findTypeOps( const Type::ForallList &forall );
    116117                        void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
    117118                        FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
     
    121122                        ObjectDecl *makeTemporary( Type *type );
    122123
    123                         ScopedMap< std::string, DeclarationWithType* > assignOps;    ///< Currently known type variable assignment operators
    124                         ScopedMap< std::string, DeclarationWithType* > ctorOps;      ///< Currently known type variable constructors
    125                         ScopedMap< std::string, DeclarationWithType* > copyOps;      ///< Currently known type variable copy constructors
    126                         ScopedMap< std::string, DeclarationWithType* > dtorOps;      ///< Currently known type variable destructors
    127                         ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;  ///< Currently known assignment operators
    128                         ResolvExpr::TypeMap< DeclarationWithType > scopedCtorOps;    ///< Currently known assignment operators
    129                         ResolvExpr::TypeMap< DeclarationWithType > scopedCopyOps;    ///< Currently known assignment operators
    130                         ResolvExpr::TypeMap< DeclarationWithType > scopedDtorOps;    ///< Currently known assignment operators
    131124                        ScopedMap< std::string, DeclarationWithType* > adapters;     ///< Set of adapter functions in the current scope
    132125
     126                        std::map< ApplicationExpr *, Expression * > retVals;
     127
    133128                        DeclarationWithType *retval;
    134                         bool useRetval;
    135129                        UniqueName tempNamer;
    136130                };
     
    275269
    276270                for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
    277                         if ( (*decl)->get_kind() == TypeDecl::Any ) {
     271                        if ( (*decl)->isComplete() ) {
    278272                                otypeDecls.push_back( *decl );
    279273                        }
     
    497491                }
    498492
    499                 Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {}
    500 
    501                 /// Returns T if the given declaration is a function with parameter (T*) for some TypeInstType T, NULL otherwise
    502                 TypeInstType *isTypeInstPtrFn( DeclarationWithType *decl ) {
    503                         if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
    504                                 if ( funType->get_parameters().size() == 1 ) {
    505                                         if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
    506                                                 if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
    507                                                         return refType;
    508                                                 } // if
    509                                         } // if
    510                                 } // if
    511                         } // if
    512                         return 0;
    513                 }
    514 
    515                 /// Returns T if the given declaration is a function with parameters (T*, T) for some TypeInstType T, NULL otherwise
    516                 TypeInstType *isTypeInstPtrValFn( DeclarationWithType *decl ) {
    517                         if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
    518                                 if ( funType->get_parameters().size() == 2 ) {
    519                                         if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
    520                                                 if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
    521                                                         if ( TypeInstType *refType2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) {
    522                                                                 if ( refType->get_name() == refType2->get_name() ) {
    523                                                                         return refType;
    524                                                                 } // if
    525                                                         } // if
    526                                                 } // if
    527                                         } // if
    528                                 } // if
    529                         } // if
    530                         return 0;
    531                 }
    532 
    533                 /// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
    534                 TypeInstType *isTypeInstAssignment( DeclarationWithType *decl ) {
    535                         return decl->get_name() == "?=?" ? isTypeInstPtrValFn( decl ) : 0;
    536                 }
    537 
    538                 /// Returns T if the given declaration is (*?{})(T *) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
    539                 TypeInstType *isTypeInstCtor( DeclarationWithType *decl ) {
    540                         return decl->get_name() == "?{}" ? isTypeInstPtrFn( decl ) : 0;
    541                 }
    542 
    543                 /// Returns T if the given declaration is (*?{})(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
    544                 TypeInstType *isTypeInstCopy( DeclarationWithType *decl ) {
    545                         return decl->get_name() == "?{}" ? isTypeInstPtrValFn( decl ) : 0;
    546                 }
    547 
    548                 /// Returns T if the given declaration is (*^?{})(T *) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
    549                 TypeInstType *isTypeInstDtor( DeclarationWithType *decl ) {
    550                         return decl->get_name() == "^?{}" ? isTypeInstPtrFn( decl ) : 0;
    551                 }
    552 
    553                 /// Returns T if the given declaration is a function with parameters (T*, T) for some type T, where neither parameter is cv-qualified,
    554                 /// NULL otherwise
    555                 Type *isNoCvPtrFn( DeclarationWithType *decl ) {
    556                         if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
    557                                 if ( funType->get_parameters().size() == 1 ) {
    558                                         Type::Qualifiers defaultQualifiers;
    559                                         Type *paramType = funType->get_parameters().front()->get_type();
    560                                         if ( paramType->get_qualifiers() != defaultQualifiers ) return 0;
    561 
    562                                         if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType ) ) {
    563                                                 Type *baseType = pointerType->get_base();
    564                                                 if ( baseType->get_qualifiers() == defaultQualifiers ) {
    565                                                         return baseType;
    566                                                 } // if
    567                                         } // if
    568                                 } // if
    569                         } // if
    570                         return 0;
    571                 }
    572 
    573                 /// Returns T if the given declaration is a function with parameters (T*, T) for some type T, where neither parameter is cv-qualified,
    574                 /// NULL otherwise
    575                 Type *isNoCvPtrValFn( DeclarationWithType *decl ) {
    576                         if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
    577                                 if ( funType->get_parameters().size() == 2 ) {
    578                                         Type::Qualifiers defaultQualifiers;
    579                                         Type *paramType1 = funType->get_parameters().front()->get_type();
    580                                         if ( paramType1->get_qualifiers() != defaultQualifiers ) return 0;
    581                                         Type *paramType2 = funType->get_parameters().back()->get_type();
    582                                         if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0;
    583 
    584                                         if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) {
    585                                                 Type *baseType1 = pointerType->get_base();
    586                                                 if ( baseType1->get_qualifiers() != defaultQualifiers ) return 0;
    587                                                 SymTab::Indexer dummy;
    588                                                 if ( ResolvExpr::typesCompatible( baseType1, paramType2, dummy ) ) {
    589                                                         return baseType1;
    590                                                 } // if
    591                                         } // if
    592                                 } // if
    593                         } // if
    594                         return 0;
    595                 }
    596 
    597                 /// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise
    598                 /// Only picks assignments where neither parameter is cv-qualified
    599                 Type *isAssignment( DeclarationWithType *decl ) {
    600                         return decl->get_name() == "?=?" ? isNoCvPtrValFn( decl ) : 0;
    601                 }
    602 
    603                 /// returns T if the given declaration is: (*?{})(T *) for some type T, NULL otherwise
    604                 /// Only picks ctors where the parameter is not cv-qualified
    605                 Type *isCtor( DeclarationWithType *decl ) {
    606                         return decl->get_name() == "?{}" ? isNoCvPtrFn( decl ) : 0;
    607                 }
    608 
    609                 /// returns T if the given declaration is: (*?{})(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise
    610                 /// Only picks copy constructors where neither parameter is cv-qualified
    611                 Type *isCopy( DeclarationWithType *decl ) {
    612                         return decl->get_name() == "?{}" ? isNoCvPtrValFn( decl ) : 0;
    613                 }
    614 
    615                 /// returns T if the given declaration is: (*?{})(T *) for some type T, NULL otherwise
    616                 /// Only picks ctors where the parameter is not cv-qualified
    617                 Type *isDtor( DeclarationWithType *decl ) {
    618                         return decl->get_name() == "^?{}" ? isNoCvPtrFn( decl ) : 0;
    619                 }
    620 
    621                 void Pass1::findTypeOps( const Type::ForallList &forall ) {
    622                         // what if a nested function uses an assignment operator?
    623                         // assignOps.clear();
    624                         for ( Type::ForallList::const_iterator i = forall.begin(); i != forall.end(); ++i ) {
    625                                 for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
    626                                         std::string typeName;
    627                                         if ( TypeInstType *typeInst = isTypeInstAssignment( *assert ) ) {
    628                                                 assignOps[ typeInst->get_name() ] = *assert;
    629                                         } else if ( TypeInstType *typeInst = isTypeInstCtor( *assert ) ) {
    630                                                 ctorOps[ typeInst->get_name() ] = *assert;
    631                                         } else if ( TypeInstType *typeInst = isTypeInstCopy( *assert ) ) {
    632                                                 copyOps[ typeInst->get_name() ] = *assert;
    633                                         } else if ( TypeInstType *typeInst = isTypeInstDtor( *assert ) ) {
    634                                                 dtorOps[ typeInst->get_name() ] = *assert;
    635                                         } // if
    636                                 } // for
    637                         } // for
    638                 }
     493                Pass1::Pass1() : tempNamer( "_temp" ) {}
    639494
    640495                DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
    641                         // if this is a assignment function, put it in the map for this scope
    642                         if ( Type *paramType = isAssignment( functionDecl ) ) {
    643                                 if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {
    644                                         scopedAssignOps.insert( paramType, functionDecl );
    645                                 }
    646                         } else if ( Type *paramType = isCtor( functionDecl ) ) {
    647                                 if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {
    648                                         scopedCtorOps.insert( paramType, functionDecl );
    649                                 }
    650                         } else if ( Type *paramType = isCopy( functionDecl ) ) {
    651                                 if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {
    652                                         scopedCopyOps.insert( paramType, functionDecl );
    653                                 }
    654                         } else if ( Type *paramType = isDtor( functionDecl ) ) {
    655                                 if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {
    656                                         scopedDtorOps.insert( paramType, functionDecl );
    657                                 }
    658                         }
    659 
    660496                        if ( functionDecl->get_statements() ) {         // empty routine body ?
    661497                                doBeginScope();
    662498                                scopeTyVars.beginScope();
    663                                 assignOps.beginScope();
    664                                 ctorOps.beginScope();
    665                                 copyOps.beginScope();
    666                                 dtorOps.beginScope();
    667499
    668500                                DeclarationWithType *oldRetval = retval;
    669                                 bool oldUseRetval = useRetval;
    670501
    671502                                // process polymorphic return value
    672                                 retval = 0;
    673                                 if ( isDynRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
     503                                retval = nullptr;
     504                                if ( isDynRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() != LinkageSpec::C ) {
    674505                                        retval = functionDecl->get_functionType()->get_returnVals().front();
    675506
     
    683514                                FunctionType *functionType = functionDecl->get_functionType();
    684515                                makeTyVarMap( functionDecl->get_functionType(), scopeTyVars );
    685                                 findTypeOps( functionDecl->get_functionType()->get_forall() );
    686516
    687517                                std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
     
    700530                                        if ( adapters.find( mangleName ) == adapters.end() ) {
    701531                                                std::string adapterName = makeAdapterName( mangleName );
    702                                                 adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0 ) ) );
     532                                                adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), nullptr ) ) );
    703533                                        } // if
    704534                                } // for
     
    707537
    708538                                scopeTyVars.endScope();
    709                                 assignOps.endScope();
    710                                 ctorOps.endScope();
    711                                 copyOps.endScope();
    712                                 dtorOps.endScope();
    713539                                retval = oldRetval;
    714                                 useRetval = oldUseRetval;
    715540                                doEndScope();
    716541                        } // if
     
    719544
    720545                TypeDecl *Pass1::mutate( TypeDecl *typeDecl ) {
    721                         scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
     546                        addToTyVarMap( typeDecl, scopeTyVars );
    722547                        return Mutator::mutate( typeDecl );
    723548                }
    724549
    725550                Expression *Pass1::mutate( CommaExpr *commaExpr ) {
    726                         bool oldUseRetval = useRetval;
    727                         useRetval = false;
     551                        // Attempting to find application expressions that were mutated by the copy constructor passes
     552                        // to use an explicit return variable, so that the variable can be reused as a parameter to the
     553                        // call rather than creating a new temp variable. Previously this step was an optimization, but
     554                        // with the introduction of tuples and UniqueExprs, it is necessary to ensure that they use the same variable.
     555                        // Essentially, looking for pattern: (x=f(...), x)
     556                        // To compound the issue, the right side can be *x, etc. because of lvalue-returning functions
     557                        if ( UntypedExpr * assign = dynamic_cast< UntypedExpr * >( commaExpr->get_arg1() ) ) {
     558                                if ( InitTweak::isAssignment( InitTweak::getFunctionName( assign ) ) ) {
     559                                        assert( assign->get_args().size() == 2 );
     560                                        if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( assign->get_args().back() ) ) {
     561                                                // first argument is assignable, so it must be an lvalue, so it should be legal to take its address.
     562                                                retVals[appExpr] = assign->get_args().front();
     563                                        }
     564                                }
     565                        }
     566
    728567                        commaExpr->set_arg1( maybeMutate( commaExpr->get_arg1(), *this ) );
    729                         useRetval = oldUseRetval;
    730568                        commaExpr->set_arg2( maybeMutate( commaExpr->get_arg2(), *this ) );
    731569                        return commaExpr;
     
    733571
    734572                Expression *Pass1::mutate( ConditionalExpr *condExpr ) {
    735                         bool oldUseRetval = useRetval;
    736                         useRetval = false;
    737573                        condExpr->set_arg1( maybeMutate( condExpr->get_arg1(), *this ) );
    738                         useRetval = oldUseRetval;
    739574                        condExpr->set_arg2( maybeMutate( condExpr->get_arg2(), *this ) );
    740575                        condExpr->set_arg3( maybeMutate( condExpr->get_arg3(), *this ) );
     
    769604                }
    770605
    771                 void Pass1::passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
     606                void Pass1::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
    772607                        // pass size/align for type variables
    773608                        for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) {
    774609                                ResolvExpr::EqvClass eqvClass;
    775610                                assert( env );
    776                                 if ( tyParm->second == TypeDecl::Any ) {
     611                                if ( tyParm->second.isComplete ) {
    777612                                        Type *concrete = env->lookup( tyParm->first );
    778613                                        if ( concrete ) {
     
    783618                                        } else {
    784619                                                // xxx - should this be an assertion?
    785                                                 throw SemanticError( "unbound type variable: " + tyParm->first + " in application ", appExpr );
     620                                                std::string x = env ? toString( *env ) : "missing env";
     621                                                throw SemanticError( x + "\n" + "unbound type variable: " + tyParm->first + " in application ", appExpr );
    786622                                        } // if
    787623                                } // if
     
    801637                                Type *concRetType = replaceWithConcrete( appExpr, polyRetType );
    802638                                passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
     639                                ++fnArg; // skip the return parameter in the argument list
    803640                        }
    804641
    805642                        // add type information args for presently unseen types in parameter list
    806643                        for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
    807                                 VariableExpr *fnArgBase = getBaseVar( *fnArg );
    808                                 if ( ! fnArgBase ) continue; // xxx - previously had check for non-empty fnArgBase results
    809                                 passArgTypeVars( appExpr, (*fnParm)->get_type(), fnArgBase->get_result(), arg, exprTyVars, seenTypes );
     644                                if ( ! (*fnArg)->get_result() ) continue;
     645                                Type * argType = (*fnArg)->get_result();
     646                                passArgTypeVars( appExpr, (*fnParm)->get_type(), argType, arg, exprTyVars, seenTypes );
    810647                        }
    811648                }
     
    818655
    819656                Expression *Pass1::addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg ) {
    820                         // ***** Code Removal ***** After introducing a temporary variable for all return expressions, the following code appears superfluous.
    821                         // if ( useRetval ) {
    822                         //      assert( retval );
    823                         //      arg = appExpr->get_args().insert( arg, new VariableExpr( retval ) );
    824                         //      arg++;
    825                         // } else {
    826 
    827657                        // Create temporary to hold return value of polymorphic function and produce that temporary as a result
    828                         // using a comma expression.  Possibly change comma expression into statement expression "{}" for multiple
    829                         // return values.
    830                         ObjectDecl *newObj = makeTemporary( retType->clone() );
    831                         Expression *paramExpr = new VariableExpr( newObj );
     658                        // using a comma expression.
     659                        assert( retType );
     660
     661                        Expression * paramExpr = nullptr;
     662                        // try to use existing return value parameter if it exists, otherwise create a new temporary
     663                        if ( retVals.count( appExpr ) ) {
     664                                paramExpr = retVals[appExpr]->clone();
     665                        } else {
     666                                ObjectDecl *newObj = makeTemporary( retType->clone() );
     667                                paramExpr = new VariableExpr( newObj );
     668                        }
     669                        Expression * retExpr = paramExpr->clone();
    832670
    833671                        // If the type of the temporary is not polymorphic, box temporary by taking its address;
    834672                        // otherwise the temporary is already boxed and can be used directly.
    835                         if ( ! isPolyType( newObj->get_type(), scopeTyVars, env ) ) {
     673                        if ( ! isPolyType( paramExpr->get_result(), scopeTyVars, env ) ) {
    836674                                paramExpr = new AddressExpr( paramExpr );
    837675                        } // if
     
    839677                        arg++;
    840678                        // Build a comma expression to call the function and emulate a normal return.
    841                         CommaExpr *commaExpr = new CommaExpr( appExpr, new VariableExpr( newObj ) );
     679                        CommaExpr *commaExpr = new CommaExpr( appExpr, retExpr );
    842680                        commaExpr->set_env( appExpr->get_env() );
    843681                        appExpr->set_env( 0 );
    844682                        return commaExpr;
    845                         // } // if
    846                         // return appExpr;
    847683                }
    848684
     
    859695                                Type *concrete = env->lookup( typeInst->get_name() );
    860696                                if ( concrete == 0 ) {
    861                                         throw SemanticError( "Unbound type variable " + typeInst->get_name() + " in ", appExpr );
     697                                        // xxx - should this be an assertion?
     698                                        std::string x = env ? toString( *env ) : "missing env";
     699                                        throw SemanticError( x + "\n" + "Unbound type variable " + typeInst->get_name() + " in ", appExpr );
    862700                                } // if
    863701                                return concrete;
     
    878716                }
    879717
    880                 Expression *Pass1::addDynRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *dynType, std::list< Expression *>::iterator &arg ) {
     718                Expression *Pass1::addDynRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *dynType, std::list< Expression *>::iterator &arg ) {
    881719                        assert( env );
    882720                        Type *concrete = replaceWithConcrete( appExpr, dynType );
     
    956794                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
    957795                                        InferredParams::const_iterator inferParam = appExpr->get_inferParams().find( (*assert)->get_uniqueId() );
    958                                         assert( inferParam != appExpr->get_inferParams().end() && "NOTE: Explicit casts of polymorphic functions to compatible monomorphic functions are currently unsupported" );
     796                                        if ( inferParam == appExpr->get_inferParams().end() ) {
     797                                                std::cerr << "looking for assertion: " << (*assert) << std::endl << appExpr << std::endl;
     798                                        }
     799                                        assertf( inferParam != appExpr->get_inferParams().end(), "NOTE: Explicit casts of polymorphic functions to compatible monomorphic functions are currently unsupported" );
    959800                                        Expression *newExpr = inferParam->second.expr->clone();
    960801                                        addCast( newExpr, (*assert)->get_type(), tyVars );
     
    12671108                        // }
    12681109                        // std::cerr << "\n";
    1269                         bool oldUseRetval = useRetval;
    1270                         useRetval = false;
    12711110                        appExpr->get_function()->acceptMutator( *this );
    12721111                        mutateAll( appExpr->get_args(), *this );
    1273                         useRetval = oldUseRetval;
    12741112
    12751113                        assert( appExpr->get_function()->has_result() );
     
    12861124                        std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
    12871125
    1288                         TyVarMap exprTyVars( (TypeDecl::Kind)-1 );
    1289                         makeTyVarMap( function, exprTyVars );
     1126                        TyVarMap exprTyVars( TypeDecl::Data{} );
     1127                        makeTyVarMap( function, exprTyVars ); // xxx - should this take into account the variables already bound in scopeTyVars (i.e. remove them from exprTyVars?)
    12901128                        ReferenceToType *dynRetType = isDynRet( function, exprTyVars );
     1129                        Type *concRetType = appExpr->get_result()->isVoid() ? nullptr : appExpr->get_result();// ?: dynRetType; // xxx - is concRetType a good name?
    12911130
    12921131                        if ( dynRetType ) {
    1293                                 ret = addDynRetParam( appExpr, function, dynRetType, arg );
    1294                         } else if ( needsAdapter( function, scopeTyVars ) ) {
     1132                                ret = addDynRetParam( appExpr, function, concRetType, arg ); // xxx - used to use dynRetType instead of concRetType
     1133                        } else if ( needsAdapter( function, scopeTyVars ) && ! needsAdapter( function, exprTyVars) ) { // xxx - exprTyVars is used above...?
     1134                                // xxx - the ! needsAdapter check may be incorrect. It seems there is some situation where an adapter is applied where it shouldn't be, and this fixes it for some cases. More investigation is needed.
     1135
    12951136                                // std::cerr << "needs adapter: ";
    12961137                                // printTyVarMap( std::cerr, scopeTyVars );
     
    13011142                        arg = appExpr->get_args().begin();
    13021143
    1303                         passTypeVars( appExpr, dynRetType, arg, exprTyVars );
     1144                        passTypeVars( appExpr, concRetType, arg, exprTyVars ); // xxx - used to use dynRetType instead of concRetType; this changed so that the correct type paramaters are passed for return types (it should be the concrete type's parameters, not the formal type's)
    13041145                        addInferredParams( appExpr, function, arg, exprTyVars );
    13051146
     
    13601201                }
    13611202
    1362                 /// Wraps a function declaration in a new pointer-to-function variable expression
    1363                 VariableExpr *wrapFunctionDecl( DeclarationWithType *functionDecl ) {
    1364                         // line below cloned from FixFunction.cc
    1365                         // xxx - functionObj is never added to a list of declarations...
    1366                         ObjectDecl *functionObj = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
    1367                                                                   new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
    1368                         functionObj->set_mangleName( functionDecl->get_mangleName() );
    1369                         functionObj->set_scopeLevel( functionDecl->get_scopeLevel() );
    1370                         return new VariableExpr( functionObj );
    1371                 }
    1372 
    1373                 /// Finds the operation declaration for a given type in one of the two maps
    1374                 DeclarationWithType* findOpForType( Type *formalType, const ScopedMap< std::string, DeclarationWithType* >& ops, ResolvExpr::TypeMap< DeclarationWithType >& scopedOps ) {
    1375                         if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {
    1376                                 ScopedMap< std::string, DeclarationWithType *>::const_iterator opIt = ops.find( formalTypeInstType->get_name() );
    1377                                 return opIt == ops.end() ? 0 : opIt->second;
    1378                         } else {
    1379                                 return scopedOps.find( formalType );
    1380                         }
    1381                 }
    1382 
    1383                 /// Adds an assertion parameter to the application expression for the actual assertion declaration valued with the assert op
    1384                 void addAssertionFor( ApplicationExpr *appExpr, DeclarationWithType *actualDecl, DeclarationWithType *assertOp ) {
    1385                         appExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
    1386                                         = ParamEntry( assertOp->get_uniqueId(), assertOp->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertOp ) );
    1387                 }
    1388 
    13891203                Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
     1204                        // maybe need access to the env when mutating the expr
     1205                        if ( Expression * expr = returnStmt->get_expr() ) {
     1206                                if ( expr->get_env() ) {
     1207                                        env = expr->get_env();
     1208                                }
     1209                        }
     1210
    13901211                        if ( retval && returnStmt->get_expr() ) {
    13911212                                assert( returnStmt->get_expr()->has_result() && ! returnStmt->get_expr()->get_result()->isVoid() );
    1392                                 // ***** Code Removal ***** After introducing a temporary variable for all return expressions, the following code appears superfluous.
    1393                                 // if ( returnStmt->get_expr()->get_results().front()->get_isLvalue() ) {
    1394                                 // by this point, a cast expr on a polymorphic return value is redundant
    1395                                 while ( CastExpr *castExpr = dynamic_cast< CastExpr *>( returnStmt->get_expr() ) ) {
    1396                                         returnStmt->set_expr( castExpr->get_arg() );
    1397                                         returnStmt->get_expr()->set_env( castExpr->get_env() );
    1398                                         castExpr->set_env( 0 );
    1399                                         castExpr->set_arg( 0 );
    1400                                         delete castExpr;
    1401                                 } //while
    1402 
    1403                                 // find assignment operator for (polymorphic) return type
    1404                                 ApplicationExpr *assignExpr = 0;
    1405                                 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
    1406                                         // find assignment operator for type variable
    1407                                         ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
    1408                                         if ( assignIter == assignOps.end() ) {
    1409                                                 throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
    1410                                         } // if
    1411                                         assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) );
    1412                                 } else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) {
    1413                                         // find assignment operator for generic type
    1414                                         DeclarationWithType *functionDecl = scopedAssignOps.find( refType );
    1415                                         if ( ! functionDecl ) {
    1416                                                 throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() );
    1417                                         }
    1418 
    1419                                         // wrap it up in an application expression
    1420                                         assignExpr = new ApplicationExpr( wrapFunctionDecl( functionDecl ) );
    1421                                         assignExpr->set_env( env->clone() );
    1422 
    1423                                         // find each of its needed secondary assignment operators
    1424                                         std::list< Expression* > &tyParams = refType->get_parameters();
    1425                                         Type::ForallList &forallParams = functionDecl->get_type()->get_forall();
    1426                                         std::list< Expression* >::const_iterator tyIt = tyParams.begin();
    1427                                         Type::ForallList::const_iterator forallIt = forallParams.begin();
    1428                                         for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) {
    1429                                                 // Add appropriate mapping to assignment expression environment
    1430                                                 TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt );
    1431                                                 assert( formalTypeExpr && "type parameters must be type expressions" );
    1432                                                 Type *formalType = formalTypeExpr->get_type();
    1433                                                 assignExpr->get_env()->add( (*forallIt)->get_name(), formalType );
    1434 
    1435                                                 // skip non-otype parameters (ftype/dtype)
    1436                                                 if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue;
    1437 
    1438                                                 // find otype operators for formal type
    1439                                                 DeclarationWithType *assertAssign = findOpForType( formalType, assignOps, scopedAssignOps );
    1440                                                 if ( ! assertAssign ) throw SemanticError( "No assignment operation found for ", formalType );
    1441 
    1442                                                 DeclarationWithType *assertCtor = findOpForType( formalType, ctorOps, scopedCtorOps );
    1443                                                 if ( ! assertCtor ) throw SemanticError( "No default constructor found for ", formalType );
    1444 
    1445                                                 DeclarationWithType *assertCopy = findOpForType( formalType, copyOps, scopedCopyOps );
    1446                                                 if ( ! assertCopy ) throw SemanticError( "No copy constructor found for ", formalType );
    1447 
    1448                                                 DeclarationWithType *assertDtor = findOpForType( formalType, dtorOps, scopedDtorOps );
    1449                                                 if ( ! assertDtor ) throw SemanticError( "No destructor found for ", formalType );
    1450 
    1451                                                 // add inferred parameters for otype operators to assignment expression
    1452                                                 // NOTE: Code here assumes that first four assertions are assign op, ctor, copy ctor, dtor, in that order
    1453                                                 std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
    1454                                                 assert( asserts.size() >= 4 && "Type param needs otype operator assertions" );
    1455 
    1456                                                 std::list< DeclarationWithType* >::iterator actualIt = asserts.begin();
    1457                                                 addAssertionFor( assignExpr, *actualIt, assertAssign );
    1458                                                 ++actualIt;
    1459                                                 addAssertionFor( assignExpr, *actualIt, assertCtor );
    1460                                                 ++actualIt;
    1461                                                 addAssertionFor( assignExpr, *actualIt, assertCopy );
    1462                                                 ++actualIt;
    1463                                                 addAssertionFor( assignExpr, *actualIt, assertDtor );
    1464 
    1465                                         }
    1466                                 }
    1467                                 assert( assignExpr );
    1468 
    1469                                 // replace return statement with appropriate assignment to out parameter
    1470                                 Expression *retParm = new NameExpr( retval->get_name() );
    1471                                 retParm->set_result( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
    1472                                 assignExpr->get_args().push_back( retParm );
    1473                                 assignExpr->get_args().push_back( returnStmt->get_expr() );
    1474                                 stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( assignExpr ) ) );
    1475                                 // } else {
    1476                                 //      useRetval = true;
    1477                                 //      stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( returnStmt->get_expr() ) ) );
    1478                                 //      useRetval = false;
    1479                                 // } // if
     1213                                delete returnStmt->get_expr();
    14801214                                returnStmt->set_expr( 0 );
    14811215                        } else {
     
    15071241                void Pass1::doBeginScope() {
    15081242                        adapters.beginScope();
    1509                         scopedAssignOps.beginScope();
    1510                         scopedCtorOps.beginScope();
    1511                         scopedCopyOps.beginScope();
    1512                         scopedDtorOps.beginScope();
    15131243                }
    15141244
    15151245                void Pass1::doEndScope() {
    15161246                        adapters.endScope();
    1517                         scopedAssignOps.endScope();
    1518                         scopedCtorOps.endScope();
    1519                         scopedCopyOps.endScope();
    1520                         scopedDtorOps.endScope();
    15211247                }
    15221248
     
    15501276                }
    15511277
     1278                /// determines if `pref` is a prefix of `str`
     1279                bool isPrefix( const std::string & str, const std::string & pref ) {
     1280                        if ( pref.size() > str.size() ) return false;
     1281                        auto its = std::mismatch( pref.begin(), pref.end(), str.begin() );
     1282                        return its.first == pref.end();
     1283                }
     1284
    15521285                DeclarationWithType * Pass2::mutate( FunctionDecl *functionDecl ) {
    1553                         return handleDecl( functionDecl, functionDecl->get_functionType() );
     1286                        functionDecl = safe_dynamic_cast< FunctionDecl * > ( handleDecl( functionDecl, functionDecl->get_functionType() ) );
     1287                        FunctionType * ftype = functionDecl->get_functionType();
     1288                        if ( ! ftype->get_returnVals().empty() && functionDecl->get_statements() ) {
     1289                                if ( functionDecl->get_name() != "?=?" && ! isPrefix( functionDecl->get_name(), "_thunk" ) ) { // xxx - remove check for ?=? once reference types are in; remove check for prefix once thunks properly use ctor/dtors
     1290                                        assert( ftype->get_returnVals().size() == 1 );
     1291                                        DeclarationWithType * retval = ftype->get_returnVals().front();
     1292                                        if ( retval->get_name() == "" ) {
     1293                                                retval->set_name( "_retval" );
     1294                                        }
     1295                                        functionDecl->get_statements()->get_kids().push_front( new DeclStmt( noLabels, retval ) );
     1296                                        DeclarationWithType * newRet = retval->clone(); // for ownership purposes
     1297                                        ftype->get_returnVals().front() = newRet;
     1298                                }
     1299                        }
     1300                        return functionDecl;
    15541301                }
    15551302
     
    15591306
    15601307                TypeDecl * Pass2::mutate( TypeDecl *typeDecl ) {
    1561                         scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
     1308                        addToTyVarMap( typeDecl, scopeTyVars );
    15621309                        if ( typeDecl->get_base() ) {
    15631310                                return handleDecl( typeDecl, typeDecl->get_base() );
     
    15871334                        // move polymorphic return type to parameter list
    15881335                        if ( isDynRet( funcType ) ) {
    1589                                 DeclarationWithType *ret = funcType->get_returnVals().front();
     1336                                ObjectDecl *ret = safe_dynamic_cast< ObjectDecl* >( funcType->get_returnVals().front() );
    15901337                                ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) );
    15911338                                funcType->get_parameters().push_front( ret );
    15921339                                funcType->get_returnVals().pop_front();
     1340                                ret->set_init( nullptr ); // xxx - memory leak?
    15931341                        }
    15941342
     
    16021350                                ObjectDecl *sizeParm, *alignParm;
    16031351                                // add all size and alignment parameters to parameter list
    1604                                 if ( (*tyParm)->get_kind() == TypeDecl::Any ) {
     1352                                if ( (*tyParm)->isComplete() ) {
    16051353                                        TypeInstType parmType( Type::Qualifiers(), (*tyParm)->get_name(), *tyParm );
    16061354                                        std::string parmName = mangleType( &parmType );
     
    17111459
    17121460                TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) {
    1713                         scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
     1461                        addToTyVarMap( typeDecl, scopeTyVars );
    17141462                        return Parent::mutate( typeDecl );
    17151463                }
     
    18251573                                // replace member expression with pointer to base plus offset
    18261574                                UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
    1827                                 fieldLoc->get_args().push_back( makeDerefdVar( varExpr->clone(), varDepth ) );
     1575                                Expression * aggr = memberExpr->get_aggregate()->clone();
     1576                                delete aggr->get_env(); // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
     1577                                aggr->set_env( nullptr );
     1578                                fieldLoc->get_args().push_back( aggr );
    18281579                                fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
    18291580                                newMemberExpr = fieldLoc;
     
    18751626                        for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) {
    18761627                                // skip non-otype parameters
    1877                                 if ( (*baseParam)->get_kind() != TypeDecl::Any ) continue;
     1628                                if ( ! (*baseParam)->isComplete() ) continue;
    18781629                                TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam );
    18791630                                assert( typeExpr && "all otype parameters should be type expressions" );
     
    20871838//   Initializer *init = 0;
    20881839//   std::list< Expression *> designators;
    2089 //   scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
     1840//   addToTyVarMap( typeDecl, scopeTyVars );
    20901841//   if ( typeDecl->get_base() ) {
    20911842//     init = new SimpleInit( new SizeofExpr( handleDecl( typeDecl, typeDecl->get_base() ) ), designators );
     
    20931844//   return new ObjectDecl( typeDecl->get_name(), Declaration::Extern, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ), init );
    20941845
    2095                         scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
     1846                        addToTyVarMap( typeDecl, scopeTyVars );
    20961847                        return Mutator::mutate( typeDecl );
    20971848                }
  • src/GenPoly/CopyParams.cc

    r596f987b r66f8528  
    3838        };
    3939
     40        /// creates local copies of polymorphic function parameters
    4041        void copyParams( std::list< Declaration* > &translationUnit ) {
    4142                CopyParams copier;
     
    5354                        if ( ! modVars.empty() ) {
    5455                                std::map< std::string, DeclarationWithType* > assignOps;
     56                                // xxx - this needs to use constructors, not assignment operators
    5557                                // assume the assignment operator is the first assert param after any "type" parameter
    5658                                for ( Type::ForallList::const_iterator tyVar = funcDecl->get_functionType()->get_forall().begin(); tyVar != funcDecl->get_functionType()->get_forall().end(); ++tyVar ) {
  • src/GenPoly/GenPoly.cc

    r596f987b r66f8528  
    9292        }
    9393
    94         Type *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
     94        ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
    9595                type = replaceTypeInst( type, env );
    9696
    9797                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
    9898                        auto var = tyVars.find( typeInst->get_name() );
    99                         if ( var != tyVars.end() && var->second == TypeDecl::Any ) {
    100                                 return type;
     99                        if ( var != tyVars.end() && var->second.isComplete ) {
     100                                return typeInst;
    101101                        }
    102102                } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
    103                         if ( hasDynParams( structType->get_parameters(), tyVars, env ) ) return type;
     103                        if ( hasDynParams( structType->get_parameters(), tyVars, env ) ) return structType;
    104104                } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
    105                         if ( hasDynParams( unionType->get_parameters(), tyVars, env ) ) return type;
     105                        if ( hasDynParams( unionType->get_parameters(), tyVars, env ) ) return unionType;
    106106                }
    107107                return 0;
     
    117117                if ( function->get_returnVals().empty() ) return 0;
    118118
    119                 TyVarMap forallTypes( (TypeDecl::Kind)-1 );
     119                TyVarMap forallTypes( TypeDecl::Data{} );
    120120                makeTyVarMap( function, forallTypes );
    121121                return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
     
    219219                                expr = commaExpr->get_arg2();
    220220                                continue;
     221                        } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( expr ) ) {
     222                                int lvl1;
     223                                int lvl2;
     224                                VariableExpr * var1 = getBaseVar( condExpr->get_arg2(), &lvl1 );
     225                                VariableExpr * var2 = getBaseVar( condExpr->get_arg3(), &lvl2 );
     226                                if ( lvl1 == lvl2 && var1 && var2 && var1->get_var() == var2->get_var() ) {
     227                                        *levels = lvl1;
     228                                        return var1;
     229                                }
     230                                break;
    221231                        } else break;
    222232
     
    225235
    226236                return 0;
     237        }
     238
     239        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
     240                tyVarMap[ tyVar->get_name() ] = TypeDecl::Data{ tyVar };
    227241        }
    228242
     
    230244                for ( Type::ForallList::const_iterator tyVar = type->get_forall().begin(); tyVar != type->get_forall().end(); ++tyVar ) {
    231245                        assert( *tyVar );
    232                         tyVarMap[ (*tyVar)->get_name() ] = (*tyVar)->get_kind();
     246                        addToTyVarMap( *tyVar, tyVarMap );
    233247                }
    234248                if ( PointerType *pointer = dynamic_cast< PointerType* >( type ) ) {
  • src/GenPoly/GenPoly.h

    r596f987b r66f8528  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // GenPoly.h -- 
     7// GenPoly.h --
    88//
    99// Author           : Richard C. Bilson
     
    3030
    3131namespace GenPoly {
    32         typedef ErasableScopedMap< std::string, TypeDecl::Kind > TyVarMap;
     32        typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;
    3333
    3434        /// Replaces a TypeInstType by its referrent in the environment, if applicable
    3535        Type* replaceTypeInst( Type* type, const TypeSubstitution* env );
    36        
     36
    3737        /// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided
    3838        Type *isPolyType( Type *type, const TypeSubstitution *env = 0 );
    39        
     39
    4040        /// returns polymorphic type if is polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided
    4141        Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
    4242
    4343        /// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided
    44         Type *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
     44        ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
    4545
    4646        /// true iff function has dynamic-layout return type under the given type variable map
     
    5555        /// returns polymorphic type if is pointer to polymorphic type, NULL otherwise; will look up substitution in env if provided
    5656        Type *isPolyPtr( Type *type, const TypeSubstitution *env = 0 );
    57        
     57
    5858        /// returns polymorphic type if is pointer to polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided
    5959        Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
     
    7474        VariableExpr *getBaseVar( Expression *expr, int *levels = 0 );
    7575
     76        /// Adds the type variable `tyVar` to `tyVarMap`
     77        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap );
     78
    7679        /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap`
    7780        void makeTyVarMap( Type *type, TyVarMap &tyVarMap );
    78        
     81
    7982        /// Prints type variable map
    8083        void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap );
     
    8285        /// Gets the mangled name of this type; alias for SymTab::Mangler::mangleType().
    8386        inline std::string mangleType( Type *ty ) { return SymTab::Mangler::mangleType( ty ); }
    84        
     87
    8588        /// Gets the name of the sizeof parameter for the type, given its mangled name
    8689        inline std::string sizeofName( const std::string &name ) { return std::string( "_sizeof_" ) + name; }
     
    9497        /// Gets the name of the layout function for a given aggregate type, given its declaration
    9598        inline std::string layoutofName( AggregateDecl *decl ) { return std::string( "_layoutof_" ) + decl->get_name(); }
    96        
     99
    97100} // namespace GenPoly
    98101
  • src/GenPoly/InstantiateGeneric.cc

    r596f987b r66f8528  
    284284                                // set concDecl to new type, insert type declaration into statements to add
    285285                                concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) );
     286                                concDecl->set_body( inst->get_baseStruct()->has_body() );
    286287                                substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs,        concDecl->get_members() );
    287288                                DeclMutator::addDeclaration( concDecl );
     
    337338                                // set concDecl to new type, insert type declaration into statements to add
    338339                                concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) );
     340                                concDecl->set_body( inst->get_baseUnion()->has_body() );
    339341                                substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
    340342                                DeclMutator::addDeclaration( concDecl );
  • src/GenPoly/PolyMutator.cc

    r596f987b r66f8528  
    2323
    2424namespace GenPoly {
    25         namespace {
    26                 const std::list<Label> noLabels;
    27         }
    28 
    29         PolyMutator::PolyMutator() : scopeTyVars( (TypeDecl::Kind)-1 ), env( 0 ) {}
     25        PolyMutator::PolyMutator() : scopeTyVars( TypeDecl::Data{} ), env( 0 ) {}
    3026
    3127        void PolyMutator::mutateStatementList( std::list< Statement* > &statements ) {
     
    149145        }
    150146
     147        Expression *PolyMutator::mutate( StmtExpr * stmtExpr ) {
     148                // don't want statements from outer CompoundStmts to be added to this StmtExpr
     149                ValueGuard< std::list< Statement* > > oldStmtsToAdd( stmtsToAdd );
     150                ValueGuard< std::list< Statement* > > oldStmtsToAddAfter( stmtsToAddAfter );
     151                ValueGuard< TypeSubstitution * > oldEnv( env );
     152
     153                // xxx - not sure if this is needed, along with appropriate reset, but I don't think so...
     154                // ValueGuard< TyVarMap > oldScopeTyVars( scopeTyVars );
     155
     156                stmtsToAdd.clear();
     157                stmtsToAddAfter.clear();
     158                // scopeTyVars.clear();
     159
     160                return Parent::mutate( stmtExpr );
     161        }
    151162
    152163        Initializer *PolyMutator::mutate( SingleInit *singleInit ) {
     
    154165                return singleInit;
    155166        }
    156 
    157167} // namespace GenPoly
    158168
  • src/GenPoly/PolyMutator.h

    r596f987b r66f8528  
    4747
    4848                virtual Expression* mutate(UntypedExpr *untypedExpr);
     49                virtual Expression* mutate( StmtExpr *stmtExpr );
    4950
    5051                virtual Initializer* mutate(SingleInit *SingleInit);
  • src/GenPoly/ScrubTyVars.cc

    r596f987b r66f8528  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ScrubTyVars.cc -- 
     7// ScrubTyVars.cc --
    88//
    99// Author           : Richard C. Bilson
     
    2828                TyVarMap::const_iterator tyVar = tyVars.find( typeInst->get_name() );
    2929                if ( tyVar != tyVars.end() ) {
    30                         switch ( tyVar->second ) {
     30                        switch ( tyVar->second.kind ) {
    3131                          case TypeDecl::Any:
    3232                          case TypeDecl::Dtype:
     
    5252                return ty;
    5353        }
    54        
     54
    5555        Type * ScrubTyVars::mutate( StructInstType *structInst ) {
    5656                return mutateAggregateType( structInst );
  • src/InitTweak/FixInit.cc

    r596f987b r66f8528  
    4949namespace InitTweak {
    5050        namespace {
     51                typedef std::unordered_map< Expression *, TypeSubstitution * > EnvMap;
     52
    5153                class InsertImplicitCalls final : public GenPoly::PolyMutator {
    5254                public:
    5355                        /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
    5456                        /// function calls need their parameters to be copy constructed
    55                         static void insert( std::list< Declaration * > & translationUnit );
    56 
    57                         using GenPoly::PolyMutator::mutate;
     57                        static void insert( std::list< Declaration * > & translationUnit, EnvMap & envMap );
     58
     59                        InsertImplicitCalls( EnvMap & envMap ) : envMap( envMap ) {}
     60                        typedef GenPoly::PolyMutator Parent;
     61                        using Parent::mutate;
    5862                        virtual Expression * mutate( ApplicationExpr * appExpr ) override;
     63                        virtual Expression * mutate( StmtExpr * stmtExpr ) override;
     64
     65                        // collects environments for relevant nodes
     66                        EnvMap & envMap;
    5967                };
    6068
     
    6472                        /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both
    6573                        /// arguments and return value temporaries
    66                         static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
     74                        static void resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap );
    6775
    6876                        typedef SymTab::Indexer Parent;
    6977                        using Parent::visit;
    7078
     79                        ResolveCopyCtors( const EnvMap & envMap ) : envMap( envMap ) {}
     80
    7181                        virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
    72                         virtual void visit( UniqueExpr * unqExpr );
     82                        virtual void visit( UniqueExpr * unqExpr ) override;
     83                        virtual void visit( StmtExpr * stmtExpr ) override;
    7384
    7485                        /// create and resolve ctor/dtor expression: fname(var, [cpArg])
     
    7990                        void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );
    8091                        void destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
    81                 private:
     92
    8293                        TypeSubstitution * env;
     94                        const EnvMap & envMap;
    8395                };
    8496
     
    174186                        static void fixInitializers( std::list< Declaration * > &translationUnit );
    175187
    176                         using GenPoly::PolyMutator::mutate;
     188                        typedef GenPoly::PolyMutator Parent;
     189                        using Parent::mutate;
    177190                        virtual DeclarationWithType * mutate( ObjectDecl *objDecl ) override;
    178191
     
    186199                        static void fixCopyCtors( std::list< Declaration * > &translationUnit );
    187200
    188                         using GenPoly::PolyMutator::mutate;
     201                        typedef GenPoly::PolyMutator Parent;
     202                        using Parent::mutate;
    189203                        virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
    190204                        virtual Expression * mutate( UniqueExpr * unqExpr ) override;
     205                        virtual Expression * mutate( StmtExpr * stmtExpr ) override;
    191206                };
    192207
     
    248263                InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
    249264
    250 
    251                 InsertImplicitCalls::insert( translationUnit );
    252                 ResolveCopyCtors::resolveImplicitCalls( translationUnit );
     265                EnvMap envMap;
     266
     267                InsertImplicitCalls::insert( translationUnit, envMap );
     268                ResolveCopyCtors::resolveImplicitCalls( translationUnit, envMap );
    253269                InsertDtors::insert( translationUnit );
    254270                FixInit::fixInitializers( translationUnit );
     
    269285
    270286        namespace {
    271                 void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit ) {
    272                         InsertImplicitCalls inserter;
     287                void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit, EnvMap & envMap ) {
     288                        InsertImplicitCalls inserter( envMap );
    273289                        mutateAll( translationUnit, inserter );
    274290                }
    275291
    276                 void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit ) {
    277                         ResolveCopyCtors resolver;
     292                void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap ) {
     293                        ResolveCopyCtors resolver( envMap );
    278294                        acceptAll( translationUnit, resolver );
    279295                }
     
    326342
    327343                Expression * InsertImplicitCalls::mutate( ApplicationExpr * appExpr ) {
    328                         appExpr = dynamic_cast< ApplicationExpr * >( Mutator::mutate( appExpr ) );
     344                        appExpr = dynamic_cast< ApplicationExpr * >( Parent::mutate( appExpr ) );
    329345                        assert( appExpr );
    330346
     
    339355                                                Type * t1 = ftype->get_parameters().front()->get_type();
    340356                                                Type * t2 = ftype->get_parameters().back()->get_type();
    341                                                 PointerType * ptrType = dynamic_cast< PointerType * > ( t1 );
    342                                                 assert( ptrType );
     357                                                PointerType * ptrType = safe_dynamic_cast< PointerType * > ( t1 );
    343358
    344359                                                if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) {
     
    357372                        // wrap each function call so that it is easy to identify nodes that have to be copy constructed
    358373                        ImplicitCopyCtorExpr * expr = new ImplicitCopyCtorExpr( appExpr );
    359                         // save the type substitution onto the new node so that it is easy to find.
     374                        // save the type substitution into the envMap so that it is easy to find.
    360375                        // Ensure it is not deleted with the ImplicitCopyCtorExpr by removing it before deletion.
    361376                        // The substitution is needed to obtain the type of temporary variables so that copy constructor
     
    366381                        // constructor calls together.
    367382                        assert( env );
    368                         expr->set_env( env );
     383                        envMap[expr] = env;
    369384                        return expr;
     385                }
     386
     387                Expression * InsertImplicitCalls::mutate( StmtExpr * stmtExpr ) {
     388                        assert( env );
     389                        envMap[stmtExpr] = env;
     390                        return Parent::mutate( stmtExpr );
    370391                }
    371392
     
    392413                        assert( resolved );
    393414                        if ( resolved->get_env() ) {
     415                                // Extract useful information and discard new environments. Keeping them causes problems in PolyMutator passes.
    394416                                env->add( *resolved->get_env() );
     417                                delete resolved->get_env();
     418                                resolved->set_env( nullptr );
    395419                        } // if
    396420
     
    401425                void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {
    402426                        static UniqueName tempNamer("_tmp_cp");
    403                         CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; )
     427                        assert( env );
     428                        CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; )
    404429                        assert( arg->has_result() );
    405430                        Type * result = arg->get_result();
     
    408433                        // type may involve type variables, so apply type substitution to get temporary variable's actual type
    409434                        result = result->clone();
    410                         impCpCtorExpr->get_env()->apply( result );
     435                        env->apply( result );
    411436                        ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
    412437                        tmp->get_type()->set_isConst( false );
     
    437462                        CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
    438463                        Parent::visit( impCpCtorExpr );
    439                         env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer...
     464                        env = envMap.at(impCpCtorExpr);
     465                        assert( env );
    440466
    441467                        ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr();
     
    448474                        // each return value from the call needs to be connected with an ObjectDecl at the call site, which is
    449475                        // initialized with the return value and is destructed later
    450                         // xxx - handle multiple return values
    451                         ApplicationExpr * callExpr = impCpCtorExpr->get_callExpr();
    452                         // xxx - is this right? callExpr may not have the right environment, because it was attached at a higher
    453                         // level. Trying to pass that environment along.
    454                         callExpr->set_env( impCpCtorExpr->get_env()->clone() );
     476                        // xxx - handle named return values?
    455477                        Type * result = appExpr->get_result();
    456478                        if ( ! result->isVoid() ) {
    457479                                static UniqueName retNamer("_tmp_cp_ret");
    458480                                result = result->clone();
    459                                 impCpCtorExpr->get_env()->apply( result );
     481                                env->apply( result );
    460482                                ObjectDecl * ret = new ObjectDecl( retNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
    461483                                ret->get_type()->set_isConst( false );
     
    468490                        } // for
    469491                        CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; )
     492                }
     493
     494                void ResolveCopyCtors::visit( StmtExpr * stmtExpr ) {
     495                        Parent::visit( stmtExpr );
     496                        env = envMap.at(stmtExpr);
     497                        assert( stmtExpr->get_result() );
     498                        Type * result = stmtExpr->get_result();
     499                        if ( ! result->isVoid() ) {
     500                                static UniqueName retNamer("_tmp_stmtexpr_ret");
     501
     502                                // create variable that will hold the result of the stmt expr
     503                                result = result->clone();
     504                                env->apply( result );
     505                                ObjectDecl * ret = new ObjectDecl( retNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
     506                                ret->get_type()->set_isConst( false );
     507                                stmtExpr->get_returnDecls().push_front( ret );
     508
     509                                // must have a non-empty body, otherwise it wouldn't have a result
     510                                CompoundStmt * body = stmtExpr->get_statements();
     511                                assert( ! body->get_kids().empty() );
     512                                // must be an ExprStmt, otherwise it wouldn't have a result
     513                                ExprStmt * last = safe_dynamic_cast< ExprStmt * >( body->get_kids().back() );
     514                                last->set_expr( makeCtorDtor( "?{}", ret, last->get_expr() ) );
     515
     516                                stmtExpr->get_dtors().push_front( makeCtorDtor( "^?{}", new AddressExpr( new VariableExpr( ret ) ) ) );
     517                        } // if
     518
    470519                }
    471520
     
    492541                }
    493542
    494 
    495543                Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    496544                        CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; )
    497545
    498                         impCpCtorExpr = dynamic_cast< ImplicitCopyCtorExpr * >( Mutator::mutate( impCpCtorExpr ) );
    499                         assert( impCpCtorExpr );
    500 
     546                        impCpCtorExpr = safe_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) );
    501547                        std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls();
    502548                        std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls();
     
    558604                                        retExpr = UntypedExpr::createDeref( retExpr );
    559605                                } // if
    560                                 retExpr->set_env( env->clone() );
     606                                // move env from callExpr to retExpr
     607                                retExpr->set_env( callExpr->get_env() );
     608                                callExpr->set_env( nullptr );
    561609                                return retExpr;
    562610                        } else {
     
    565613                }
    566614
     615                Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) {
     616                        stmtExpr = safe_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) );
     617                        assert( stmtExpr->get_result() );
     618                        Type * result = stmtExpr->get_result();
     619                        if ( ! result->isVoid() ) {
     620                                for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) {
     621                                        stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     622                                } // for
     623                                // add destructors after current statement
     624                                for ( Expression * dtor : stmtExpr->get_dtors() ) {
     625                                        stmtsToAddAfter.push_back( new ExprStmt( noLabels, dtor ) );
     626                                } // for
     627                                // must have a non-empty body, otherwise it wouldn't have a result
     628                                CompoundStmt * body = stmtExpr->get_statements();
     629                                assert( ! body->get_kids().empty() );
     630                                assert( ! stmtExpr->get_returnDecls().empty() );
     631                                body->get_kids().push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
     632                        }
     633                        stmtExpr->get_returnDecls().clear();
     634                        stmtExpr->get_dtors().clear();
     635                        return stmtExpr;
     636                }
     637
    567638                Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
    568639                        static std::unordered_map< int, UniqueExpr * > unqMap;
    569640                        static std::unordered_set< int > addDeref;
    570641                        // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes
    571                         unqExpr = safe_dynamic_cast< UniqueExpr * >( Parent::mutate( unqExpr ) );
    572642                        if ( unqMap.count( unqExpr->get_id() ) ) {
    573643                                // take data from other UniqueExpr to ensure consistency
     
    582652                                return unqExpr;
    583653                        }
     654                        unqExpr = safe_dynamic_cast< UniqueExpr * >( Parent::mutate( unqExpr ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup
    584655                        unqMap[unqExpr->get_id()] = unqExpr;
    585656                        if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) {
     
    599670                        // first recursively handle pieces of ObjectDecl so that they aren't missed by other visitors when the init
    600671                        // is removed from the ObjectDecl
    601                         objDecl = dynamic_cast< ObjectDecl * >( Mutator::mutate( objDecl ) );
    602 
     672                        objDecl = dynamic_cast< ObjectDecl * >( Parent::mutate( objDecl ) );
    603673                        if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
    604674                                // a decision should have been made by the resolver, so ctor and init are not both non-NULL
     
    904974                                        // insert and resolve default/copy constructor call for each field that's unhandled
    905975                                        std::list< Statement * > stmt;
    906                                         UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
    907                                         deref->get_args().push_back( new VariableExpr( thisParam ) );
     976                                        UntypedExpr * deref = UntypedExpr::createDeref( new VariableExpr( thisParam ) );
    908977
    909978                                        Expression * arg2 = 0;
  • src/InitTweak/GenInit.cc

    r596f987b r66f8528  
    4646                ReturnFixer();
    4747
    48                 using GenPoly::PolyMutator::mutate;
     48                typedef GenPoly::PolyMutator Parent;
     49                using Parent::mutate;
    4950                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
    5051                virtual Statement * mutate( ReturnStmt * returnStmt ) override;
     
    5253          protected:
    5354                FunctionType * ftype;
    54                 UniqueName tempNamer;
    5555                std::string funcName;
    5656        };
     
    135135        }
    136136
    137         ReturnFixer::ReturnFixer() : tempNamer( "_retVal" ) {}
     137        ReturnFixer::ReturnFixer() {}
    138138
    139139        Statement *ReturnFixer::mutate( ReturnStmt *returnStmt ) {
     
    142142                // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
    143143                // is being returned
     144                // Note: under the assumption that assignments return *this, checking for ?=? here is an optimization, since it shouldn't be necessary to copy construct `this`. This is a temporary optimization until reference types are added, at which point this should be removed, along with the analogous optimization in copy constructor generation.
    144145                if ( returnStmt->get_expr() && returnVals.size() == 1 && funcName != "?=?" && ! returnVals.front()->get_type()->get_isLvalue() ) {
    145                         // ensure return value is not destructed by explicitly creating
    146                         // an empty SingleInit node wherein maybeConstruct is false
    147                         ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, returnVals.front()->get_type()->clone(), new ListInit( std::list<Initializer*>(), noDesignators, false ) );
    148                         stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
    149 
    150                         // and explicitly create the constructor expression separately
     146                        // explicitly construct the return value using the return expression and the retVal object
     147                        assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
    151148                        UntypedExpr *construct = new UntypedExpr( new NameExpr( "?{}" ) );
    152                         construct->get_args().push_back( new AddressExpr( new VariableExpr( newObj ) ) );
     149                        construct->get_args().push_back( new AddressExpr( new VariableExpr( returnVals.front() ) ) );
    153150                        construct->get_args().push_back( returnStmt->get_expr() );
    154151                        stmtsToAdd.push_back(new ExprStmt(noLabels, construct));
    155152
    156                         returnStmt->set_expr( new VariableExpr( newObj ) );
     153                        // return the retVal object
     154                        returnStmt->set_expr( new VariableExpr( returnVals.front() ) );
    157155                } // if
    158156                return returnStmt;
     
    160158
    161159        DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) {
    162                 // xxx - need to handle named return values - this pass may need to happen
    163                 // after resolution? the ordering is tricky because return statements must be
    164                 // constructed - the simplest way to do that (while also handling multiple
    165                 // returns) is to structure the returnVals into a tuple, as done here.
    166                 // however, if the tuple return value is structured before resolution,
    167                 // it's difficult to resolve named return values, since the name is lost
    168                 // in conversion to a tuple. this might be easiest to deal with
    169                 // after reference types are added, as it may then be possible to
    170                 // uniformly move named return values to the parameter list directly
    171160                ValueGuard< FunctionType * > oldFtype( ftype );
    172161                ValueGuard< std::string > oldFuncName( funcName );
    173162
    174163                ftype = functionDecl->get_functionType();
    175                 std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
    176                 if ( retVals.size() > 1 ) {
    177                         TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
    178                         ObjectDecl * newRet = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) );
    179                         retVals.clear();
    180                         retVals.push_back( newRet );
    181                 }
    182164                funcName = functionDecl->get_name();
    183                 DeclarationWithType * decl = Mutator::mutate( functionDecl );
    184                 return decl;
     165                return Parent::mutate( functionDecl );
    185166        }
    186167
     
    246227                        }
    247228                }
    248                 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
     229                // a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable)
     230                return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end() || GenPoly::isPolyType( type );
    249231        }
    250232
  • src/ResolvExpr/AdjustExprType.cc

    r596f987b r66f8528  
    9797                EqvClass eqvClass;
    9898                if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
    99                         if ( eqvClass.kind == TypeDecl::Ftype ) {
     99                        if ( eqvClass.data.kind == TypeDecl::Ftype ) {
    100100                                PointerType *pointerType = new PointerType( Type::Qualifiers(), typeInst );
    101101                                return pointerType;
  • src/ResolvExpr/AlternativeFinder.cc

    r596f987b r66f8528  
    4444#include "InitTweak/GenInit.h"
    4545#include "ResolveTypeof.h"
     46#include "Resolver.h"
    4647
    4748extern bool resolvep;
     
    185186                        if ( alternatives.begin() == oldBegin ) {
    186187                                std::ostringstream stream;
    187                                 stream << "Can't choose between alternatives for expression ";
     188                                stream << "Can't choose between " << alternatives.size() << " alternatives for expression ";
    188189                                expr->print( stream );
    189190                                stream << "Alternatives are:";
     
    308309                                        (*actualType)->print( std::cerr, 8 );
    309310                                        std::cerr << std::endl << " to ";
    310                                         (*formal)->get_type()->print( std::cerr, 8 );
     311                                        (*formalType)->print( std::cerr, 8 );
    311312                                )
    312313                                Cost newCost = conversionCost( *actualType, *formalType, indexer, alt.env );
     
    373374        void makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions ) {
    374375                for ( Type::ForallList::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
    375                         unifiableVars[ (*tyvar)->get_name() ] = (*tyvar)->get_kind();
     376                        unifiableVars[ (*tyvar)->get_name() ] = TypeDecl::Data{ *tyvar };
    376377                        for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
    377378                                needAssertions[ *assert ] = true;
     
    511512                if ( ! cur->second ) {
    512513                        inferRecursive( begin, end, newAlt, openVars, decls, newNeed, /*needParents,*/ level, indexer, out );
     514                        return; // xxx - should this continue? previously this wasn't here, and it looks like it should be
    513515                }
    514516                DeclarationWithType *curDecl = cur->first;
     517
    515518                PRINT(
    516519                        std::cerr << "inferRecursive: assertion is ";
     
    606609                makeUnifiableVars( funcType, openVars, resultNeed );
    607610                AltList instantiatedActuals; // filled by instantiate function
     611                if ( targetType && ! targetType->isVoid() ) {
     612                        // attempt to narrow based on expected target type
     613                        Type * returnType = funcType->get_returnVals().front()->get_type();
     614                        if ( ! unify( returnType, targetType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     615                                // unification failed, don't pursue this alternative
     616                                return;
     617                        }
     618                }
     619
    608620                if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave, instantiatedActuals ) ) {
    609621                        ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
     
    649661                AltList candidates;
    650662                SemanticError errors;
    651 
    652663                for ( AltList::const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
    653664                        try {
     
    739750
    740751                findMinCost( candidates.begin(), candidates.end(), std::back_inserter( alternatives ) );
     752
     753                if ( alternatives.empty() && targetType && ! targetType->isVoid() ) {
     754                        // xxx - this is a temporary hack. If resolution is unsuccessful with a target type, try again without a
     755                        // target type, since it will sometimes succeed when it wouldn't easily with target type binding. For example,
     756                        //   forall( otype T ) lvalue T ?[?]( T *, ptrdiff_t );
     757                        //   const char * x = "hello world";
     758                        //   unsigned char ch = x[0];
     759                        // Fails with simple return type binding. First, T is bound to unsigned char, then (x: const char *) is unified
     760                        // with unsigned char *, which fails because pointer base types must be unified exactly. The new resolver should
     761                        // fix this issue in a more robust way.
     762                        targetType = nullptr;
     763                        visit( untypedExpr );
     764                }
    741765        }
    742766
     
    758782        void AlternativeFinder::visit( CastExpr *castExpr ) {
    759783                Type *& toType = castExpr->get_result();
     784                assert( toType );
    760785                toType = resolveTypeof( toType, indexer );
    761786                SymTab::validateType( toType, &indexer );
     
    763788
    764789                AlternativeFinder finder( indexer, env );
     790                finder.targetType = toType;
    765791                finder.findWithAdjustment( castExpr->get_arg() );
    766792
     
    776802                        int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();
    777803                        if ( discardedValues < 0 ) continue;
    778                         // xxx - may need to go into tuple types and extract relavent types and use unifyList
     804                        // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
     805                        // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    779806                        // unification run for side-effects
    780807                        unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
     
    783810                                // count one safe conversion for each value that is thrown away
    784811                                thisCost += Cost( 0, 0, discardedValues );
    785                                 CastExpr *newExpr = castExpr->clone();
    786                                 newExpr->set_arg( i->expr->clone() );
    787                                 candidates.push_back( Alternative( newExpr, i->env, i->cost, thisCost ) );
     812
     813                                Expression * argExpr = i->expr->clone();
     814                                if ( argExpr->get_result()->size() > 1 && ! castExpr->get_result()->isVoid() ) {
     815                                        // Argument expression is a tuple and the target type is not void. Cast each member of the tuple
     816                                        // to its corresponding target type, producing the tuple of those cast expressions. If there are
     817                                        // more components of the tuple than components in the target type, then excess components do not
     818                                        // come out in the result expression (but UniqueExprs ensure that side effects will still be done).
     819                                        if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) {
     820                                                // expressions which may contain side effects require a single unique instance of the expression.
     821                                                argExpr = new UniqueExpr( argExpr );
     822                                        }
     823                                        std::list< Expression * > componentExprs;
     824                                        for ( unsigned int i = 0; i < castExpr->get_result()->size(); i++ ) {
     825                                                // cast each component
     826                                                TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i );
     827                                                componentExprs.push_back( new CastExpr( idx, castExpr->get_result()->getComponent( i )->clone() ) );
     828                                        }
     829                                        delete argExpr;
     830                                        assert( componentExprs.size() > 0 );
     831                                        // produce the tuple of casts
     832                                        candidates.push_back( Alternative( new TupleExpr( componentExprs ), i->env, i->cost, thisCost ) );
     833                                } else {
     834                                        // handle normally
     835                                        candidates.push_back( Alternative( new CastExpr( argExpr->clone(), toType->clone() ), i->env, i->cost, thisCost ) );
     836                                }
    788837                        } // if
    789838                } // for
     
    800849                AlternativeFinder funcFinder( indexer, env );
    801850                funcFinder.findWithAdjustment( memberExpr->get_aggregate() );
    802 
    803851                for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
    804852                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_result() ) ) {
     
    10751123        }
    10761124
     1125        void AlternativeFinder::visit( StmtExpr *stmtExpr ) {
     1126                StmtExpr * newStmtExpr = stmtExpr->clone();
     1127                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
     1128                // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr...
     1129                alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) );
     1130        }
     1131
    10771132} // namespace ResolvExpr
    10781133
  • src/ResolvExpr/AlternativeFinder.h

    r596f987b r66f8528  
    7070                virtual void visit( TupleAssignExpr *tupleExpr );
    7171                virtual void visit( UniqueExpr *unqExpr );
     72                virtual void visit( StmtExpr *stmtExpr );
    7273                /// Runs a new alternative finder on each element in [begin, end)
    7374                /// and writes each alternative finder to out.
     
    9192                AltList alternatives;
    9293                const TypeEnvironment &env;
     94                Type * targetType = nullptr;
    9395        }; // AlternativeFinder
    9496
  • src/ResolvExpr/CommonType.cc

    r596f987b r66f8528  
    5858                Type *result = visitor.get_result();
    5959                if ( ! result ) {
     60                        // this appears to be handling for opaque type declarations
    6061                        if ( widenSecond ) {
    61                                 TypeInstType *inst = dynamic_cast< TypeInstType* >( type2 );
    62                                 if ( inst ) {
    63                                         NamedTypeDecl *nt = indexer.lookupType( inst->get_name() );
    64                                         if ( nt ) {
    65                                                 TypeDecl *type = dynamic_cast< TypeDecl* >( nt );
    66                                                 assert( type );
     62                                if ( TypeInstType *inst = dynamic_cast< TypeInstType* >( type2 ) ) {
     63                                        if ( NamedTypeDecl *nt = indexer.lookupType( inst->get_name() ) ) {
     64                                                TypeDecl *type = safe_dynamic_cast< TypeDecl* >( nt );
    6765                                                if ( type->get_base() ) {
    6866                                                        Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers();
     
    158156                result->get_qualifiers() += otherPointer->get_qualifiers();
    159157        }
    160        
     158
    161159        void CommonType::visit( PointerType *pointerType ) {
    162160                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
     
    223221                        NamedTypeDecl *nt = indexer.lookupType( inst->get_name() );
    224222                        if ( nt ) {
    225                                 TypeDecl *type = dynamic_cast< TypeDecl* >( nt );
    226                                 assert( type );
     223                                TypeDecl *type = safe_dynamic_cast< TypeDecl* >( nt );
    227224                                if ( type->get_base() ) {
    228225                                        Type::Qualifiers tq1 = inst->get_qualifiers(), tq2 = type2->get_qualifiers();
  • src/ResolvExpr/FindOpenVars.cc

    r596f987b r66f8528  
    4848                if ( nextIsOpen ) {
    4949                        for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
    50                                 openVars[ (*i)->get_name() ] = (*i)->get_kind();
     50                                openVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
    5151                                for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
    5252                                        needAssertions[ *assert ] = false;
     
    5757                } else {
    5858                        for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
    59                                 closedVars[ (*i)->get_name() ] = (*i)->get_kind();
     59                                closedVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
    6060                                for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
    6161                                        haveAssertions[ *assert ] = false;
  • src/ResolvExpr/PtrsCastable.cc

    r596f987b r66f8528  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // PtrsCastable.cc -- 
     7// PtrsCastable.cc --
    88//
    99// Author           : Richard C. Bilson
     
    2525          public:
    2626                PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    27  
     27
    2828                int get_result() const { return result; }
    2929
     
    6161                                } //if
    6262                        } else if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
    63                                 if ( eqvClass.kind == TypeDecl::Ftype ) {
     63                                if ( eqvClass.data.kind == TypeDecl::Ftype ) {
    6464                                        return -1;
    6565                                } // if
  • src/ResolvExpr/Resolver.cc

    r596f987b r66f8528  
    3636          public:
    3737                Resolver() : SymTab::Indexer( false ) {}
    38 
    39                 using SymTab::Indexer::visit;
     38                Resolver( const SymTab:: Indexer & other ) : SymTab::Indexer( other ) {
     39                        if ( const Resolver * res = dynamic_cast< const Resolver * >( &other ) ) {
     40                                functionReturn = res->functionReturn;
     41                                initContext = res->initContext;
     42                                inEnumDecl = res->inEnumDecl;
     43                        }
     44                }
     45
     46                typedef SymTab::Indexer Parent;
     47                using Parent::visit;
    4048                virtual void visit( FunctionDecl *functionDecl ) override;
    4149                virtual void visit( ObjectDecl *functionDecl ) override;
     
    6674                void handlePtrType( PtrType * type );
    6775
    68           void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & );
    69           void resolveSingleAggrInit( Declaration *, InitIterator &, InitIterator & );
     76          void resolveAggrInit( ReferenceToType *, InitIterator &, InitIterator & );
     77          void resolveSingleAggrInit( Declaration *, InitIterator &, InitIterator &, TypeSubstitution sub );
    7078          void fallbackInit( ConstructorInit * ctorInit );
    7179
     
    192200                        initContext = new BasicType( Type::Qualifiers(), BasicType::SignedInt );
    193201                }
    194                 SymTab::Indexer::visit( objectDecl );
     202                Parent::visit( objectDecl );
    195203                if ( inEnumDecl && dynamic_cast< EnumInstType * >( initContext ) ) {
    196204                        // delete newly created signed int type
     
    212220        void Resolver::visit( ArrayType * at ) {
    213221                handlePtrType( at );
    214                 Visitor::visit( at );
     222                Parent::visit( at );
    215223        }
    216224
    217225        void Resolver::visit( PointerType * pt ) {
    218226                handlePtrType( pt );
    219                 Visitor::visit( pt );
     227                Parent::visit( pt );
    220228        }
    221229
     
    225233                        typeDecl->set_base( new_type );
    226234                } // if
    227                 SymTab::Indexer::visit( typeDecl );
     235                Parent::visit( typeDecl );
    228236        }
    229237
     
    238246                ValueGuard< Type * > oldFunctionReturn( functionReturn );
    239247                functionReturn = ResolvExpr::extractResultType( functionDecl->get_functionType() );
    240                 SymTab::Indexer::visit( functionDecl );
     248                Parent::visit( functionDecl );
    241249        }
    242250
    243251        void Resolver::visit( EnumDecl * enumDecl ) {
    244252                // in case we decide to allow nested enums
    245                 bool oldInEnumDecl = inEnumDecl;
     253                ValueGuard< bool > oldInEnumDecl( inEnumDecl );
    246254                inEnumDecl = true;
    247                 SymTab::Indexer::visit( enumDecl );
    248                 inEnumDecl = oldInEnumDecl;
     255                Parent::visit( enumDecl );
    249256        }
    250257
    251258        void Resolver::visit( ExprStmt *exprStmt ) {
    252                 if ( exprStmt->get_expr() ) {
    253                         Expression *newExpr = findVoidExpression( exprStmt->get_expr(), *this );
    254                         delete exprStmt->get_expr();
    255                         exprStmt->set_expr( newExpr );
    256                 } // if
     259                assertf( exprStmt->get_expr(), "ExprStmt has null Expression in resolver" );
     260                Expression *newExpr = findVoidExpression( exprStmt->get_expr(), *this );
     261                delete exprStmt->get_expr();
     262                exprStmt->set_expr( newExpr );
    257263        }
    258264
     
    277283                delete ifStmt->get_condition();
    278284                ifStmt->set_condition( newExpr );
    279                 Visitor::visit( ifStmt );
     285                Parent::visit( ifStmt );
    280286        }
    281287
     
    284290                delete whileStmt->get_condition();
    285291                whileStmt->set_condition( newExpr );
    286                 Visitor::visit( whileStmt );
     292                Parent::visit( whileStmt );
    287293        }
    288294
    289295        void Resolver::visit( ForStmt *forStmt ) {
    290                 SymTab::Indexer::visit( forStmt );
     296                Parent::visit( forStmt );
    291297
    292298                if ( forStmt->get_condition() ) {
     
    318324
    319325        void Resolver::visit( CaseStmt *caseStmt ) {
    320                 Visitor::visit( caseStmt );
     326                Parent::visit( caseStmt );
    321327        }
    322328
     
    396402        }
    397403
    398         void Resolver::resolveSingleAggrInit( Declaration * dcl, InitIterator & init, InitIterator & initEnd ) {
     404        template< typename AggrInst >
     405        TypeSubstitution makeGenericSubstitutuion( AggrInst * inst ) {
     406                assert( inst );
     407                assert( inst->get_baseParameters() );
     408                std::list< TypeDecl * > baseParams = *inst->get_baseParameters();
     409                std::list< Expression * > typeSubs = inst->get_parameters();
     410                TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
     411                return subs;
     412        }
     413
     414        ReferenceToType * isStructOrUnion( Type * type ) {
     415                if ( StructInstType * sit = dynamic_cast< StructInstType * >( type ) ) {
     416                        return sit;
     417                } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( type ) ) {
     418                        return uit;
     419                }
     420                return nullptr;
     421        }
     422
     423        void Resolver::resolveSingleAggrInit( Declaration * dcl, InitIterator & init, InitIterator & initEnd, TypeSubstitution sub ) {
    399424                DeclarationWithType * dt = dynamic_cast< DeclarationWithType * >( dcl );
    400425                assert( dt );
    401                 initContext = dt->get_type();
     426                // need to substitute for generic types, so that casts are to concrete types
     427                initContext = dt->get_type()->clone();
     428                sub.apply( initContext );
     429
    402430                try {
    403431                        if ( init == initEnd ) return; // stop when there are no more initializers
     
    406434                } catch( SemanticError & ) {
    407435                        // need to delve deeper, if you can
    408                         if ( StructInstType * sit = dynamic_cast< StructInstType * >( dt->get_type() ) ) {
    409                                 resolveAggrInit( sit->get_baseStruct(), init, initEnd );
    410                         } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( dt->get_type() ) ) {
    411                                 resolveAggrInit( uit->get_baseUnion(), init, initEnd );
     436                        if ( ReferenceToType * type = isStructOrUnion( initContext ) ) {
     437                                resolveAggrInit( type, init, initEnd );
    412438                        } else {
    413439                                // member is not an aggregate type, so can't go any deeper
     
    419445        }
    420446
    421         void Resolver::resolveAggrInit( AggregateDecl * aggr, InitIterator & init, InitIterator & initEnd ) {
    422                 if ( StructDecl * st = dynamic_cast< StructDecl * >( aggr ) ) {
     447        void Resolver::resolveAggrInit( ReferenceToType * inst, InitIterator & init, InitIterator & initEnd ) {
     448                if ( StructInstType * sit = dynamic_cast< StructInstType * >( inst ) ) {
     449                        TypeSubstitution sub = makeGenericSubstitutuion( sit );
     450                        StructDecl * st = sit->get_baseStruct();
    423451                        // want to resolve each initializer to the members of the struct,
    424452                        // but if there are more initializers than members we should stop
    425453                        list< Declaration * >::iterator it = st->get_members().begin();
    426454                        for ( ; it != st->get_members().end(); ++it) {
    427                                 resolveSingleAggrInit( *it, init, initEnd );
     455                                resolveSingleAggrInit( *it, init, initEnd, sub );
    428456                        }
    429                 } else if ( UnionDecl * un = dynamic_cast< UnionDecl * >( aggr ) ) {
     457                } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( inst ) ) {
     458                        TypeSubstitution sub = makeGenericSubstitutuion( uit );
     459                        UnionDecl * un = uit->get_baseUnion();
    430460                        // only resolve to the first member of a union
    431                         resolveSingleAggrInit( *un->get_members().begin(), init, initEnd );
     461                        resolveSingleAggrInit( *un->get_members().begin(), init, initEnd, sub );
    432462                } // if
    433463        }
     
    449479                                (*iter++)->accept( *this );
    450480                        }
    451                 } else if ( StructInstType * st = dynamic_cast< StructInstType * >( initContext ) ) {
    452                         resolveAggrInit( st->get_baseStruct(), iter, end );
    453                 } else if ( UnionInstType * st = dynamic_cast< UnionInstType * >( initContext ) ) {
    454                         resolveAggrInit( st->get_baseUnion(), iter, end );
     481                } else if ( ReferenceToType * type = isStructOrUnion( initContext ) ) {
     482                        resolveAggrInit( type, iter, end );
    455483                } else if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( initContext ) ) {
    456484                        Type * base = tt->get_baseType()->get_base();
     
    461489                        } else {
    462490                                // missing implementation type -- might be an unknown type variable, so try proceeding with the current init context
    463                                 Visitor::visit( listInit );
     491                                Parent::visit( listInit );
    464492                        }
    465493                } else {
    466494                        assert( dynamic_cast< BasicType * >( initContext ) || dynamic_cast< PointerType * >( initContext )
    467                                 || dynamic_cast< ZeroType * >( initContext ) || dynamic_cast< OneType * >( initContext ) );
     495                                || dynamic_cast< ZeroType * >( initContext ) || dynamic_cast< OneType * >( initContext ) || dynamic_cast < EnumInstType * > ( initContext ) );
    468496                        // basic types are handled here
    469                         Visitor::visit( listInit );
     497                        Parent::visit( listInit );
    470498                }
    471499
     
    533561        }
    534562
     563        // needs to be callable from outside the resolver, so this is a standalone function
     564        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) {
     565                assert( ctorInit );
     566                Resolver resolver( indexer );
     567                ctorInit->accept( resolver );
     568        }
     569
     570        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) {
     571                assert( stmtExpr );
     572                Resolver resolver( indexer );
     573                stmtExpr->accept( resolver );
     574        }
     575
    535576        void Resolver::visit( ConstructorInit *ctorInit ) {
    536577                // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
  • src/ResolvExpr/Resolver.h

    r596f987b r66f8528  
    2525        Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer );
    2626        Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer );
     27        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
     28        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
    2729} // namespace ResolvExpr
    2830
  • src/ResolvExpr/TypeEnvironment.cc

    r596f987b r66f8528  
    3232        //
    3333        // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
    34         bool AssertCompare::operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) {
     34        bool AssertCompare::operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
    3535                        // Objects are always less than functions
    3636                        if ( ObjectDecl * objectDecl1 = dynamic_cast< ObjectDecl * >( d1 ) ) {
     
    9494                dest.type = maybeClone( src.type );
    9595                dest.allowWidening = src.allowWidening;
    96                 dest.kind = src.kind;
     96                dest.data = src.data;
    9797        }
    9898
     
    162162                        EqvClass newClass;
    163163                        newClass.vars.insert( (*i)->get_name() );
    164                         newClass.kind = (*i)->get_kind();
     164                        newClass.data = TypeDecl::Data{ (*i) };
    165165                        env.push_back( newClass );
    166166                } // for
     
    177177                                        sub.add( *theVar, theClass->type );
    178178                                } else if ( theVar != theClass->vars.begin() ) {
    179                                         TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->kind == TypeDecl::Ftype );
     179                                        TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype );
    180180///         std::cout << " bound to variable " << *theClass->vars.begin() << std::endl;
    181181                                        sub.add( *theVar, newTypeInst );
     
    243243                for ( std::list< EqvClass >::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {
    244244                        for ( std::set< std::string >::const_iterator var = eqvClass->vars.begin(); var != eqvClass->vars.end(); ++var ) {
    245                                 openVars[ *var ] = eqvClass->kind;
     245                                openVars[ *var ] = eqvClass->data;
    246246                        } // for
    247247                } // for
  • src/ResolvExpr/TypeEnvironment.h

    r596f987b r66f8528  
    2929namespace ResolvExpr {
    3030        struct AssertCompare {
    31                 bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 );
     31                bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const;
    3232        };
    3333        typedef std::map< DeclarationWithType*, bool, AssertCompare > AssertionSet;
    34         typedef std::map< std::string, TypeDecl::Kind > OpenVarSet;
     34        typedef std::map< std::string, TypeDecl::Data > OpenVarSet;
    3535
    3636        void printAssertionSet( const AssertionSet &, std::ostream &, int indent = 0 );
     
    4141                Type *type;
    4242                bool allowWidening;
    43                 TypeDecl::Kind kind;
     43                TypeDecl::Data data;
    4444
    4545                void initialize( const EqvClass &src, EqvClass &dest );
  • src/ResolvExpr/Unify.cc

    r596f987b r66f8528  
    9999                newFirst->get_qualifiers() = Type::Qualifiers();
    100100                newSecond->get_qualifiers() = Type::Qualifiers();
    101 ///   std::cout << "first is ";
    102 ///   first->print( std::cout );
    103 ///   std::cout << std::endl << "second is ";
    104 ///   second->print( std::cout );
    105 ///   std::cout << std::endl << "newFirst is ";
    106 ///   newFirst->print( std::cout );
    107 ///   std::cout << std::endl << "newSecond is ";
    108 ///   newSecond->print( std::cout );
    109 ///   std::cout << std::endl;
     101///   std::cerr << "first is ";
     102///   first->print( std::cerr );
     103///   std::cerr << std::endl << "second is ";
     104///   second->print( std::cerr );
     105///   std::cerr << std::endl << "newFirst is ";
     106///   newFirst->print( std::cerr );
     107///   std::cerr << std::endl << "newSecond is ";
     108///   newSecond->print( std::cerr );
     109///   std::cerr << std::endl;
    110110                bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    111111                delete newFirst;
     
    123123        }
    124124
    125         bool tyVarCompatible( TypeDecl::Kind kind, Type *type, const SymTab::Indexer &indexer ) {
    126                 switch ( kind ) {
     125        struct CompleteTypeChecker : public Visitor {
     126                virtual void visit( VoidType *basicType ) { status = false; }
     127                virtual void visit( BasicType *basicType ) {}
     128                virtual void visit( PointerType *pointerType ) {}
     129                virtual void visit( ArrayType *arrayType ) { status = ! arrayType->get_isVarLen(); }
     130                virtual void visit( FunctionType *functionType ) {}
     131                virtual void visit( StructInstType *aggregateUseType ) { status = aggregateUseType->get_baseStruct()->has_body(); }
     132                virtual void visit( UnionInstType *aggregateUseType ) { status = aggregateUseType->get_baseUnion()->has_body(); }
     133                // xxx - enum inst does not currently contain a pointer to base, this should be fixed.
     134                virtual void visit( EnumInstType *aggregateUseType ) { /* status = aggregateUseType->get_baseEnum()->hasBody(); */ }
     135                virtual void visit( TraitInstType *aggregateUseType ) { assert( false ); }
     136                virtual void visit( TypeInstType *aggregateUseType ) { status = aggregateUseType->get_baseType()->isComplete(); }
     137                virtual void visit( TupleType *tupleType ) {} // xxx - not sure if this is right, might need to recursively check complete-ness
     138                virtual void visit( TypeofType *typeofType ) { assert( false ); }
     139                virtual void visit( AttrType *attrType ) { assert( false ); } // xxx - not sure what to do here
     140                virtual void visit( VarArgsType *varArgsType ){} // xxx - is this right?
     141                virtual void visit( ZeroType *zeroType ) {}
     142                virtual void visit( OneType *oneType ) {}
     143                bool status = true;
     144        };
     145        bool isComplete( Type * type ) {
     146                CompleteTypeChecker checker;
     147                assert( type );
     148                type->accept( checker );
     149                return checker.status;
     150        }
     151
     152        bool tyVarCompatible( const TypeDecl::Data & data, Type *type, const SymTab::Indexer &indexer ) {
     153                switch ( data.kind ) {
    127154                  case TypeDecl::Any:
    128155                  case TypeDecl::Dtype:
    129                         return ! isFtype( type, indexer );
    130 
     156                        // to bind to an object type variable, the type must not be a function type.
     157                        // if the type variable is specified to be a complete type then the incoming
     158                        // type must also be complete
     159                        return ! isFtype( type, indexer ) && (! data.isComplete || isComplete( type ));
    131160                  case TypeDecl::Ftype:
    132161                        return isFtype( type, indexer );
     
    136165        }
    137166
    138         bool bindVar( TypeInstType *typeInst, Type *other, TypeDecl::Kind kind, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     167        bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
    139168                OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
    140169                assert( tyvar != openVars.end() );
     
    175204                        newClass.type->get_qualifiers() = Type::Qualifiers();
    176205                        newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
    177                         newClass.kind = kind;
     206                        newClass.data = data;
    178207                        env.add( newClass );
    179208                } // if
     
    181210        }
    182211
    183         bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Kind kind, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     212        bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
    184213                bool result = true;
    185214                EqvClass class1, class2;
     
    210239
    211240                if ( type1 && type2 ) {
    212 //    std::cout << "has type1 && type2" << std::endl;
     241//    std::cerr << "has type1 && type2" << std::endl;
    213242                        WidenMode newWidenMode ( widen1, widen2 );
    214243                        Type *common = 0;
     
    248277                        newClass.vars.insert( var2->get_name() );
    249278                        newClass.allowWidening = widen1 && widen2;
    250                         newClass.kind = kind;
     279                        newClass.data = data;
    251280                        env.add( newClass );
    252281                } // if
     
    311340                } // if
    312341#ifdef DEBUG
    313                 std::cout << "============ unifyExact" << std::endl;
    314                 std::cout << "type1 is ";
    315                 type1->print( std::cout );
    316                 std::cout << std::endl << "type2 is ";
    317                 type2->print( std::cout );
    318                 std::cout << std::endl << "openVars are ";
    319                 printOpenVarSet( openVars, std::cout, 8 );
    320                 std::cout << std::endl << "input env is " << std::endl;
    321                 debugEnv.print( std::cout, 8 );
    322                 std::cout << std::endl << "result env is " << std::endl;
    323                 env.print( std::cout, 8 );
    324                 std::cout << "result is " << result << std::endl;
     342                std::cerr << "============ unifyExact" << std::endl;
     343                std::cerr << "type1 is ";
     344                type1->print( std::cerr );
     345                std::cerr << std::endl << "type2 is ";
     346                type2->print( std::cerr );
     347                std::cerr << std::endl << "openVars are ";
     348                printOpenVarSet( openVars, std::cerr, 8 );
     349                std::cerr << std::endl << "input env is " << std::endl;
     350                debugEnv.print( std::cerr, 8 );
     351                std::cerr << std::endl << "result env is " << std::endl;
     352                env.print( std::cerr, 8 );
     353                std::cerr << "result is " << result << std::endl;
    325354#endif
    326355                return result;
     
    337366                bool result;
    338367#ifdef DEBUG
    339                 std::cout << "unifyInexact type 1 is ";
    340                 type1->print( std::cout );
    341                 std::cout << "type 2 is ";
    342                 type2->print( std::cout );
    343                 std::cout << std::endl;
     368                std::cerr << "unifyInexact type 1 is ";
     369                type1->print( std::cerr );
     370                std::cerr << "type 2 is ";
     371                type2->print( std::cerr );
     372                std::cerr << std::endl;
    344373#endif
    345374                if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ) ) {
    346375#ifdef DEBUG
    347                         std::cout << "unifyInexact: no exact unification found" << std::endl;
     376                        std::cerr << "unifyInexact: no exact unification found" << std::endl;
    348377#endif
    349378                        if ( ( common = commonType( type1, type2, widenMode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) {
    350379                                common->get_qualifiers() = tq1 + tq2;
    351380#ifdef DEBUG
    352                                 std::cout << "unifyInexact: common type is ";
    353                                 common->print( std::cout );
    354                                 std::cout << std::endl;
     381                                std::cerr << "unifyInexact: common type is ";
     382                                common->print( std::cerr );
     383                                std::cerr << std::endl;
    355384#endif
    356385                                result = true;
    357386                        } else {
    358387#ifdef DEBUG
    359                                 std::cout << "unifyInexact: no common type found" << std::endl;
     388                                std::cerr << "unifyInexact: no common type found" << std::endl;
    360389#endif
    361390                                result = false;
     
    394423
    395424        void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) {
    396 ///   std::cout << "assertion set is" << std::endl;
    397 ///   printAssertionSet( assertions, std::cout, 8 );
    398 ///   std::cout << "looking for ";
    399 ///   assert->print( std::cout );
    400 ///   std::cout << std::endl;
     425///   std::cerr << "assertion set is" << std::endl;
     426///   printAssertionSet( assertions, std::cerr, 8 );
     427///   std::cerr << "looking for ";
     428///   assert->print( std::cerr );
     429///   std::cerr << std::endl;
    401430                AssertionSet::iterator i = assertions.find( assert );
    402431                if ( i != assertions.end() ) {
    403 ///     std::cout << "found it!" << std::endl;
     432///     std::cerr << "found it!" << std::endl;
    404433                        i->second = true;
    405434                } // if
  • src/ResolvExpr/Unify.h

    r596f987b r66f8528  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Unify.h -- 
     7// Unify.h --
    88//
    99// Author           : Richard C. Bilson
     
    3737                bool widenFirst : 1, widenSecond : 1;
    3838        };
    39        
    40         bool bindVar( TypeInstType *typeInst, Type *other, TypeDecl::Kind kind, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     39
     40        bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
    4141        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    4242        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
  • src/SymTab/Autogen.cc

    r596f987b r66f8528  
    2424#include "MakeLibCfa.h"
    2525#include "Autogen.h"
     26#include "GenPoly/ScopedSet.h"
     27#include "SymTab/Mangler.h"
     28#include "GenPoly/DeclMutator.h"
    2629
    2730namespace SymTab {
     
    2932
    3033        class AutogenerateRoutines : public Visitor {
    31                 public:
     34          public:
    3235                std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
     36
     37                typedef Visitor Parent;
     38                using Parent::visit;
    3339
    3440                virtual void visit( EnumDecl *enumDecl );
     
    4551                virtual void visit( SwitchStmt *switchStmt );
    4652
    47                 AutogenerateRoutines() : functionNesting( 0 ) {}
    48                 private:
     53          private:
    4954                template< typename StmtClass > void visitStatement( StmtClass *stmt );
    5055
    5156                std::list< Declaration * > declsToAdd;
    5257                std::set< std::string > structsDone;
    53                 unsigned int functionNesting;     // current level of nested functions
     58                unsigned int functionNesting = 0;     // current level of nested functions
    5459        };
    5560
     61        /// generates routines for tuple types.
     62        /// Doesn't really need to be a mutator, but it's easier to reuse DeclMutator than it is to use AddVisit
     63        /// or anything we currently have that supports adding new declarations for visitors
     64        class AutogenTupleRoutines : public GenPoly::DeclMutator {
     65          public:
     66                typedef GenPoly::DeclMutator Parent;
     67                using Parent::mutate;
     68
     69                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
     70
     71                virtual Type * mutate( TupleType *tupleType );
     72
     73                virtual CompoundStmt * mutate( CompoundStmt *compoundStmt );
     74
     75          private:
     76                unsigned int functionNesting = 0;     // current level of nested functions
     77                GenPoly::ScopedSet< std::string > seenTuples;
     78        };
     79
    5680        void autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
    57                 AutogenerateRoutines visitor;
    58                 acceptAndAdd( translationUnit, visitor, false );
     81                AutogenerateRoutines generator;
     82                acceptAndAdd( translationUnit, generator, false );
     83
     84                // needs to be done separately because AutogenerateRoutines skips types that appear as function arguments, etc.
     85                // AutogenTupleRoutines tupleGenerator;
     86                // tupleGenerator.mutateDeclarationList( translationUnit );
    5987        }
    6088
     
    6391        }
    6492
    65         template< typename OutputIterator >
    66         void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, OutputIterator out ) {
    67                 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
    68                 copy->get_args().push_back( new VariableExpr( dstParam ) );
    69                 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
    70                 copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) );
    71 
    72                 *out++ = new ExprStmt( noLabels, copy );
    73         }
    74 
    75         //E ?=?(E volatile*, int),
    76         //  ?=?(E _Atomic volatile*, int);
    77         void makeEnumFunctions( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
    78                 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    79 
    80                 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), refType ), 0 );
    81                 assignType->get_parameters().push_back( dstParam );
    82 
    83                 // void ?{}(E *); void ^?{}(E *);
    84                 FunctionType * ctorType = assignType->clone();
    85                 FunctionType * dtorType = assignType->clone();
    86 
    87                 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
    88                 assignType->get_parameters().push_back( srcParam );
    89                 // void ?{}(E *, E);
    90                 FunctionType *copyCtorType = assignType->clone();
    91 
    92                 // T ?=?(E *, E);
    93                 ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
    94                 assignType->get_returnVals().push_back( returnVal );
    95 
    96                 // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)?
    97                 // right now these cases work, but that might change.
    98 
    99                 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
     93        /// inserts a forward declaration for functionDecl into declsToAdd
     94        void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) {
     95                FunctionDecl * decl = functionDecl->clone();
     96                delete decl->get_statements();
     97                decl->set_statements( NULL );
     98                declsToAdd.push_back( decl );
     99                decl->fixUniqueId();
     100        }
     101
     102        /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
     103        FunctionType * genDefaultType( Type * paramType ) {
     104                FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
     105                ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), paramType->clone() ), nullptr );
     106                ftype->get_parameters().push_back( dstParam );
     107
     108                return ftype;
     109        }
     110
     111        /// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T)
     112        FunctionType * genCopyType( Type * paramType ) {
     113                FunctionType *ftype = genDefaultType( paramType );
     114                ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
     115                ftype->get_parameters().push_back( srcParam );
     116                return ftype;
     117        }
     118
     119        /// given type T, generate type of assignment, i.e. function type T (*) (T *, T)
     120        FunctionType * genAssignType( Type * paramType ) {
     121                FunctionType *ftype = genCopyType( paramType );
     122                ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
     123                ftype->get_returnVals().push_back( returnVal );
     124                return ftype;
     125        }
     126
     127        /// true if the aggregate's layout is dynamic
     128        template< typename AggrDecl >
     129        bool hasDynamicLayout( AggrDecl * aggregateDecl ) {
     130                for ( TypeDecl * param : aggregateDecl->get_parameters() ) {
     131                        if ( param->get_kind() == TypeDecl::Any ) return true;
     132                }
     133                return false;
     134        }
     135
     136        /// generate a function decl from a name and type. Nesting depth determines whether
     137        /// the declaration is static or not; optional paramter determines if declaration is intrinsic
     138        FunctionDecl * genFunc( const std::string & fname, FunctionType * ftype, unsigned int functionNesting, bool isIntrinsic = false  ) {
     139                // Routines at global scope marked "static" to prevent multiple definitions in separate translation units
    100140                // because each unit generates copies of the default routines for each aggregate.
    101                 // xxx - Temporary: make these functions intrinsic so they codegen as C assignment.
    102                 // Really they're something of a cross between instrinsic and autogen, so should
    103                 // probably make a new linkage type
    104                 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, new CompoundStmt( noLabels ), true, false );
    105                 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, ctorType, new CompoundStmt( noLabels ), true, false );
    106                 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, copyCtorType, new CompoundStmt( noLabels ), true, false );
    107                 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, dtorType, new CompoundStmt( noLabels ), true, false );
    108                 assignDecl->fixUniqueId();
    109                 ctorDecl->fixUniqueId();
    110                 copyCtorDecl->fixUniqueId();
    111                 dtorDecl->fixUniqueId();
    112 
     141                DeclarationNode::StorageClass sc = functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static;
     142                LinkageSpec::Spec spec = isIntrinsic ? LinkageSpec::Intrinsic : LinkageSpec::AutoGen;
     143                FunctionDecl * decl = new FunctionDecl( fname, sc, spec, ftype, new CompoundStmt( noLabels ), true, false );
     144                decl->fixUniqueId();
     145                return decl;
     146        }
     147
     148        /// generates a single enumeration assignment expression
     149        ApplicationExpr * genEnumAssign( FunctionType * ftype, FunctionDecl * assignDecl ) {
    113150                // enum copy construct and assignment is just C-style assignment.
    114151                // this looks like a bad recursive call, but code gen will turn it into
    115152                // a C-style assignment.
    116153                // This happens before function pointer type conversion, so need to do it manually here
     154                // NOTE: ftype is not necessarily the functionType belonging to assignDecl - ftype is the
     155                // type of the function that this expression is being generated for (so that the correct
     156                // parameters) are using in the variable exprs
     157                assert( ftype->get_parameters().size() == 2 );
     158                ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
     159                ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
     160
    117161                VariableExpr * assignVarExpr = new VariableExpr( assignDecl );
    118162                Type * assignVarExprType = assignVarExpr->get_result();
     
    122166                assignExpr->get_args().push_back( new VariableExpr( dstParam ) );
    123167                assignExpr->get_args().push_back( new VariableExpr( srcParam ) );
     168                return assignExpr;
     169        }
     170
     171        // E ?=?(E volatile*, int),
     172        //   ?=?(E _Atomic volatile*, int);
     173        void makeEnumFunctions( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
     174
     175                // T ?=?(E *, E);
     176                FunctionType *assignType = genAssignType( refType );
     177
     178                // void ?{}(E *); void ^?{}(E *);
     179                FunctionType * ctorType = genDefaultType( refType->clone() );
     180                FunctionType * dtorType = genDefaultType( refType->clone() );
     181
     182                // void ?{}(E *, E);
     183                FunctionType *copyCtorType = genCopyType( refType->clone() );
     184
     185                // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)?
     186                // right now these cases work, but that might change.
     187
     188                // xxx - Temporary: make these functions intrinsic so they codegen as C assignment.
     189                // Really they're something of a cross between instrinsic and autogen, so should
     190                // probably make a new linkage type
     191                FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting, true );
     192                FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting, true );
     193                FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting, true );
     194                FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting, true );
    124195
    125196                // body is either return stmt or expr stmt
    126                 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, assignExpr ) );
    127                 copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, assignExpr->clone() ) );
    128 
    129                 declsToAdd.push_back( assignDecl );
     197                assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, genEnumAssign( assignType, assignDecl ) ) );
     198                copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, genEnumAssign( copyCtorType, assignDecl ) ) );
     199
    130200                declsToAdd.push_back( ctorDecl );
    131201                declsToAdd.push_back( copyCtorDecl );
    132202                declsToAdd.push_back( dtorDecl );
    133         }
    134 
    135         /// Clones a reference type, replacing any parameters it may have with a clone of the provided list
    136         template< typename GenericInstType >
    137         GenericInstType *cloneWithParams( GenericInstType *refType, const std::list< Expression* >& params ) {
    138                 GenericInstType *clone = refType->clone();
    139                 clone->get_parameters().clear();
    140                 cloneAll( params, clone->get_parameters() );
    141                 return clone;
    142         }
    143 
    144         /// Creates a new type decl that's the same as src, but renamed and with only the ?=?, ?{} (default and copy), and ^?{} assertions (for complete types only)
    145         TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
    146                 // TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() );
    147 
    148                 // if ( src->get_kind() == TypeDecl::Any ) {
    149                 //      TypeInstType *opParamType = new TypeInstType( Type::Qualifiers(), name, dst );
    150                 //      FunctionType *opFunctionType = new FunctionType( Type::Qualifiers(), false );
    151                 //      opFunctionType->get_parameters().push_back(
    152                 //              new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), opParamType->clone() ), 0 ) );
    153                 //      FunctionDecl *ctorAssert = new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType->clone(), 0, false, false );
    154                 //      FunctionDecl *dtorAssert = new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType->clone(), 0, false, false );
    155 
    156                 //      opFunctionType->get_parameters().push_back(
    157                 //              new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, opParamType, 0 ) );
    158                 //      FunctionDecl *copyCtorAssert = new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType->clone(), 0, false, false );
    159 
    160                 //      opFunctionType->get_returnVals().push_back(
    161                 //              new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, opParamType->clone(), 0 ) );
    162                 //      FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType, 0, false, false );
    163 
    164 
    165                 //      dst->get_assertions().push_back( assignAssert );
    166                 //      dst->get_assertions().push_back( ctorAssert );
    167                 //      dst->get_assertions().push_back( dtorAssert );
    168                 //      dst->get_assertions().push_back( copyCtorAssert );
    169                 // }
    170 
    171                 TypeDecl *dst = new TypeDecl( src->get_name(), src->get_storageClass(), 0, src->get_kind() );
    172                 cloneAll(src->get_assertions(), dst->get_assertions());
    173                 return dst;
    174         }
    175 
    176         void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, TypeSubstitution & genericSubs, bool isDynamicLayout, bool forward = true ) {
    177 //              if ( isDynamicLayout && src ) {
    178 //                      genericSubs.apply( src );
    179 //              }
    180 
     203                declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
     204        }
     205
     206        /// generates a single struct member operation (constructor call, destructor call, assignment call)
     207        void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) {
    181208                ObjectDecl * returnVal = NULL;
    182209                if ( ! func->get_functionType()->get_returnVals().empty() ) {
     
    187214
    188215                // assign to destination (and return value if generic)
    189                 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
    190                 derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
     216                UntypedExpr *derefExpr = UntypedExpr::createDeref( new VariableExpr( dstParam ) );
    191217                Expression *dstselect = new MemberExpr( field, derefExpr );
    192218                genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    193219
    194220                if ( isDynamicLayout && returnVal ) {
    195                         UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
    196                         derefRet->get_args().push_back( new VariableExpr( returnVal ) );
    197                         Expression *retselect = new MemberExpr( field, derefRet );
     221                        // xxx - there used to be a dereference on returnVal, but this seems to have been wrong?
     222                        Expression *retselect = new MemberExpr( field, new VariableExpr( returnVal ) );
    198223                        genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    199224                } // if
    200225        }
    201226
     227        /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies
    202228        template<typename Iterator>
    203         void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs, bool isDynamicLayout, bool forward = true ) {
     229        void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) {
    204230                for ( ; member != end; ++member ) {
    205231                        if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate
     
    237263
    238264                                Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL;
    239                                 makeStructMemberOp( dstParam, srcselect, field, func, genericSubs, isDynamicLayout, forward );
     265                                makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout, forward );
    240266                        } // if
    241267                } // for
     
    245271        /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
    246272        template<typename Iterator>
    247         void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs, bool isDynamicLayout ) {
     273        void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout ) {
    248274                FunctionType * ftype = func->get_functionType();
    249275                std::list<DeclarationWithType*> & params = ftype->get_parameters();
     
    271297                                        // matching parameter, initialize field with copy ctor
    272298                                        Expression *srcselect = new VariableExpr(*parameter);
    273                                         makeStructMemberOp( dstParam, srcselect, field, func, genericSubs, isDynamicLayout );
     299                                        makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout );
    274300                                        ++parameter;
    275301                                } else {
    276302                                        // no matching parameter, initialize field with default ctor
    277                                         makeStructMemberOp( dstParam, NULL, field, func, genericSubs, isDynamicLayout );
     303                                        makeStructMemberOp( dstParam, NULL, field, func, isDynamicLayout );
    278304                                }
    279305                        }
     
    281307        }
    282308
    283         void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) {
    284                 FunctionDecl * decl = functionDecl->clone();
    285                 delete decl->get_statements();
    286                 decl->set_statements( NULL );
    287                 declsToAdd.push_back( decl );
    288                 decl->fixUniqueId();
    289         }
    290 
     309        /// generates struct constructors, destructor, and assignment functions
    291310        void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
    292                 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    293311
    294312                // Make function polymorphic in same parameters as generic struct, if applicable
    295                 bool isDynamicLayout = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
    296                 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
    297                 std::list< Expression* > structParams;  // List of matching parameters to put on types
    298                 TypeSubstitution genericSubs; // Substitutions to make to member types of struct
    299                 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    300                         if ( (*param)->get_kind() == TypeDecl::Any ) isDynamicLayout = true;
    301                         TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
    302                         assignType->get_forall().push_back( typeParam );
    303                         TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
    304                         genericSubs.add( (*param)->get_name(), newParamType );
    305                         structParams.push_back( new TypeExpr( newParamType ) );
    306                 }
    307 
    308                 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
    309                 assignType->get_parameters().push_back( dstParam );
     313                const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
     314                bool isDynamicLayout = hasDynamicLayout( aggregateDecl );  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
     315
     316                // T ?=?(T *, T);
     317                FunctionType *assignType = genAssignType( refType );
     318                cloneAll( typeParams, assignType->get_forall() );
    310319
    311320                // void ?{}(T *); void ^?{}(T *);
    312                 FunctionType *ctorType = assignType->clone();
    313                 FunctionType *dtorType = assignType->clone();
    314 
    315                 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
    316                 assignType->get_parameters().push_back( srcParam );
     321                FunctionType *ctorType = genDefaultType( refType );
     322                cloneAll( typeParams, ctorType->get_forall() );
     323                FunctionType *dtorType = genDefaultType( refType );
     324                cloneAll( typeParams, dtorType->get_forall() );
    317325
    318326                // void ?{}(T *, T);
    319                 FunctionType *copyCtorType = assignType->clone();
    320 
    321                 // T ?=?(T *, T);
    322                 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
    323                 assignType->get_returnVals().push_back( returnVal );
    324 
    325                 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    326                 // because each unit generates copies of the default routines for each aggregate.
    327                 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
    328                 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false );
    329                 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, new CompoundStmt( noLabels ), true, false );
    330                 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false );
    331                 assignDecl->fixUniqueId();
    332                 ctorDecl->fixUniqueId();
    333                 copyCtorDecl->fixUniqueId();
    334                 dtorDecl->fixUniqueId();
     327                FunctionType *copyCtorType = genCopyType( refType );
     328                cloneAll( typeParams, copyCtorType->get_forall() );
     329
     330                FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting );
     331                FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting );
     332                FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting );
     333                FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting );
    335334
    336335                if ( functionNesting == 0 ) {
    337336                        // forward declare if top-level struct, so that
    338337                        // type is complete as soon as its body ends
     338                        // Note: this is necessary if we want structs which contain
     339                        // generic (otype) structs as members.
    339340                        addForwardDecl( assignDecl, declsToAdd );
    340341                        addForwardDecl( ctorDecl, declsToAdd );
     
    365366                        }
    366367                        memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) );
    367                         FunctionDecl * ctor = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, memCtorType->clone(), new CompoundStmt( noLabels ), true, false );
    368                         ctor->fixUniqueId();
    369                         makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, genericSubs, isDynamicLayout );
     368                        FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
     369                        makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, isDynamicLayout );
    370370                        memCtors.push_back( ctor );
    371371                }
     
    373373
    374374                // generate appropriate calls to member ctor, assignment
    375                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, genericSubs, isDynamicLayout );
    376                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, genericSubs, isDynamicLayout );
    377                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, genericSubs, isDynamicLayout );
     375                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, isDynamicLayout );
     376                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, isDynamicLayout );
     377                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, isDynamicLayout );
    378378                // needs to do everything in reverse, so pass "forward" as false
    379                 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, genericSubs, isDynamicLayout, false );
    380 
    381                 if ( ! isDynamicLayout ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    382 
    383                 declsToAdd.push_back( assignDecl );
     379                makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, isDynamicLayout, false );
     380
     381                assert( assignType->get_parameters().size() == 2 );
     382                ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() );
     383                assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
     384
    384385                declsToAdd.push_back( ctorDecl );
    385386                declsToAdd.push_back( copyCtorDecl );
    386387                declsToAdd.push_back( dtorDecl );
     388                declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
    387389                declsToAdd.splice( declsToAdd.end(), memCtors );
    388390        }
    389391
     392        /// generate a single union assignment expression (using memcpy)
     393        template< typename OutputIterator >
     394        void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) {
     395                UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
     396                copy->get_args().push_back( new VariableExpr( dstParam ) );
     397                copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
     398                copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) );
     399                *out++ = new ExprStmt( noLabels, copy );
     400        }
     401
     402        /// generates the body of a union assignment/copy constructor/field constructor
     403        void makeUnionAssignBody( FunctionDecl * funcDecl, bool isDynamicLayout ) {
     404                FunctionType * ftype = funcDecl->get_functionType();
     405                assert( ftype->get_parameters().size() == 2 );
     406                ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
     407                ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
     408                ObjectDecl * returnVal = nullptr;
     409                if ( ! ftype->get_returnVals().empty() ) {
     410                        returnVal = safe_dynamic_cast< ObjectDecl * >( ftype->get_returnVals().front() );
     411                }
     412
     413                makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) );
     414                if ( returnVal ) {
     415                        if ( isDynamicLayout ) makeUnionFieldsAssignment( srcParam, returnVal, back_inserter( funcDecl->get_statements()->get_kids() ) );
     416                        else funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
     417                }
     418        }
     419
     420        /// generates union constructors, destructors, and assignment operator
    390421        void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
    391                 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    392 
    393422                // Make function polymorphic in same parameters as generic union, if applicable
    394                 bool isDynamicLayout = false; // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
    395                 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
    396                 std::list< Expression* > unionParams;  // List of matching parameters to put on types
    397                 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    398                         if ( (*param)->get_kind() == TypeDecl::Any ) isDynamicLayout = true;
    399                         TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
    400                         assignType->get_forall().push_back( typeParam );
    401                         unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
    402                 }
    403 
    404                 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 );
    405                 assignType->get_parameters().push_back( dstParam );
     423                const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
     424                bool isDynamicLayout = hasDynamicLayout( aggregateDecl );  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
    406425
    407426                // default ctor/dtor need only first parameter
    408                 FunctionType * ctorType = assignType->clone();
    409                 FunctionType * dtorType = assignType->clone();
    410 
    411                 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
    412                 assignType->get_parameters().push_back( srcParam );
     427                // void ?{}(T *); void ^?{}(T *);
     428                FunctionType *ctorType = genDefaultType( refType );
     429                FunctionType *dtorType = genDefaultType( refType );
    413430
    414431                // copy ctor needs both parameters
    415                 FunctionType * copyCtorType = assignType->clone();
     432                // void ?{}(T *, T);
     433                FunctionType *copyCtorType = genCopyType( refType );
    416434
    417435                // assignment needs both and return value
    418                 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
    419                 assignType->get_returnVals().push_back( returnVal );
     436                // T ?=?(T *, T);
     437                FunctionType *assignType = genAssignType( refType );
     438
     439                cloneAll( typeParams, ctorType->get_forall() );
     440                cloneAll( typeParams, dtorType->get_forall() );
     441                cloneAll( typeParams, copyCtorType->get_forall() );
     442                cloneAll( typeParams, assignType->get_forall() );
    420443
    421444                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    422445                // because each unit generates copies of the default routines for each aggregate.
    423                 FunctionDecl *assignDecl = new FunctionDecl( "?=?",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
    424                 FunctionDecl *ctorDecl = new FunctionDecl( "?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false );
    425                 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, NULL, true, false );
    426                 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false );
    427 
    428                 assignDecl->fixUniqueId();
    429                 ctorDecl->fixUniqueId();
    430                 copyCtorDecl->fixUniqueId();
    431                 dtorDecl->fixUniqueId();
    432 
    433                 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( assignDecl->get_statements()->get_kids() ) );
    434                 if ( isDynamicLayout ) makeUnionFieldsAssignment( srcParam, returnVal, back_inserter( assignDecl->get_statements()->get_kids() ) );
    435                 else assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
     446                FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting );
     447                FunctionDecl *ctorDecl = genFunc( "?{}",  ctorType, functionNesting );
     448                FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting );
     449                FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting );
     450
     451                makeUnionAssignBody( assignDecl, isDynamicLayout );
    436452
    437453                // body of assignment and copy ctor is the same
    438                 copyCtorDecl->set_statements( assignDecl->get_statements()->clone() );
     454                makeUnionAssignBody( copyCtorDecl, isDynamicLayout );
    439455
    440456                // create a constructor which takes the first member type as a parameter.
     
    449465                                FunctionType * memCtorType = ctorType->clone();
    450466                                memCtorType->get_parameters().push_back( srcParam );
    451                                 FunctionDecl * ctor = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, memCtorType, new CompoundStmt( noLabels ), true, false );
    452                                 ctor->fixUniqueId();
    453 
    454                                 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( ctor->get_statements()->get_kids() ) );
     467                                FunctionDecl * ctor = genFunc( "?{}", memCtorType, functionNesting );
     468
     469                                makeUnionAssignBody( ctor, isDynamicLayout );
    455470                                memCtors.push_back( ctor );
    456471                                // only generate a ctor for the first field
     
    459474                }
    460475
    461                 declsToAdd.push_back( assignDecl );
    462476                declsToAdd.push_back( ctorDecl );
    463477                declsToAdd.push_back( copyCtorDecl );
    464478                declsToAdd.push_back( dtorDecl );
     479                declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
    465480                declsToAdd.splice( declsToAdd.end(), memCtors );
    466481        }
     
    478493                if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
    479494                        StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
     495                        for ( TypeDecl * typeDecl : structDecl->get_parameters() ) {
     496                                structInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
     497                        }
    480498                        structInst.set_baseStruct( structDecl );
    481499                        makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd );
     
    488506                        UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
    489507                        unionInst.set_baseUnion( unionDecl );
     508                        for ( TypeDecl * typeDecl : unionDecl->get_parameters() ) {
     509                                unionInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
     510                        }
    490511                        makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAdd );
    491512                } // if
     
    493514
    494515        void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
    495                 CompoundStmt *stmts = 0;
    496516                TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false );
    497517                typeInst->set_baseType( typeDecl );
    498                 ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 );
    499                 ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 );
     518                ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, typeInst->clone(), nullptr );
     519                ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), typeInst->clone() ), nullptr );
     520
     521                std::list< Statement * > stmts;
    500522                if ( typeDecl->get_base() ) {
    501523                        // xxx - generate ctor/dtors for typedecls, e.g.
    502524                        // otype T = int *;
    503                         stmts = new CompoundStmt( std::list< Label >() );
    504525                        UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
    505526                        assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) );
    506527                        assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) );
    507                         stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) );
     528                        stmts.push_back( new ReturnStmt( std::list< Label >(), assign ) );
    508529                } // if
    509530                FunctionType *type = new FunctionType( Type::Qualifiers(), false );
     
    511532                type->get_parameters().push_back( dst );
    512533                type->get_parameters().push_back( src );
    513                 FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, true, false );
     534                FunctionDecl *func = genFunc( "?=?", type, functionNesting );
     535                func->get_statements()->get_kids() = stmts;
    514536                declsToAdd.push_back( func );
    515537        }
     
    556578                visitStatement( switchStmt );
    557579        }
     580
     581        void makeTupleFunctionBody( FunctionDecl * function ) {
     582                FunctionType * ftype = function->get_functionType();
     583                assertf( ftype->get_parameters().size() == 1 || ftype->get_parameters().size() == 2, "too many parameters in generated tuple function" );
     584
     585                UntypedExpr * untyped = new UntypedExpr( new NameExpr( function->get_name() ) );
     586
     587                /// xxx - &* is used to make this easier for later passes to handle
     588                untyped->get_args().push_back( new AddressExpr( UntypedExpr::createDeref( new VariableExpr( ftype->get_parameters().front() ) ) ) );
     589                if ( ftype->get_parameters().size() == 2 ) {
     590                        untyped->get_args().push_back( new VariableExpr( ftype->get_parameters().back() ) );
     591                }
     592                function->get_statements()->get_kids().push_back( new ExprStmt( noLabels, untyped ) );
     593                function->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, UntypedExpr::createDeref( new VariableExpr( ftype->get_parameters().front() ) ) ) );
     594        }
     595
     596        Type * AutogenTupleRoutines::mutate( TupleType * tupleType ) {
     597                tupleType = safe_dynamic_cast< TupleType * >( Parent::mutate( tupleType ) );
     598                std::string mangleName = SymTab::Mangler::mangleType( tupleType );
     599                if ( seenTuples.find( mangleName ) != seenTuples.end() ) return tupleType;
     600                seenTuples.insert( mangleName );
     601
     602                // T ?=?(T *, T);
     603                FunctionType *assignType = genAssignType( tupleType );
     604
     605                // void ?{}(T *); void ^?{}(T *);
     606                FunctionType *ctorType = genDefaultType( tupleType );
     607                FunctionType *dtorType = genDefaultType( tupleType );
     608
     609                // void ?{}(T *, T);
     610                FunctionType *copyCtorType = genCopyType( tupleType );
     611
     612                std::set< TypeDecl* > done;
     613                std::list< TypeDecl * > typeParams;
     614                for ( Type * t : *tupleType ) {
     615                        if ( TypeInstType * ty = dynamic_cast< TypeInstType * >( t ) ) {
     616                                if ( ! done.count( ty->get_baseType() ) ) {
     617                                        TypeDecl * newDecl = new TypeDecl( ty->get_baseType()->get_name(), DeclarationNode::NoStorageClass, nullptr, TypeDecl::Any );
     618                                        TypeInstType * inst = new TypeInstType( Type::Qualifiers(), newDecl->get_name(), newDecl );
     619                                        newDecl->get_assertions().push_back( new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, genAssignType( inst ), nullptr, true, false ) );
     620                                        newDecl->get_assertions().push_back( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, genDefaultType( inst ), nullptr, true, false ) );
     621                                        newDecl->get_assertions().push_back( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, genCopyType( inst ), nullptr, true, false ) );
     622                                        newDecl->get_assertions().push_back( new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, genDefaultType( inst ), nullptr, true, false ) );
     623                                        typeParams.push_back( newDecl );
     624                                        done.insert( ty->get_baseType() );
     625                                }
     626                        }
     627                }
     628                cloneAll( typeParams, ctorType->get_forall() );
     629                cloneAll( typeParams, dtorType->get_forall() );
     630                cloneAll( typeParams, copyCtorType->get_forall() );
     631                cloneAll( typeParams, assignType->get_forall() );
     632
     633                FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting );
     634                FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting );
     635                FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting );
     636                FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting );
     637
     638                makeTupleFunctionBody( assignDecl );
     639                makeTupleFunctionBody( ctorDecl );
     640                makeTupleFunctionBody( copyCtorDecl );
     641                makeTupleFunctionBody( dtorDecl );
     642
     643                addDeclaration( ctorDecl );
     644                addDeclaration( copyCtorDecl );
     645                addDeclaration( dtorDecl );
     646                addDeclaration( assignDecl ); // assignment should come last since it uses copy constructor in return
     647
     648                return tupleType;
     649        }
     650
     651        DeclarationWithType * AutogenTupleRoutines::mutate( FunctionDecl *functionDecl ) {
     652                functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
     653                mutateAll( functionDecl->get_oldDecls(), *this );
     654                functionNesting += 1;
     655                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
     656                functionNesting -= 1;
     657                return functionDecl;
     658        }
     659
     660        CompoundStmt * AutogenTupleRoutines::mutate( CompoundStmt *compoundStmt ) {
     661                seenTuples.beginScope();
     662                compoundStmt = safe_dynamic_cast< CompoundStmt * >( Parent::mutate( compoundStmt ) );
     663                seenTuples.endScope();
     664                return compoundStmt;
     665        }
    558666} // SymTab
  • src/SymTab/Indexer.cc

    r596f987b r66f8528  
    4040
    4141namespace SymTab {
     42        struct NewScope {
     43                NewScope( SymTab::Indexer & indexer ) : indexer( indexer ) { indexer.enterScope(); }
     44                ~NewScope() { indexer.leaveScope(); }
     45                SymTab::Indexer & indexer;
     46        };
     47
    4248        template< typename TreeType, typename VisitorType >
    4349        inline void acceptNewScope( TreeType *tree, VisitorType &visitor ) {
     
    454460        void Indexer::visit( TupleAssignExpr *tupleExpr ) {
    455461                acceptNewScope( tupleExpr->get_result(), *this );
    456                 enterScope();
    457                 acceptAll( tupleExpr->get_tempDecls(), *this );
    458                 acceptAll( tupleExpr->get_assigns(), *this );
    459                 leaveScope();
     462                maybeAccept( tupleExpr->get_stmtExpr(), *this );
    460463        }
    461464
  • src/SymTab/Indexer.h

    r596f987b r66f8528  
    2525        class Indexer : public Visitor {
    2626          public:
    27                 Indexer( bool useDebug = false );
     27                explicit Indexer( bool useDebug = false );
    2828
    2929                Indexer( const Indexer &that );
  • src/SymTab/Validate.cc

    r596f987b r66f8528  
    6161#include <algorithm>
    6262#include "InitTweak/InitTweak.h"
     63#include "CodeGen/CodeGenerator.h"
    6364
    6465#define debugPrint( x ) if ( doDebug ) { std::cout << x; }
    6566
    6667namespace SymTab {
    67         class HoistStruct : public Visitor {
     68        class HoistStruct final : public Visitor {
    6869          public:
    6970                /// Flattens nested struct types
     
    8687        };
    8788
     89        /// Fix return types so that every function returns exactly one value
     90        class ReturnTypeFixer final : public Visitor {
     91          public:
     92
     93                typedef Visitor Parent;
     94                using Parent::visit;
     95
     96                static void fix( std::list< Declaration * > &translationUnit );
     97
     98                virtual void visit( FunctionDecl * functionDecl );
     99
     100                virtual void visit( FunctionType * ftype );
     101        };
     102
    88103        /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers.
    89         class EnumAndPointerDecayPass : public Visitor {
     104        class EnumAndPointerDecayPass final : public Visitor {
    90105                typedef Visitor Parent;
    91106                virtual void visit( EnumDecl *aggregateDecl );
     
    94109
    95110        /// Associates forward declarations of aggregates with their definitions
    96         class Pass2 final : public Indexer {
     111        class LinkReferenceToTypes final : public Indexer {
    97112                typedef Indexer Parent;
    98113          public:
    99                 Pass2( bool doDebug, const Indexer *indexer );
     114                LinkReferenceToTypes( bool doDebug, const Indexer *indexer );
    100115          private:
    101116                using Indexer::visit;
     
    193208        void validate( std::list< Declaration * > &translationUnit, bool doDebug ) {
    194209                EnumAndPointerDecayPass epc;
    195                 Pass2 pass2( doDebug, 0 );
     210                LinkReferenceToTypes lrt( doDebug, 0 );
    196211                Pass3 pass3( 0 );
    197212                CompoundLiteral compoundliteral;
     
    199214                EliminateTypedef::eliminateTypedef( translationUnit );
    200215                HoistStruct::hoistStruct( translationUnit );
     216                ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
    201217                autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecayPass
    202218                acceptAll( translationUnit, epc );
    203                 acceptAll( translationUnit, pass2 );
     219                acceptAll( translationUnit, lrt );
    204220                ReturnChecker::checkFunctionReturns( translationUnit );
    205221                compoundliteral.mutateDeclarationList( translationUnit );
     
    210226        void validateType( Type *type, const Indexer *indexer ) {
    211227                EnumAndPointerDecayPass epc;
    212                 Pass2 pass2( false, indexer );
     228                LinkReferenceToTypes lrt( false, indexer );
    213229                Pass3 pass3( indexer );
    214230                type->accept( epc );
    215                 type->accept( pass2 );
     231                type->accept( lrt );
    216232                type->accept( pass3 );
    217233        }
     
    324340        }
    325341
    326         Pass2::Pass2( bool doDebug, const Indexer *other_indexer ) : Indexer( doDebug ) {
     342        LinkReferenceToTypes::LinkReferenceToTypes( bool doDebug, const Indexer *other_indexer ) : Indexer( doDebug ) {
    327343                if ( other_indexer ) {
    328344                        indexer = other_indexer;
     
    332348        }
    333349
    334         void Pass2::visit( StructInstType *structInst ) {
     350        void LinkReferenceToTypes::visit( StructInstType *structInst ) {
    335351                Parent::visit( structInst );
    336352                StructDecl *st = indexer->lookupStruct( structInst->get_name() );
     
    346362        }
    347363
    348         void Pass2::visit( UnionInstType *unionInst ) {
     364        void LinkReferenceToTypes::visit( UnionInstType *unionInst ) {
    349365                Parent::visit( unionInst );
    350366                UnionDecl *un = indexer->lookupUnion( unionInst->get_name() );
     
    359375        }
    360376
    361         void Pass2::visit( TraitInstType *contextInst ) {
     377        void LinkReferenceToTypes::visit( TraitInstType *contextInst ) {
    362378                Parent::visit( contextInst );
     379                if ( contextInst->get_name() == "sized" ) {
     380                        // "sized" is a special trait with no members - just flick the sized status on for the type variable
     381                        if ( contextInst->get_parameters().size() != 1 ) {
     382                                throw SemanticError( "incorrect number of context parameters: ", contextInst );
     383                        }
     384                        TypeExpr * param = safe_dynamic_cast< TypeExpr * > ( contextInst->get_parameters().front() );
     385                        TypeInstType * inst = safe_dynamic_cast< TypeInstType * > ( param->get_type() );
     386                        TypeDecl * decl = inst->get_baseType();
     387                        decl->set_sized( true );
     388                        // since "sized" is special, the next few steps don't apply
     389                        return;
     390                }
    363391                TraitDecl *ctx = indexer->lookupTrait( contextInst->get_name() );
    364392                if ( ! ctx ) {
     
    386414        }
    387415
    388         void Pass2::visit( StructDecl *structDecl ) {
     416        void LinkReferenceToTypes::visit( StructDecl *structDecl ) {
    389417                // visit struct members first so that the types of self-referencing members are updated properly
    390418                Parent::visit( structDecl );
     
    400428        }
    401429
    402         void Pass2::visit( UnionDecl *unionDecl ) {
     430        void LinkReferenceToTypes::visit( UnionDecl *unionDecl ) {
    403431                Parent::visit( unionDecl );
    404432                if ( ! unionDecl->get_members().empty() ) {
     
    413441        }
    414442
    415         void Pass2::visit( TypeInstType *typeInst ) {
     443        void LinkReferenceToTypes::visit( TypeInstType *typeInst ) {
    416444                if ( NamedTypeDecl *namedTypeDecl = lookupType( typeInst->get_name() ) ) {
    417445                        if ( TypeDecl *typeDecl = dynamic_cast< TypeDecl * >( namedTypeDecl ) ) {
     
    584612
    585613                typedeclNames[ typeDecl->get_name() ] = typeDecl;
    586                 return typeDecl;
     614                return Mutator::mutate( typeDecl );
    587615        }
    588616
     
    735763                return new VariableExpr( newtempvar );
    736764        }
     765
     766        void ReturnTypeFixer::fix( std::list< Declaration * > &translationUnit ) {
     767                ReturnTypeFixer fixer;
     768                acceptAll( translationUnit, fixer );
     769        }
     770
     771        void ReturnTypeFixer::visit( FunctionDecl * functionDecl ) {
     772                Parent::visit( functionDecl );
     773                FunctionType * ftype = functionDecl->get_functionType();
     774                std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
     775                assertf( retVals.size() == 0 || retVals.size() == 1, "Function %s has too many return values: %d", functionDecl->get_name().c_str(), retVals.size() );
     776                if ( retVals.size() == 1 ) {
     777                        // ensure all function return values have a name - use the name of the function to disambiguate (this also provides a nice bit of help for debugging)
     778                        // ensure other return values have a name
     779                        DeclarationWithType * ret = retVals.front();
     780                        if ( ret->get_name() == "" ) {
     781                                ret->set_name( toString( "_retval_", CodeGen::genName( functionDecl ) ) );
     782                        }
     783                }
     784        }
     785
     786        void ReturnTypeFixer::visit( FunctionType * ftype ) {
     787                // xxx - need to handle named return values - this information needs to be saved somehow
     788                // so that resolution has access to the names.
     789                // Note that this pass needs to happen early so that other passes which look for tuple types
     790                // find them in all of the right places, including function return types.
     791                std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
     792                if ( retVals.size() > 1 ) {
     793                        // generate a single return parameter which is the tuple of all of the return values
     794                        TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
     795                        // ensure return value is not destructed by explicitly creating an empty ListInit node wherein maybeConstruct is false.
     796                        ObjectDecl * newRet = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) );
     797                        deleteAll( retVals );
     798                        retVals.clear();
     799                        retVals.push_back( newRet );
     800                }
     801        }
    737802} // namespace SymTab
    738803
  • src/SynTree/ApplicationExpr.cc

    r596f987b r66f8528  
    3030        if ( &other == this ) return *this;
    3131        decl = other.decl;
     32        // xxx - this looks like a memory leak
    3233        actualType = maybeClone( other.actualType );
    3334        formalType = maybeClone( other.formalType );
  • src/SynTree/CompoundStmt.cc

    r596f987b r66f8528  
    4949                Statement * origStmt = *origit++;
    5050                if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( s ) ) {
    51                         DeclStmt * origDeclStmt = dynamic_cast< DeclStmt * >( origStmt );
    52                         assert( origDeclStmt );
     51                        DeclStmt * origDeclStmt = safe_dynamic_cast< DeclStmt * >( origStmt );
    5352                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * > ( declStmt->get_decl() ) ) {
    54                                 DeclarationWithType * origdwt = dynamic_cast< DeclarationWithType * > ( origDeclStmt->get_decl() );
    55                                 assert( origdwt );
     53                                DeclarationWithType * origdwt = safe_dynamic_cast< DeclarationWithType * > ( origDeclStmt->get_decl() );
    5654                                assert( dwt->get_name() == origdwt->get_name() );
    5755                                declMap[ origdwt ] = dwt;
    58                         }
    59                 }
     56                        } else assert( ! dynamic_cast< DeclarationWithType * > ( origDeclStmt->get_decl() ) );
     57                } else assert( ! dynamic_cast< DeclStmt * > ( s ) );
    6058        }
    6159        if ( ! declMap.empty() ) {
  • src/SynTree/Declaration.h

    r596f987b r66f8528  
    180180  public:
    181181        enum Kind { Any, Dtype, Ftype };
     182        /// Data extracted from a type decl
     183        struct Data {
     184                TypeDecl::Kind kind;
     185                bool isComplete;
     186                Data() : kind( (TypeDecl::Kind)-1 ), isComplete( false ) {}
     187                Data( TypeDecl * typeDecl ) : Data( typeDecl->get_kind(), typeDecl->isComplete() ) {}
     188                Data( Kind kind, bool isComplete ) : kind( kind ), isComplete( isComplete ) {}
     189                bool operator==(const Data & other) const { return kind == other.kind && isComplete == other.isComplete; }
     190                bool operator!=(const Data & other) const { return !(*this == other);}
     191        };
    182192
    183193        TypeDecl( const std::string &name, DeclarationNode::StorageClass sc, Type *type, Kind kind );
     
    186196        Kind get_kind() const { return kind; }
    187197
     198        bool isComplete() const { return kind == Any || sized; }
     199        bool get_sized() const { return sized; }
     200        TypeDecl * set_sized( bool newValue ) { sized = newValue; return this; }
     201
    188202        virtual TypeDecl *clone() const { return new TypeDecl( *this ); }
    189203        virtual void accept( Visitor &v ) { v.visit( this ); }
     
    192206        virtual std::string typeString() const;
    193207        Kind kind;
     208        bool sized;
    194209};
    195210
     
    284299
    285300std::ostream & operator<<( std::ostream & out, const Declaration * decl );
     301std::ostream & operator<<( std::ostream & os, const TypeDecl::Data & data );
    286302
    287303#endif // DECLARATION_H
  • src/SynTree/Expression.cc

    r596f987b r66f8528  
    332332}
    333333
     334namespace {
     335        TypeSubstitution makeSub( Type * t ) {
     336                if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) {
     337                        return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->get_parameters().begin() );
     338                } else if ( UnionInstType * aggInst = dynamic_cast< UnionInstType * >( t ) ) {
     339                        return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->get_parameters().begin() );
     340                } else {
     341                        assertf( false, "makeSub expects struct or union type for aggregate" );
     342                }
     343        }
     344}
     345
    334346
    335347MemberExpr::MemberExpr( DeclarationWithType *_member, Expression *_aggregate, Expression *_aname ) :
    336348                Expression( _aname ), member(_member), aggregate(_aggregate) {
    337         set_result( member->get_type()->clone() );
     349
     350        TypeSubstitution sub( makeSub( aggregate->get_result() ) );
     351        Type * res = member->get_type()->clone();
     352        sub.apply( res );
     353        set_result( res );
    338354        get_result()->set_isLvalue( true );
    339355}
     
    511527
    512528ImplicitCopyCtorExpr::~ImplicitCopyCtorExpr() {
     529        set_env( nullptr ); // ImplicitCopyCtorExpr does not take ownership of an environment
    513530        delete callExpr;
    514531        deleteAll( tempDecls );
     
    520537        os <<  "Implicit Copy Constructor Expression: " << std::endl;
    521538        assert( callExpr );
     539        os << std::string( indent+2, ' ' );
    522540        callExpr->print( os, indent + 2 );
    523541        os << std::endl << std::string( indent, ' ' ) << "with temporaries:" << std::endl;
     
    571589        os << std::string( indent+2, ' ' );
    572590        initializer->print( os, indent + 2 );
     591        Expression::print( os, indent );
    573592}
    574593
     
    590609        os << " ... ";
    591610        high->print( os, indent );
     611        Expression::print( os, indent );
    592612}
    593613
     
    601621        }
    602622}
    603 StmtExpr::StmtExpr( const StmtExpr &other ) : Expression( other ), statements( other.statements->clone() ) {}
     623StmtExpr::StmtExpr( const StmtExpr &other ) : Expression( other ), statements( other.statements->clone() ) {
     624        cloneAll( other.returnDecls, returnDecls );
     625        cloneAll( other.dtors, dtors );
     626}
    604627StmtExpr::~StmtExpr() {
    605628        delete statements;
     629        deleteAll( dtors );
     630        deleteAll( returnDecls );
    606631}
    607632void StmtExpr::print( std::ostream &os, int indent ) const {
    608633        os << "Statement Expression: " << std::endl << std::string( indent, ' ' );
    609634        statements->print( os, indent+2 );
     635        if ( ! returnDecls.empty() ) {
     636                os << std::string( indent+2, ' ' ) << "with returnDecls: ";
     637                printAll( returnDecls, os, indent+2 );
     638        }
     639        if ( ! dtors.empty() ) {
     640                os << std::string( indent+2, ' ' ) << "with dtors: ";
     641                printAll( dtors, os, indent+2 );
     642        }
     643        Expression::print( os, indent );
    610644}
    611645
     
    631665        get_expr()->print( os, indent+2 );
    632666        if ( get_object() ) {
    633                 os << " with decl: ";
     667                os << std::string( indent+2, ' ' ) << "with decl: ";
    634668                get_object()->printShort( os, indent+2 );
    635669        }
     670        Expression::print( os, indent );
    636671}
    637672
  • src/SynTree/Expression.h

    r596f987b r66f8528  
    543543
    544544        std::list< ObjectDecl * > & get_tempDecls() { return tempDecls; }
    545         void set_tempDecls( std::list< ObjectDecl * > newValue ) { tempDecls = newValue; }
    546 
    547545        std::list< ObjectDecl * > & get_returnDecls() { return returnDecls; }
    548         void set_returnDecls( std::list< ObjectDecl * > newValue ) { returnDecls = newValue; }
    549 
    550546        std::list< Expression * > & get_dtors() { return dtors; }
    551         void set_dtors( std::list< Expression * > newValue ) { dtors = newValue; }
    552547
    553548        virtual ImplicitCopyCtorExpr *clone() const { return new ImplicitCopyCtorExpr( *this ); }
     
    706701        virtual ~TupleAssignExpr();
    707702
    708         std::list< Expression * > & get_assigns() { return assigns; }
    709         std::list< ObjectDecl * > & get_tempDecls() { return tempDecls; }
     703        TupleAssignExpr * set_stmtExpr( StmtExpr * newValue ) { stmtExpr = newValue; return this; }
     704        StmtExpr * get_stmtExpr() const { return stmtExpr; }
    710705
    711706        virtual TupleAssignExpr *clone() const { return new TupleAssignExpr( *this ); }
     
    714709        virtual void print( std::ostream &os, int indent = 0 ) const;
    715710  private:
    716         std::list< Expression * > assigns; // assignment expressions that use tempDecls
    717         std::list< ObjectDecl * > tempDecls; // temporaries for address of lhs exprs
     711        StmtExpr * stmtExpr = nullptr;
    718712};
    719713
     
    728722        StmtExpr * set_statements( CompoundStmt * newValue ) { statements = newValue; return this; }
    729723
     724        std::list< ObjectDecl * > & get_returnDecls() { return returnDecls; }
     725        std::list< Expression * > & get_dtors() { return dtors; }
     726
    730727        virtual StmtExpr *clone() const { return new StmtExpr( *this ); }
    731728        virtual void accept( Visitor &v ) { v.visit( this ); }
     
    734731private:
    735732        CompoundStmt * statements;
     733        std::list< ObjectDecl * > returnDecls; // return variable(s) for stmt expression
     734        std::list< Expression * > dtors; // destructor(s) for return variable(s)
    736735};
    737736
  • src/SynTree/Initializer.cc

    r596f987b r66f8528  
    6565}
    6666
     67ListInit::ListInit( const ListInit & other ) : Initializer( other ) {
     68        cloneAll( other.initializers, initializers );
     69        cloneAll( other.designators, designators );
     70}
     71
     72
    6773ListInit::~ListInit() {
    6874        deleteAll( initializers );
  • src/SynTree/Initializer.h

    r596f987b r66f8528  
    8888        ListInit( const std::list<Initializer*> &initializers,
    8989                          const std::list<Expression *> &designators = std::list< Expression * >(), bool maybeConstructed = false );
     90        ListInit( const ListInit & other );
    9091        virtual ~ListInit();
    9192
  • src/SynTree/Mutator.cc

    r596f987b r66f8528  
    325325        mutateAll( impCpCtorExpr->get_tempDecls(), *this );
    326326        mutateAll( impCpCtorExpr->get_returnDecls(), *this );
     327        mutateAll( impCpCtorExpr->get_dtors(), *this );
    327328        return impCpCtorExpr;
    328329}
     
    373374Expression *Mutator::mutate( TupleAssignExpr *assignExpr ) {
    374375        assignExpr->set_result( maybeMutate( assignExpr->get_result(), *this ) );
    375         mutateAll( assignExpr->get_tempDecls(), *this );
    376         mutateAll( assignExpr->get_assigns(), *this );
     376        assignExpr->set_stmtExpr( maybeMutate( assignExpr->get_stmtExpr(), *this ) );
    377377        return assignExpr;
    378378}
     
    381381        stmtExpr->set_result( maybeMutate( stmtExpr->get_result(), *this ) );
    382382        stmtExpr->set_statements( maybeMutate( stmtExpr->get_statements(), *this ) );
     383        mutateAll( stmtExpr->get_returnDecls(), *this );
     384        mutateAll( stmtExpr->get_dtors(), *this );
    383385        return stmtExpr;
    384386}
     
    503505Initializer *Mutator::mutate( ConstructorInit *ctorInit ) {
    504506        ctorInit->set_ctor( maybeMutate( ctorInit->get_ctor(), *this ) );
     507        ctorInit->set_dtor( maybeMutate( ctorInit->get_dtor(), *this ) );
    505508        ctorInit->set_init( maybeMutate( ctorInit->get_init(), *this ) );
    506509        return ctorInit;
  • src/SynTree/ReferenceToType.cc

    r596f987b r66f8528  
    4646
    4747namespace {
    48         void doLookup( const std::list< Declaration* > &members, const std::list< TypeDecl* > &parms, const std::list< Expression* > &args, const std::string &name, std::list< Declaration* > &foundDecls ) {
    49                 std::list< Declaration* > found;
     48        void doLookup( const std::list< Declaration* > &members, const std::string &name, std::list< Declaration* > &foundDecls ) {
    5049                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    5150                        if ( (*i)->get_name() == name ) {
    52                                 found.push_back( *i );
     51                                foundDecls.push_back( *i );
    5352                        } // if
    5453                } // for
    55                 applySubstitution( parms.begin(), parms.end(), args.begin(), found.begin(), found.end(), back_inserter( foundDecls ) );
    5654        }
    5755} // namespace
     
    6866void StructInstType::lookup( const std::string &name, std::list< Declaration* > &foundDecls ) const {
    6967        assert( baseStruct );
    70         doLookup( baseStruct->get_members(), baseStruct->get_parameters(), parameters, name, foundDecls );
     68        doLookup( baseStruct->get_members(), name, foundDecls );
    7169}
    7270
     
    9492void UnionInstType::lookup( const std::string &name, std::list< Declaration* > &foundDecls ) const {
    9593        assert( baseUnion );
    96         doLookup( baseUnion->get_members(), baseUnion->get_parameters(), parameters, name, foundDecls );
     94        doLookup( baseUnion->get_members(), name, foundDecls );
    9795}
    9896
     
    130128}
    131129
     130TypeInstType::TypeInstType( const TypeInstType &other ) : Parent( other ), baseType( other.baseType ), isFtype( other.isFtype ) {
     131}
     132
     133
    132134TypeInstType::~TypeInstType() {
    133135        // delete baseType; //This is shared and should not be deleted
  • src/SynTree/TupleExpr.cc

    r596f987b r66f8528  
    8787}
    8888
    89 
    90 TupleAssignExpr::TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls, Expression * _aname ) : Expression( _aname ), assigns( assigns ), tempDecls( tempDecls ) {
     89TupleAssignExpr::TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls, Expression * _aname ) : Expression( _aname ) {
     90        // convert internally into a StmtExpr which contains the declarations and produces the tuple of the assignments
    9191        set_result( Tuples::makeTupleType( assigns ) );
     92        CompoundStmt * compoundStmt = new CompoundStmt( noLabels );
     93        std::list< Statement * > & stmts = compoundStmt->get_kids();
     94        for ( ObjectDecl * obj : tempDecls ) {
     95                stmts.push_back( new DeclStmt( noLabels, obj ) );
     96        }
     97        TupleExpr * tupleExpr = new TupleExpr( assigns );
     98        assert( tupleExpr->get_result() );
     99        stmts.push_back( new ExprStmt( noLabels, tupleExpr ) );
     100        stmtExpr = new StmtExpr( compoundStmt );
    92101}
    93102
    94103TupleAssignExpr::TupleAssignExpr( const TupleAssignExpr &other ) : Expression( other ) {
    95         cloneAll( other.assigns, assigns );
    96         cloneAll( other.tempDecls, tempDecls );
    97 
    98         // clone needs to go into assigns and replace tempDecls
    99         VarExprReplacer::DeclMap declMap;
    100         std::list< ObjectDecl * >::const_iterator origit = other.tempDecls.begin();
    101         for ( ObjectDecl * temp : tempDecls ) {
    102                 assert( origit != other.tempDecls.end() );
    103                 ObjectDecl * origTemp = *origit++;
    104                 assert( origTemp );
    105                 assert( temp->get_name() == origTemp->get_name() );
    106                 declMap[ origTemp ] = temp;
    107         }
    108         if ( ! declMap.empty() ) {
    109                 VarExprReplacer replacer( declMap );
    110                 for ( Expression * assn : assigns ) {
    111                         assn->accept( replacer );
    112                 }
    113         }
     104        assert( other.stmtExpr );
     105        stmtExpr = other.stmtExpr->clone();
    114106}
    115107
    116108TupleAssignExpr::~TupleAssignExpr() {
    117         deleteAll( assigns );
    118         // deleteAll( tempDecls );
     109        delete stmtExpr;
    119110}
    120111
    121112void TupleAssignExpr::print( std::ostream &os, int indent ) const {
    122         os << "Tuple Assignment Expression, with temporaries:" << std::endl;
    123         printAll( tempDecls, os, indent+4 );
    124         os << std::string( indent+2, ' ' ) << "with assignments: " << std::endl;
    125         printAll( assigns, os, indent+4 );
     113        os << "Tuple Assignment Expression, with stmt expr:" << std::endl;
     114        os << std::string( indent+2, ' ' );
     115        stmtExpr->print( os, indent+4 );
    126116        Expression::print( os, indent );
    127117}
  • src/SynTree/Type.h

    r596f987b r66f8528  
    7272        virtual unsigned size() const { return 1; };
    7373        virtual bool isVoid() const { return size() == 0; }
     74        virtual Type * getComponent( unsigned i ) { assertf( size() == 1 && i == 0, "Type::getComponent was called with size %d and index %d\n", size(), i ); return this; }
    7475
    7576        virtual Type *clone() const = 0;
     
    339340        TypeInstType( const Type::Qualifiers &tq, const std::string &name, TypeDecl *baseType );
    340341        TypeInstType( const Type::Qualifiers &tq, const std::string &name, bool isFtype );
    341         TypeInstType( const TypeInstType &other ) : Parent( other ), baseType( other.baseType ), isFtype( other.isFtype ) {}
     342        TypeInstType( const TypeInstType &other );
    342343        ~TypeInstType();
    343344
     
    373374        iterator begin() { return types.begin(); }
    374375        iterator end() { return types.end(); }
     376
     377        virtual Type * getComponent( unsigned i ) {
     378                assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d", i, size() );
     379                return *(begin()+i);
     380        }
    375381
    376382        virtual TupleType *clone() const { return new TupleType( *this ); }
  • src/SynTree/TypeDecl.cc

    r596f987b r66f8528  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // TypeDecl.cc -- 
     7// TypeDecl.cc --
    88//
    99// Author           : Richard C. Bilson
     
    1818#include "Common/utility.h"
    1919
    20 TypeDecl::TypeDecl( const std::string &name, DeclarationNode::StorageClass sc, Type *type, Kind kind ) : Parent( name, sc, type ), kind( kind ) {
     20TypeDecl::TypeDecl( const std::string &name, DeclarationNode::StorageClass sc, Type *type, Kind kind ) : Parent( name, sc, type ), kind( kind ), sized( kind == Any ) {
    2121}
    2222
    23 TypeDecl::TypeDecl( const TypeDecl &other ) : Parent( other ), kind( other.kind ) {
     23TypeDecl::TypeDecl( const TypeDecl &other ) : Parent( other ), kind( other.kind ), sized( other.sized ) {
    2424}
    2525
     
    2929}
    3030
     31std::ostream & operator<<( std::ostream & os, const TypeDecl::Data & data ) {
     32  return os << data.kind << ", " << data.isComplete;
     33}
     34
    3135// Local Variables: //
    3236// tab-width: 4 //
  • src/SynTree/VarExprReplacer.cc

    r596f987b r66f8528  
    2121// replace variable with new node from decl map
    2222void VarExprReplacer::visit( VariableExpr * varExpr ) {
     23  // xxx - assertions and parameters aren't accounted for in this... (i.e. they aren't inserted into the map when it's made, only DeclStmts are)
    2324  if ( declMap.count( varExpr->get_var() ) ) {
    2425    varExpr->set_var( declMap.at( varExpr->get_var() ) );
  • src/SynTree/Visitor.cc

    r596f987b r66f8528  
    276276        acceptAll( impCpCtorExpr->get_tempDecls(), *this );
    277277        acceptAll( impCpCtorExpr->get_returnDecls(), *this );
     278        acceptAll( impCpCtorExpr->get_dtors(), *this );
    278279}
    279280
     
    317318void Visitor::visit( TupleAssignExpr *assignExpr ) {
    318319        maybeAccept( assignExpr->get_result(), *this );
    319         acceptAll( assignExpr->get_tempDecls(), *this );
    320         acceptAll( assignExpr->get_assigns(), *this );
     320        maybeAccept( assignExpr->get_stmtExpr(), *this );
    321321}
    322322
     
    324324        maybeAccept( stmtExpr->get_result(), *this );
    325325        maybeAccept( stmtExpr->get_statements(), *this );
     326        acceptAll( stmtExpr->get_returnDecls(), *this );
     327        acceptAll( stmtExpr->get_dtors(), *this );
    326328}
    327329
     
    425427void Visitor::visit( ConstructorInit *ctorInit ) {
    426428        maybeAccept( ctorInit->get_ctor(), *this );
     429        maybeAccept( ctorInit->get_dtor(), *this );
    427430        maybeAccept( ctorInit->get_init(), *this );
    428431}
  • src/Tuples/Explode.cc

    r596f987b r66f8528  
    2323                        Expression * applyAddr( Expression * expr, bool first = true ) {
    2424                                if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ){
     25                                        foundUniqueExpr = true;
    2526                                        std::list< Expression * > exprs;
    2627                                        for ( Expression *& expr : tupleExpr->get_exprs() ) {
     
    4647                                // should now be a tuple of addresses rather than the address of a tuple.
    4748                                // Still, this code is a bit awkward, and could use some improvement.
    48                                 foundUniqueExpr = true;
     49                                if ( dynamic_cast< AddressExpr * > ( uniqueExpr->get_expr() ) ) {
     50                                        // this unique expression has already been mutated or otherwise shouldn't be (can't take the address-of an address-of expression)
     51                                        return uniqueExpr;
     52                                }
    4953                                UniqueExpr * newUniqueExpr = new UniqueExpr( applyAddr( uniqueExpr->get_expr() ), uniqueExpr->get_id() );
    5054                                delete uniqueExpr;
  • src/Tuples/TupleAssignment.cc

    r596f987b r66f8528  
    2323#include "Common/SemanticError.h"
    2424#include "InitTweak/InitTweak.h"
     25#include "InitTweak/GenInit.h"
    2526
    2627#include <functional>
     
    4748                        virtual ~Matcher() {}
    4849                        virtual void match( std::list< Expression * > &out ) = 0;
     50                        ObjectDecl * newObject( UniqueName & namer, Expression * expr );
    4951                        ResolvExpr::AltList lhs, rhs;
    5052                        TupleAssignSpotter &spotter;
     53                        ResolvExpr::Cost baseCost;
    5154                        std::list< ObjectDecl * > tmpDecls;
     55                        ResolvExpr::TypeEnvironment compositeEnv;
    5256                };
    5357
     
    146150                                finder.findWithAdjustment(*i);
    147151                        } catch (...) {
    148                                 return; // xxx - no match should not mean failure, it just means this particular tuple assignment isn't valid
     152                                return; // no match should not mean failure, it just means this particular tuple assignment isn't valid
    149153                        }
    150154                        // prune expressions that don't coincide with
     
    161165                        solved_assigns.push_back( alt.expr->clone() );
    162166                }
    163                 // xxx - need to do this??
    164                 ResolvExpr::TypeEnvironment compositeEnv;
    165                 simpleCombineEnvironments( current.begin(), current.end(), compositeEnv );
    166                 currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), compositeEnv, ResolvExpr::sumCost( current ) ) );
    167         }
    168 
    169         TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList &alts ) : spotter(spotter) {
     167                // combine assignment environments into combined expression environment
     168                simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv );
     169                currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, ResolvExpr::sumCost( current  ) + matcher->baseCost ) );
     170        }
     171
     172        TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList &alts ) : spotter(spotter), baseCost( ResolvExpr::sumCost( alts ) ) {
    170173                assert( ! alts.empty() );
     174                // combine argument environments into combined expression environment
     175                simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
     176
    171177                ResolvExpr::Alternative lhsAlt = alts.front();
    172178                // peel off the cast that exists on ctor/dtor expressions
     
    217223        }
    218224
    219         ObjectDecl * newObject( UniqueName & namer, Expression * expr ) {
     225        // removes environments from subexpressions within statement exprs, which could throw off later passes like those in Box which rely on PolyMutator.
     226        // xxx - maybe this should happen in alternative finder for every StmtExpr?
     227        // xxx - it's possible that these environments could contain some useful information. Maybe the right thing to do is aggregate the environments and pass the aggregate back to be added into the compositeEnv
     228        struct EnvRemover : public Visitor {
     229                virtual void visit( ExprStmt * stmt ) {
     230                        delete stmt->get_expr()->get_env();
     231                        stmt->get_expr()->set_env( nullptr );
     232                        Visitor::visit( stmt );
     233                }
     234        };
     235
     236        ObjectDecl * TupleAssignSpotter::Matcher::newObject( UniqueName & namer, Expression * expr ) {
    220237                assert( expr->has_result() && ! expr->get_result()->isVoid() );
    221                 return new ObjectDecl( namer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) );
     238                ObjectDecl * ret = new ObjectDecl( namer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) );
     239                ConstructorInit * ctorInit = InitTweak::genCtorInit( ret );
     240                ret->set_init( ctorInit );
     241                ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object
     242                EnvRemover rm; // remove environments from subexpressions of StmtExprs
     243                ctorInit->accept( rm );
     244                return ret;
    222245        }
    223246
     
    244267                        std::list< ObjectDecl * > ltmp;
    245268                        std::list< ObjectDecl * > rtmp;
    246                         std::transform( lhs.begin(), lhs.end(), back_inserter( ltmp ), []( ResolvExpr::Alternative & alt ){
     269                        std::transform( lhs.begin(), lhs.end(), back_inserter( ltmp ), [&]( ResolvExpr::Alternative & alt ){
    247270                                return newObject( lhsNamer, alt.expr );
    248271                        });
    249                         std::transform( rhs.begin(), rhs.end(), back_inserter( rtmp ), []( ResolvExpr::Alternative & alt ){
     272                        std::transform( rhs.begin(), rhs.end(), back_inserter( rtmp ), [&]( ResolvExpr::Alternative & alt ){
    250273                                return newObject( rhsNamer, alt.expr );
    251274                        });
  • src/Tuples/TupleExpansion.cc

    r596f987b r66f8528  
    9393                        typedef Mutator Parent;
    9494                        using Parent::mutate;
    95                        
     95
    9696                        virtual Expression * mutate( TupleExpr * tupleExpr ) override;
    9797                };
     
    194194                                new CommaExpr( new CommaExpr( assignUnq, assignFinished ), var->clone() ) );
    195195                        condExpr->set_result( var->get_result()->clone() );
     196                        condExpr->set_env( maybeClone( unqExpr->get_env() ) );
    196197                        decls[id] = condExpr;
    197198                }
     
    202203        Expression * TupleAssignExpander::mutate( TupleAssignExpr * assnExpr ) {
    203204                assnExpr = safe_dynamic_cast< TupleAssignExpr * >( Parent::mutate( assnExpr ) );
    204                 CompoundStmt * compoundStmt = new CompoundStmt( noLabels );
    205                 std::list< Statement * > & stmts = compoundStmt->get_kids();
    206                 for ( ObjectDecl * obj : assnExpr->get_tempDecls() ) {
    207                         stmts.push_back( new DeclStmt( noLabels, obj ) );
    208                 }
    209                 TupleExpr * tupleExpr = new TupleExpr( assnExpr->get_assigns() );
    210                 assert( tupleExpr->get_result() );
    211                 stmts.push_back( new ExprStmt( noLabels, tupleExpr ) );
    212                 assnExpr->get_tempDecls().clear();
    213                 assnExpr->get_assigns().clear();
     205                StmtExpr * ret = assnExpr->get_stmtExpr();
     206                assnExpr->set_stmtExpr( nullptr );
     207                // move env to StmtExpr
     208                ret->set_env( assnExpr->get_env() );
     209                assnExpr->set_env( nullptr );
    214210                delete assnExpr;
    215                 return new StmtExpr( compoundStmt );
     211                return ret;
    216212        }
    217213
    218214        Type * TupleTypeReplacer::mutate( TupleType * tupleType ) {
    219215                std::string mangleName = SymTab::Mangler::mangleType( tupleType );
    220                 TupleType * newType = safe_dynamic_cast< TupleType * > ( Parent::mutate( tupleType ) );
     216                tupleType = safe_dynamic_cast< TupleType * > ( Parent::mutate( tupleType ) );
    221217                if ( ! typeMap.count( mangleName ) ) {
    222218                        // generate struct type to replace tuple type
     219                        // xxx - should fix this to only generate one tuple struct for each number of type parameters
    223220                        StructDecl * decl = new StructDecl( "_tuple_type_" + mangleName );
    224221                        decl->set_body( true );
    225                         int cnt = 0;
    226                         for ( Type * t : *newType ) {
    227                                 decl->get_members().push_back( new ObjectDecl( toString("field_", cnt++), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, t->clone(), nullptr ) );
     222                        for ( size_t i = 0; i < tupleType->size(); ++i ) {
     223                                TypeDecl * tyParam = new TypeDecl( toString("tuple_param_", i), DeclarationNode::NoStorageClass, nullptr, TypeDecl::Any );
     224                                decl->get_members().push_back( new ObjectDecl( toString("field_", i), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, new TypeInstType( Type::Qualifiers(), tyParam->get_name(), tyParam ), nullptr ) );
     225                                decl->get_parameters().push_back( tyParam );
    228226                        }
    229227                        typeMap[mangleName] = decl;
    230228                        addDeclaration( decl );
    231229                }
    232                 Type::Qualifiers qualifiers = newType->get_qualifiers();
    233                 delete newType;
    234                 return new StructInstType( qualifiers, typeMap[mangleName] );
     230                Type::Qualifiers qualifiers = tupleType->get_qualifiers();
     231
     232                StructDecl * decl = typeMap[mangleName];
     233                StructInstType * newType = new StructInstType( qualifiers, decl );
     234                for ( Type * t : *tupleType ) {
     235                        newType->get_parameters().push_back( new TypeExpr( t->clone() ) );
     236                }
     237                delete tupleType;
     238                return newType;
    235239        }
    236240
     
    240244                tupleExpr->set_tuple( nullptr );
    241245                unsigned int idx = tupleExpr->get_index();
     246                TypeSubstitution * env = tupleExpr->get_env();
     247                tupleExpr->set_env( nullptr );
    242248                delete tupleExpr;
    243249
     
    246252                assert( structDecl->get_members().size() > idx );
    247253                Declaration * member = *std::next(structDecl->get_members().begin(), idx);
    248                 return new MemberExpr( safe_dynamic_cast< DeclarationWithType * >( member ), tuple );
    249         }
    250 
    251         Expression * replaceTupleExpr( Type * result, const std::list< Expression * > & exprs ) {
     254                MemberExpr * memExpr = new MemberExpr( safe_dynamic_cast< DeclarationWithType * >( member ), tuple );
     255                memExpr->set_env( env );
     256                return memExpr;
     257        }
     258
     259        Expression * replaceTupleExpr( Type * result, const std::list< Expression * > & exprs, TypeSubstitution * env ) {
    252260                if ( result->isVoid() ) {
    253261                        // void result - don't need to produce a value for cascading - just output a chain of comma exprs
    254262                        assert( ! exprs.empty() );
    255263                        std::list< Expression * >::const_iterator iter = exprs.begin();
    256                         Expression * expr = *iter++;
     264                        Expression * expr = new CastExpr( *iter++ );
    257265                        for ( ; iter != exprs.end(); ++iter ) {
    258                                 expr = new CommaExpr( expr, *iter );
    259                         }
     266                                expr = new CommaExpr( expr, new CastExpr( *iter ) );
     267                        }
     268                        expr->set_env( env );
    260269                        return expr;
    261270                } else {
     
    267276                                inits.push_back( new SingleInit( expr ) );
    268277                        }
    269                         return new CompoundLiteralExpr( result, new ListInit( inits ) );
     278                        Expression * expr = new CompoundLiteralExpr( result, new ListInit( inits ) );
     279                        expr->set_env( env );
     280                        return expr;
    270281                }
    271282        }
     
    277288                std::list< Expression * > exprs = tupleExpr->get_exprs();
    278289                assert( result );
     290                TypeSubstitution * env = tupleExpr->get_env();
    279291
    280292                // remove data from shell and delete it
    281293                tupleExpr->set_result( nullptr );
    282294                tupleExpr->get_exprs().clear();
     295                tupleExpr->set_env( nullptr );
    283296                delete tupleExpr;
    284297
    285                 return replaceTupleExpr( result, exprs );
     298                return replaceTupleExpr( result, exprs, env );
    286299        }
    287300
  • src/main.cc

    r596f987b r66f8528  
    266266                OPTPRINT( "expandUniqueExpr" ); // xxx - is this the right place for this? want to expand ASAP so that subsequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
    267267                Tuples::expandUniqueExpr( translationUnit );
     268                OPTPRINT( "expandTuples" ); // xxx - is this the right place for this?
     269                Tuples::expandTuples( translationUnit );
    268270
    269271                OPTPRINT("instantiateGenerics")
     
    282284                OPTPRINT( "box" )
    283285                GenPoly::box( translationUnit );
    284                 OPTPRINT( "expandTuples" ); // xxx - is this the right place for this?
    285                 Tuples::expandTuples( translationUnit );
    286286
    287287                // print tree right before code generation
  • src/prelude/prelude.cf

    r596f987b r66f8528  
    105105forall( otype T ) const volatile T *     --?( const volatile T ** );
    106106
    107 forall( otype T ) lvalue T               *?(                 T * );
    108 forall( otype T ) const lvalue T                 *?( const           T * );
    109 forall( otype T ) volatile lvalue T      *?(       volatile  T * );
    110 forall( otype T ) const volatile lvalue T *?( const volatile  T * );
     107forall( dtype T | sized(T) ) lvalue T            *?(                 T * );
     108forall( dtype T | sized(T) ) const lvalue T              *?( const           T * );
     109forall( dtype T | sized(T) ) volatile lvalue T   *?(       volatile  T * );
     110forall( dtype T | sized(T) ) const volatile lvalue T *?( const volatile  T * );
    111111forall( ftype FT ) lvalue FT             *?( FT * );
    112112
  • src/tests/.expect/32/declarationSpecifier.txt

    r596f987b r66f8528  
    2020static inline void ___constructor__F_P13s__anonymous013s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1, struct __anonymous0 ___src__13s__anonymous0_1);
    2121static inline void ___destructor__F_P13s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1);
     22static inline void ___constructor__F_P13s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1){
     23    ((void)((*((int *)(&(*___dst__P13s__anonymous0_1).__i__i_1)))) /* ?{} */);
     24}
     25static inline void ___constructor__F_P13s__anonymous013s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1, struct __anonymous0 ___src__13s__anonymous0_1){
     26    ((void)((*((int *)(&(*___dst__P13s__anonymous0_1).__i__i_1)))=___src__13s__anonymous0_1.__i__i_1) /* ?{} */);
     27}
     28static inline void ___destructor__F_P13s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1){
     29    ((void)((*((int *)(&(*___dst__P13s__anonymous0_1).__i__i_1)))) /* ^?{} */);
     30}
    2231static inline struct __anonymous0 ___operator_assign__F13s__anonymous0_P13s__anonymous013s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1, struct __anonymous0 ___src__13s__anonymous0_1){
    2332    ((void)((*___dst__P13s__anonymous0_1).__i__i_1=___src__13s__anonymous0_1.__i__i_1));
    2433    return ((struct __anonymous0 )___src__13s__anonymous0_1);
    25 }
    26 static inline void ___constructor__F_P13s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1){
    27     ((void)((*((int *)(&(*___dst__P13s__anonymous0_1).__i__i_1)))) /* ?{} */);
    28 }
    29 static inline void ___constructor__F_P13s__anonymous013s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1, struct __anonymous0 ___src__13s__anonymous0_1){
    30     ((void)((*((int *)(&(*___dst__P13s__anonymous0_1).__i__i_1)))=___src__13s__anonymous0_1.__i__i_1) /* ?{} */);
    31 }
    32 static inline void ___destructor__F_P13s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1){
    33     ((void)((*((int *)(&(*___dst__P13s__anonymous0_1).__i__i_1)))) /* ^?{} */);
    3434}
    3535static inline void ___constructor__F_P13s__anonymous0i_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1, int __i__i_1){
     
    4444static inline void ___constructor__F_P13s__anonymous113s__anonymous1_autogen___1(struct __anonymous1 *___dst__P13s__anonymous1_1, struct __anonymous1 ___src__13s__anonymous1_1);
    4545static inline void ___destructor__F_P13s__anonymous1_autogen___1(struct __anonymous1 *___dst__P13s__anonymous1_1);
     46static inline void ___constructor__F_P13s__anonymous1_autogen___1(struct __anonymous1 *___dst__P13s__anonymous1_1){
     47    ((void)((*((int *)(&(*___dst__P13s__anonymous1_1).__i__i_1)))) /* ?{} */);
     48}
     49static inline void ___constructor__F_P13s__anonymous113s__anonymous1_autogen___1(struct __anonymous1 *___dst__P13s__anonymous1_1, struct __anonymous1 ___src__13s__anonymous1_1){
     50    ((void)((*((int *)(&(*___dst__P13s__anonymous1_1).__i__i_1)))=___src__13s__anonymous1_1.__i__i_1) /* ?{} */);
     51}
     52static inline void ___destructor__F_P13s__anonymous1_autogen___1(struct __anonymous1 *___dst__P13s__anonymous1_1){
     53    ((void)((*((int *)(&(*___dst__P13s__anonymous1_1).__i__i_1)))) /* ^?{} */);
     54}
    4655static inline struct __anonymous1 ___operator_assign__F13s__anonymous1_P13s__anonymous113s__anonymous1_autogen___1(struct __anonymous1 *___dst__P13s__anonymous1_1, struct __anonymous1 ___src__13s__anonymous1_1){
    4756    ((void)((*___dst__P13s__anonymous1_1).__i__i_1=___src__13s__anonymous1_1.__i__i_1));
    4857    return ((struct __anonymous1 )___src__13s__anonymous1_1);
    49 }
    50 static inline void ___constructor__F_P13s__anonymous1_autogen___1(struct __anonymous1 *___dst__P13s__anonymous1_1){
    51     ((void)((*((int *)(&(*___dst__P13s__anonymous1_1).__i__i_1)))) /* ?{} */);
    52 }
    53 static inline void ___constructor__F_P13s__anonymous113s__anonymous1_autogen___1(struct __anonymous1 *___dst__P13s__anonymous1_1, struct __anonymous1 ___src__13s__anonymous1_1){
    54     ((void)((*((int *)(&(*___dst__P13s__anonymous1_1).__i__i_1)))=___src__13s__anonymous1_1.__i__i_1) /* ?{} */);
    55 }
    56 static inline void ___destructor__F_P13s__anonymous1_autogen___1(struct __anonymous1 *___dst__P13s__anonymous1_1){
    57     ((void)((*((int *)(&(*___dst__P13s__anonymous1_1).__i__i_1)))) /* ^?{} */);
    5858}
    5959static inline void ___constructor__F_P13s__anonymous1i_autogen___1(struct __anonymous1 *___dst__P13s__anonymous1_1, int __i__i_1){
     
    6868static inline void ___constructor__F_P13s__anonymous213s__anonymous2_autogen___1(struct __anonymous2 *___dst__P13s__anonymous2_1, struct __anonymous2 ___src__13s__anonymous2_1);
    6969static inline void ___destructor__F_P13s__anonymous2_autogen___1(struct __anonymous2 *___dst__P13s__anonymous2_1);
     70static inline void ___constructor__F_P13s__anonymous2_autogen___1(struct __anonymous2 *___dst__P13s__anonymous2_1){
     71    ((void)((*((int *)(&(*___dst__P13s__anonymous2_1).__i__i_1)))) /* ?{} */);
     72}
     73static inline void ___constructor__F_P13s__anonymous213s__anonymous2_autogen___1(struct __anonymous2 *___dst__P13s__anonymous2_1, struct __anonymous2 ___src__13s__anonymous2_1){
     74    ((void)((*((int *)(&(*___dst__P13s__anonymous2_1).__i__i_1)))=___src__13s__anonymous2_1.__i__i_1) /* ?{} */);
     75}
     76static inline void ___destructor__F_P13s__anonymous2_autogen___1(struct __anonymous2 *___dst__P13s__anonymous2_1){
     77    ((void)((*((int *)(&(*___dst__P13s__anonymous2_1).__i__i_1)))) /* ^?{} */);
     78}
    7079static inline struct __anonymous2 ___operator_assign__F13s__anonymous2_P13s__anonymous213s__anonymous2_autogen___1(struct __anonymous2 *___dst__P13s__anonymous2_1, struct __anonymous2 ___src__13s__anonymous2_1){
    7180    ((void)((*___dst__P13s__anonymous2_1).__i__i_1=___src__13s__anonymous2_1.__i__i_1));
    7281    return ((struct __anonymous2 )___src__13s__anonymous2_1);
    73 }
    74 static inline void ___constructor__F_P13s__anonymous2_autogen___1(struct __anonymous2 *___dst__P13s__anonymous2_1){
    75     ((void)((*((int *)(&(*___dst__P13s__anonymous2_1).__i__i_1)))) /* ?{} */);
    76 }
    77 static inline void ___constructor__F_P13s__anonymous213s__anonymous2_autogen___1(struct __anonymous2 *___dst__P13s__anonymous2_1, struct __anonymous2 ___src__13s__anonymous2_1){
    78     ((void)((*((int *)(&(*___dst__P13s__anonymous2_1).__i__i_1)))=___src__13s__anonymous2_1.__i__i_1) /* ?{} */);
    79 }
    80 static inline void ___destructor__F_P13s__anonymous2_autogen___1(struct __anonymous2 *___dst__P13s__anonymous2_1){
    81     ((void)((*((int *)(&(*___dst__P13s__anonymous2_1).__i__i_1)))) /* ^?{} */);
    8282}
    8383static inline void ___constructor__F_P13s__anonymous2i_autogen___1(struct __anonymous2 *___dst__P13s__anonymous2_1, int __i__i_1){
     
    9292static inline void ___constructor__F_P13s__anonymous313s__anonymous3_autogen___1(struct __anonymous3 *___dst__P13s__anonymous3_1, struct __anonymous3 ___src__13s__anonymous3_1);
    9393static inline void ___destructor__F_P13s__anonymous3_autogen___1(struct __anonymous3 *___dst__P13s__anonymous3_1);
     94static inline void ___constructor__F_P13s__anonymous3_autogen___1(struct __anonymous3 *___dst__P13s__anonymous3_1){
     95    ((void)((*((int *)(&(*___dst__P13s__anonymous3_1).__i__i_1)))) /* ?{} */);
     96}
     97static inline void ___constructor__F_P13s__anonymous313s__anonymous3_autogen___1(struct __anonymous3 *___dst__P13s__anonymous3_1, struct __anonymous3 ___src__13s__anonymous3_1){
     98    ((void)((*((int *)(&(*___dst__P13s__anonymous3_1).__i__i_1)))=___src__13s__anonymous3_1.__i__i_1) /* ?{} */);
     99}
     100static inline void ___destructor__F_P13s__anonymous3_autogen___1(struct __anonymous3 *___dst__P13s__anonymous3_1){
     101    ((void)((*((int *)(&(*___dst__P13s__anonymous3_1).__i__i_1)))) /* ^?{} */);
     102}
    94103static inline struct __anonymous3 ___operator_assign__F13s__anonymous3_P13s__anonymous313s__anonymous3_autogen___1(struct __anonymous3 *___dst__P13s__anonymous3_1, struct __anonymous3 ___src__13s__anonymous3_1){
    95104    ((void)((*___dst__P13s__anonymous3_1).__i__i_1=___src__13s__anonymous3_1.__i__i_1));
    96105    return ((struct __anonymous3 )___src__13s__anonymous3_1);
    97 }
    98 static inline void ___constructor__F_P13s__anonymous3_autogen___1(struct __anonymous3 *___dst__P13s__anonymous3_1){
    99     ((void)((*((int *)(&(*___dst__P13s__anonymous3_1).__i__i_1)))) /* ?{} */);
    100 }
    101 static inline void ___constructor__F_P13s__anonymous313s__anonymous3_autogen___1(struct __anonymous3 *___dst__P13s__anonymous3_1, struct __anonymous3 ___src__13s__anonymous3_1){
    102     ((void)((*((int *)(&(*___dst__P13s__anonymous3_1).__i__i_1)))=___src__13s__anonymous3_1.__i__i_1) /* ?{} */);
    103 }
    104 static inline void ___destructor__F_P13s__anonymous3_autogen___1(struct __anonymous3 *___dst__P13s__anonymous3_1){
    105     ((void)((*((int *)(&(*___dst__P13s__anonymous3_1).__i__i_1)))) /* ^?{} */);
    106106}
    107107static inline void ___constructor__F_P13s__anonymous3i_autogen___1(struct __anonymous3 *___dst__P13s__anonymous3_1, int __i__i_1){
     
    116116static inline void ___constructor__F_P13s__anonymous413s__anonymous4_autogen___1(struct __anonymous4 *___dst__P13s__anonymous4_1, struct __anonymous4 ___src__13s__anonymous4_1);
    117117static inline void ___destructor__F_P13s__anonymous4_autogen___1(struct __anonymous4 *___dst__P13s__anonymous4_1);
     118static inline void ___constructor__F_P13s__anonymous4_autogen___1(struct __anonymous4 *___dst__P13s__anonymous4_1){
     119    ((void)((*((int *)(&(*___dst__P13s__anonymous4_1).__i__i_1)))) /* ?{} */);
     120}
     121static inline void ___constructor__F_P13s__anonymous413s__anonymous4_autogen___1(struct __anonymous4 *___dst__P13s__anonymous4_1, struct __anonymous4 ___src__13s__anonymous4_1){
     122    ((void)((*((int *)(&(*___dst__P13s__anonymous4_1).__i__i_1)))=___src__13s__anonymous4_1.__i__i_1) /* ?{} */);
     123}
     124static inline void ___destructor__F_P13s__anonymous4_autogen___1(struct __anonymous4 *___dst__P13s__anonymous4_1){
     125    ((void)((*((int *)(&(*___dst__P13s__anonymous4_1).__i__i_1)))) /* ^?{} */);
     126}
    118127static inline struct __anonymous4 ___operator_assign__F13s__anonymous4_P13s__anonymous413s__anonymous4_autogen___1(struct __anonymous4 *___dst__P13s__anonymous4_1, struct __anonymous4 ___src__13s__anonymous4_1){
    119128    ((void)((*___dst__P13s__anonymous4_1).__i__i_1=___src__13s__anonymous4_1.__i__i_1));
    120129    return ((struct __anonymous4 )___src__13s__anonymous4_1);
    121 }
    122 static inline void ___constructor__F_P13s__anonymous4_autogen___1(struct __anonymous4 *___dst__P13s__anonymous4_1){
    123     ((void)((*((int *)(&(*___dst__P13s__anonymous4_1).__i__i_1)))) /* ?{} */);
    124 }
    125 static inline void ___constructor__F_P13s__anonymous413s__anonymous4_autogen___1(struct __anonymous4 *___dst__P13s__anonymous4_1, struct __anonymous4 ___src__13s__anonymous4_1){
    126     ((void)((*((int *)(&(*___dst__P13s__anonymous4_1).__i__i_1)))=___src__13s__anonymous4_1.__i__i_1) /* ?{} */);
    127 }
    128 static inline void ___destructor__F_P13s__anonymous4_autogen___1(struct __anonymous4 *___dst__P13s__anonymous4_1){
    129     ((void)((*((int *)(&(*___dst__P13s__anonymous4_1).__i__i_1)))) /* ^?{} */);
    130130}
    131131static inline void ___constructor__F_P13s__anonymous4i_autogen___1(struct __anonymous4 *___dst__P13s__anonymous4_1, int __i__i_1){
     
    140140static inline void ___constructor__F_P13s__anonymous513s__anonymous5_autogen___1(struct __anonymous5 *___dst__P13s__anonymous5_1, struct __anonymous5 ___src__13s__anonymous5_1);
    141141static inline void ___destructor__F_P13s__anonymous5_autogen___1(struct __anonymous5 *___dst__P13s__anonymous5_1);
     142static inline void ___constructor__F_P13s__anonymous5_autogen___1(struct __anonymous5 *___dst__P13s__anonymous5_1){
     143    ((void)((*((int *)(&(*___dst__P13s__anonymous5_1).__i__i_1)))) /* ?{} */);
     144}
     145static inline void ___constructor__F_P13s__anonymous513s__anonymous5_autogen___1(struct __anonymous5 *___dst__P13s__anonymous5_1, struct __anonymous5 ___src__13s__anonymous5_1){
     146    ((void)((*((int *)(&(*___dst__P13s__anonymous5_1).__i__i_1)))=___src__13s__anonymous5_1.__i__i_1) /* ?{} */);
     147}
     148static inline void ___destructor__F_P13s__anonymous5_autogen___1(struct __anonymous5 *___dst__P13s__anonymous5_1){
     149    ((void)((*((int *)(&(*___dst__P13s__anonymous5_1).__i__i_1)))) /* ^?{} */);
     150}
    142151static inline struct __anonymous5 ___operator_assign__F13s__anonymous5_P13s__anonymous513s__anonymous5_autogen___1(struct __anonymous5 *___dst__P13s__anonymous5_1, struct __anonymous5 ___src__13s__anonymous5_1){
    143152    ((void)((*___dst__P13s__anonymous5_1).__i__i_1=___src__13s__anonymous5_1.__i__i_1));
    144153    return ((struct __anonymous5 )___src__13s__anonymous5_1);
    145 }
    146 static inline void ___constructor__F_P13s__anonymous5_autogen___1(struct __anonymous5 *___dst__P13s__anonymous5_1){
    147     ((void)((*((int *)(&(*___dst__P13s__anonymous5_1).__i__i_1)))) /* ?{} */);
    148 }
    149 static inline void ___constructor__F_P13s__anonymous513s__anonymous5_autogen___1(struct __anonymous5 *___dst__P13s__anonymous5_1, struct __anonymous5 ___src__13s__anonymous5_1){
    150     ((void)((*((int *)(&(*___dst__P13s__anonymous5_1).__i__i_1)))=___src__13s__anonymous5_1.__i__i_1) /* ?{} */);
    151 }
    152 static inline void ___destructor__F_P13s__anonymous5_autogen___1(struct __anonymous5 *___dst__P13s__anonymous5_1){
    153     ((void)((*((int *)(&(*___dst__P13s__anonymous5_1).__i__i_1)))) /* ^?{} */);
    154154}
    155155static inline void ___constructor__F_P13s__anonymous5i_autogen___1(struct __anonymous5 *___dst__P13s__anonymous5_1, int __i__i_1){
     
    164164static inline void ___constructor__F_P13s__anonymous613s__anonymous6_autogen___1(struct __anonymous6 *___dst__P13s__anonymous6_1, struct __anonymous6 ___src__13s__anonymous6_1);
    165165static inline void ___destructor__F_P13s__anonymous6_autogen___1(struct __anonymous6 *___dst__P13s__anonymous6_1);
     166static inline void ___constructor__F_P13s__anonymous6_autogen___1(struct __anonymous6 *___dst__P13s__anonymous6_1){
     167    ((void)((*((int *)(&(*___dst__P13s__anonymous6_1).__i__i_1)))) /* ?{} */);
     168}
     169static inline void ___constructor__F_P13s__anonymous613s__anonymous6_autogen___1(struct __anonymous6 *___dst__P13s__anonymous6_1, struct __anonymous6 ___src__13s__anonymous6_1){
     170    ((void)((*((int *)(&(*___dst__P13s__anonymous6_1).__i__i_1)))=___src__13s__anonymous6_1.__i__i_1) /* ?{} */);
     171}
     172static inline void ___destructor__F_P13s__anonymous6_autogen___1(struct __anonymous6 *___dst__P13s__anonymous6_1){
     173    ((void)((*((int *)(&(*___dst__P13s__anonymous6_1).__i__i_1)))) /* ^?{} */);
     174}
    166175static inline struct __anonymous6 ___operator_assign__F13s__anonymous6_P13s__anonymous613s__anonymous6_autogen___1(struct __anonymous6 *___dst__P13s__anonymous6_1, struct __anonymous6 ___src__13s__anonymous6_1){
    167176    ((void)((*___dst__P13s__anonymous6_1).__i__i_1=___src__13s__anonymous6_1.__i__i_1));
    168177    return ((struct __anonymous6 )___src__13s__anonymous6_1);
    169 }
    170 static inline void ___constructor__F_P13s__anonymous6_autogen___1(struct __anonymous6 *___dst__P13s__anonymous6_1){
    171     ((void)((*((int *)(&(*___dst__P13s__anonymous6_1).__i__i_1)))) /* ?{} */);
    172 }
    173 static inline void ___constructor__F_P13s__anonymous613s__anonymous6_autogen___1(struct __anonymous6 *___dst__P13s__anonymous6_1, struct __anonymous6 ___src__13s__anonymous6_1){
    174     ((void)((*((int *)(&(*___dst__P13s__anonymous6_1).__i__i_1)))=___src__13s__anonymous6_1.__i__i_1) /* ?{} */);
    175 }
    176 static inline void ___destructor__F_P13s__anonymous6_autogen___1(struct __anonymous6 *___dst__P13s__anonymous6_1){
    177     ((void)((*((int *)(&(*___dst__P13s__anonymous6_1).__i__i_1)))) /* ^?{} */);
    178178}
    179179static inline void ___constructor__F_P13s__anonymous6i_autogen___1(struct __anonymous6 *___dst__P13s__anonymous6_1, int __i__i_1){
     
    188188static inline void ___constructor__F_P13s__anonymous713s__anonymous7_autogen___1(struct __anonymous7 *___dst__P13s__anonymous7_1, struct __anonymous7 ___src__13s__anonymous7_1);
    189189static inline void ___destructor__F_P13s__anonymous7_autogen___1(struct __anonymous7 *___dst__P13s__anonymous7_1);
     190static inline void ___constructor__F_P13s__anonymous7_autogen___1(struct __anonymous7 *___dst__P13s__anonymous7_1){
     191    ((void)((*((int *)(&(*___dst__P13s__anonymous7_1).__i__i_1)))) /* ?{} */);
     192}
     193static inline void ___constructor__F_P13s__anonymous713s__anonymous7_autogen___1(struct __anonymous7 *___dst__P13s__anonymous7_1, struct __anonymous7 ___src__13s__anonymous7_1){
     194    ((void)((*((int *)(&(*___dst__P13s__anonymous7_1).__i__i_1)))=___src__13s__anonymous7_1.__i__i_1) /* ?{} */);
     195}
     196static inline void ___destructor__F_P13s__anonymous7_autogen___1(struct __anonymous7 *___dst__P13s__anonymous7_1){
     197    ((void)((*((int *)(&(*___dst__P13s__anonymous7_1).__i__i_1)))) /* ^?{} */);
     198}
    190199static inline struct __anonymous7 ___operator_assign__F13s__anonymous7_P13s__anonymous713s__anonymous7_autogen___1(struct __anonymous7 *___dst__P13s__anonymous7_1, struct __anonymous7 ___src__13s__anonymous7_1){
    191200    ((void)((*___dst__P13s__anonymous7_1).__i__i_1=___src__13s__anonymous7_1.__i__i_1));
    192201    return ((struct __anonymous7 )___src__13s__anonymous7_1);
    193 }
    194 static inline void ___constructor__F_P13s__anonymous7_autogen___1(struct __anonymous7 *___dst__P13s__anonymous7_1){
    195     ((void)((*((int *)(&(*___dst__P13s__anonymous7_1).__i__i_1)))) /* ?{} */);
    196 }
    197 static inline void ___constructor__F_P13s__anonymous713s__anonymous7_autogen___1(struct __anonymous7 *___dst__P13s__anonymous7_1, struct __anonymous7 ___src__13s__anonymous7_1){
    198     ((void)((*((int *)(&(*___dst__P13s__anonymous7_1).__i__i_1)))=___src__13s__anonymous7_1.__i__i_1) /* ?{} */);
    199 }
    200 static inline void ___destructor__F_P13s__anonymous7_autogen___1(struct __anonymous7 *___dst__P13s__anonymous7_1){
    201     ((void)((*((int *)(&(*___dst__P13s__anonymous7_1).__i__i_1)))) /* ^?{} */);
    202202}
    203203static inline void ___constructor__F_P13s__anonymous7i_autogen___1(struct __anonymous7 *___dst__P13s__anonymous7_1, int __i__i_1){
     
    220220static inline void ___constructor__F_P13s__anonymous813s__anonymous8_autogen___1(struct __anonymous8 *___dst__P13s__anonymous8_1, struct __anonymous8 ___src__13s__anonymous8_1);
    221221static inline void ___destructor__F_P13s__anonymous8_autogen___1(struct __anonymous8 *___dst__P13s__anonymous8_1);
     222static inline void ___constructor__F_P13s__anonymous8_autogen___1(struct __anonymous8 *___dst__P13s__anonymous8_1){
     223    ((void)((*((short *)(&(*___dst__P13s__anonymous8_1).__i__s_1)))) /* ?{} */);
     224}
     225static inline void ___constructor__F_P13s__anonymous813s__anonymous8_autogen___1(struct __anonymous8 *___dst__P13s__anonymous8_1, struct __anonymous8 ___src__13s__anonymous8_1){
     226    ((void)((*((short *)(&(*___dst__P13s__anonymous8_1).__i__s_1)))=___src__13s__anonymous8_1.__i__s_1) /* ?{} */);
     227}
     228static inline void ___destructor__F_P13s__anonymous8_autogen___1(struct __anonymous8 *___dst__P13s__anonymous8_1){
     229    ((void)((*((short *)(&(*___dst__P13s__anonymous8_1).__i__s_1)))) /* ^?{} */);
     230}
    222231static inline struct __anonymous8 ___operator_assign__F13s__anonymous8_P13s__anonymous813s__anonymous8_autogen___1(struct __anonymous8 *___dst__P13s__anonymous8_1, struct __anonymous8 ___src__13s__anonymous8_1){
    223232    ((void)((*___dst__P13s__anonymous8_1).__i__s_1=___src__13s__anonymous8_1.__i__s_1));
    224233    return ((struct __anonymous8 )___src__13s__anonymous8_1);
    225 }
    226 static inline void ___constructor__F_P13s__anonymous8_autogen___1(struct __anonymous8 *___dst__P13s__anonymous8_1){
    227     ((void)((*((short *)(&(*___dst__P13s__anonymous8_1).__i__s_1)))) /* ?{} */);
    228 }
    229 static inline void ___constructor__F_P13s__anonymous813s__anonymous8_autogen___1(struct __anonymous8 *___dst__P13s__anonymous8_1, struct __anonymous8 ___src__13s__anonymous8_1){
    230     ((void)((*((short *)(&(*___dst__P13s__anonymous8_1).__i__s_1)))=___src__13s__anonymous8_1.__i__s_1) /* ?{} */);
    231 }
    232 static inline void ___destructor__F_P13s__anonymous8_autogen___1(struct __anonymous8 *___dst__P13s__anonymous8_1){
    233     ((void)((*((short *)(&(*___dst__P13s__anonymous8_1).__i__s_1)))) /* ^?{} */);
    234234}
    235235static inline void ___constructor__F_P13s__anonymous8s_autogen___1(struct __anonymous8 *___dst__P13s__anonymous8_1, short __i__s_1){
     
    244244static inline void ___constructor__F_P13s__anonymous913s__anonymous9_autogen___1(struct __anonymous9 *___dst__P13s__anonymous9_1, struct __anonymous9 ___src__13s__anonymous9_1);
    245245static inline void ___destructor__F_P13s__anonymous9_autogen___1(struct __anonymous9 *___dst__P13s__anonymous9_1);
     246static inline void ___constructor__F_P13s__anonymous9_autogen___1(struct __anonymous9 *___dst__P13s__anonymous9_1){
     247    ((void)((*((short *)(&(*___dst__P13s__anonymous9_1).__i__s_1)))) /* ?{} */);
     248}
     249static inline void ___constructor__F_P13s__anonymous913s__anonymous9_autogen___1(struct __anonymous9 *___dst__P13s__anonymous9_1, struct __anonymous9 ___src__13s__anonymous9_1){
     250    ((void)((*((short *)(&(*___dst__P13s__anonymous9_1).__i__s_1)))=___src__13s__anonymous9_1.__i__s_1) /* ?{} */);
     251}
     252static inline void ___destructor__F_P13s__anonymous9_autogen___1(struct __anonymous9 *___dst__P13s__anonymous9_1){
     253    ((void)((*((short *)(&(*___dst__P13s__anonymous9_1).__i__s_1)))) /* ^?{} */);
     254}
    246255static inline struct __anonymous9 ___operator_assign__F13s__anonymous9_P13s__anonymous913s__anonymous9_autogen___1(struct __anonymous9 *___dst__P13s__anonymous9_1, struct __anonymous9 ___src__13s__anonymous9_1){
    247256    ((void)((*___dst__P13s__anonymous9_1).__i__s_1=___src__13s__anonymous9_1.__i__s_1));
    248257    return ((struct __anonymous9 )___src__13s__anonymous9_1);
    249 }
    250 static inline void ___constructor__F_P13s__anonymous9_autogen___1(struct __anonymous9 *___dst__P13s__anonymous9_1){
    251     ((void)((*((short *)(&(*___dst__P13s__anonymous9_1).__i__s_1)))) /* ?{} */);
    252 }
    253 static inline void ___constructor__F_P13s__anonymous913s__anonymous9_autogen___1(struct __anonymous9 *___dst__P13s__anonymous9_1, struct __anonymous9 ___src__13s__anonymous9_1){
    254     ((void)((*((short *)(&(*___dst__P13s__anonymous9_1).__i__s_1)))=___src__13s__an