Changeset 1f44196 for src/InitTweak


Ignore:
Timestamp:
Nov 29, 2016, 3:30:59 PM (9 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, stuck-waitfor-destruct, with_gc
Children:
8e5724e
Parents:
3a2128f (diff), 9129a84 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg2:software/cfa/cfa-cc

Conflicts:

src/Parser/parser.cc

Location:
src/InitTweak
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r3a2128f r1f44196  
    1818#include <iterator>
    1919#include <algorithm>
     20#include <unordered_map>
     21#include <unordered_set>
    2022#include "InitTweak.h"
    2123#include "FixInit.h"
     
    3537#include "GenPoly/DeclMutator.h"
    3638#include "SynTree/AddStmtVisitor.h"
    37 #include "CodeGen/GenType.h"  // for warnings
    38 
    39 bool ctordtorp = false;
    40 bool ctorp = false;
    41 bool cpctorp = false;
    42 bool dtorp = false;
     39#include "CodeGen/GenType.h"  // for warning/error messages
     40
     41bool ctordtorp = false; // print all debug
     42bool ctorp = false; // print ctor debug
     43bool cpctorp = false; // print copy ctor debug
     44bool dtorp = false; // print dtor debug
    4345#define PRINT( text ) if ( ctordtorp ) { text }
    4446#define CP_CTOR_PRINT( text ) if ( ctordtorp || cpctorp ) { text }
     
    4749namespace InitTweak {
    4850        namespace {
    49                 const std::list<Label> noLabels;
    50                 const std::list<Expression*> noDesignators;
    51 
    5251                class InsertImplicitCalls final : public GenPoly::PolyMutator {
    5352                public:
     
    6766                        static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
    6867
    69                         using SymTab::Indexer::visit;
     68                        typedef SymTab::Indexer Parent;
     69                        using Parent::visit;
     70
    7071                        virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
     72                        virtual void visit( UniqueExpr * unqExpr );
    7173
    7274                        /// create and resolve ctor/dtor expression: fname(var, [cpArg])
    73                         ApplicationExpr * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );
     75                        Expression * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );
     76                        Expression * makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg = NULL );
    7477                        /// true if type does not need to be copy constructed to ensure correctness
    75                         bool skipCopyConstruct( Type * );
     78                        bool skipCopyConstruct( Type * type );
     79                        void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );
     80                        void destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
    7681                private:
    7782                        TypeSubstitution * env;
     
    183188                        using GenPoly::PolyMutator::mutate;
    184189                        virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
     190                        virtual Expression * mutate( UniqueExpr * unqExpr ) override;
    185191                };
    186192
     
    368374                }
    369375
    370                 ApplicationExpr * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
     376                Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
    371377                        assert( var );
     378                        return makeCtorDtor( fname, new AddressExpr( new VariableExpr( var ) ), cpArg );
     379                }
     380
     381                Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg ) {
     382                        assert( thisArg );
    372383                        UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) );
    373                         untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ) );
     384                        untyped->get_args().push_back( thisArg );
    374385                        if (cpArg) untyped->get_args().push_back( cpArg->clone() );
    375386
     
    378389                        // (VariableExpr and already resolved expression)
    379390                        CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
    380                         ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) );
     391                        Expression * resolved = ResolvExpr::findVoidExpression( untyped, *this );
     392                        assert( resolved );
    381393                        if ( resolved->get_env() ) {
    382394                                env->add( *resolved->get_env() );
    383395                        } // if
    384396
    385                         assert( resolved );
    386397                        delete untyped;
    387398                        return resolved;
    388399                }
    389400
     401                void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {
     402                        static UniqueName tempNamer("_tmp_cp");
     403                        CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; )
     404                        assert( arg->has_result() );
     405                        Type * result = arg->get_result();
     406                        if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types
     407
     408                        // type may involve type variables, so apply type substitution to get temporary variable's actual type
     409                        result = result->clone();
     410                        impCpCtorExpr->get_env()->apply( result );
     411                        ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
     412                        tmp->get_type()->set_isConst( false );
     413
     414                        // create and resolve copy constructor
     415                        CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; )
     416                        Expression * cpCtor = makeCtorDtor( "?{}", tmp, arg );
     417
     418                        if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( cpCtor ) ) {
     419                                // if the chosen constructor is intrinsic, the copy is unnecessary, so
     420                                // don't create the temporary and don't call the copy constructor
     421                                VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
     422                                assert( function );
     423                                if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
     424                        }
     425
     426                        // replace argument to function call with temporary
     427                        arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
     428                        impCpCtorExpr->get_tempDecls().push_back( tmp );
     429                        impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
     430                }
     431
     432                void ResolveCopyCtors::destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr ) {
     433                        impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", new AddressExpr( ret ) ) );
     434                }
     435
    390436                void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
    391                         static UniqueName tempNamer("_tmp_cp");
    392                         static UniqueName retNamer("_tmp_cp_ret");
    393 
    394437                        CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
    395                         Visitor::visit( impCpCtorExpr );
     438                        Parent::visit( impCpCtorExpr );
    396439                        env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer...
    397440
     
    400443                        // take each argument and attempt to copy construct it.
    401444                        for ( Expression * & arg : appExpr->get_args() ) {
    402                                 CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; )
    403                                 // xxx - need to handle tuple arguments
    404                                 assert( ! arg->get_results().empty() );
    405                                 Type * result = arg->get_results().front();
    406                                 if ( skipCopyConstruct( result ) ) continue; // skip certain non-copyable types
    407                                 // type may involve type variables, so apply type substitution to get temporary variable's actual type
    408                                 result = result->clone();
    409                                 impCpCtorExpr->get_env()->apply( result );
    410                                 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
    411                                 tmp->get_type()->set_isConst( false );
    412 
    413                                 // create and resolve copy constructor
    414                                 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; )
    415                                 ApplicationExpr * cpCtor = makeCtorDtor( "?{}", tmp, arg );
    416 
    417                                 // if the chosen constructor is intrinsic, the copy is unnecessary, so
    418                                 // don't create the temporary and don't call the copy constructor
    419                                 VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() );
    420                                 assert( function );
    421                                 if ( function->get_var()->get_linkage() != LinkageSpec::Intrinsic ) {
    422                                         // replace argument to function call with temporary
    423                                         arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
    424                                         impCpCtorExpr->get_tempDecls().push_back( tmp );
    425                                         impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
    426                                 } // if
     445                                copyConstructArg( arg, impCpCtorExpr );
    427446                        } // for
    428447
     
    434453                        // level. Trying to pass that environment along.
    435454                        callExpr->set_env( impCpCtorExpr->get_env()->clone() );
    436                         for ( Type * result : appExpr->get_results() ) {
     455                        Type * result = appExpr->get_result();
     456                        if ( ! result->isVoid() ) {
     457                                static UniqueName retNamer("_tmp_cp_ret");
    437458                                result = result->clone();
    438459                                impCpCtorExpr->get_env()->apply( result );
     
    441462                                impCpCtorExpr->get_returnDecls().push_back( ret );
    442463                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    443                                 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
     464                                if ( ! result->get_isLvalue() ) {
     465                                        // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
     466                                        destructRet( new VariableExpr( ret ), impCpCtorExpr );
     467                                }
    444468                        } // for
    445469                        CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; )
     470                }
     471
     472                void ResolveCopyCtors::visit( UniqueExpr * unqExpr ) {
     473                        static std::unordered_set< int > vars;
     474                        if ( vars.count( unqExpr->get_id() ) ) {
     475                                // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
     476                                return;
     477                        }
     478
     479                        Parent::visit( unqExpr );
     480                        // it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought
     481                        assert( unqExpr->get_result() );
     482                        if ( ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast<ImplicitCopyCtorExpr*>( unqExpr->get_expr() ) ) {
     483                                // note the variable used as the result from the call
     484                                assert( impCpCtorExpr->get_result() && impCpCtorExpr->get_returnDecls().size() == 1 );
     485                                unqExpr->set_var( new VariableExpr( impCpCtorExpr->get_returnDecls().front() ) );
     486                        } else {
     487                                // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
     488                                unqExpr->set_object( new ObjectDecl( toString("_unq_expr_", unqExpr->get_id()), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) );
     489                                unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) );
     490                        }
     491                        vars.insert( unqExpr->get_id() );
    446492                }
    447493
     
    490536                                // know the result type of the assignment is the type of the LHS (minus the pointer), so
    491537                                // add that onto the assignment expression so that later steps have the necessary information
    492                                 assign->add_result( returnDecl->get_type()->clone() );
     538                                assign->set_result( returnDecl->get_type()->clone() );
    493539
    494540                                Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
    495                                 if ( callExpr->get_results().front()->get_isLvalue() ) {
     541                                if ( callExpr->get_result()->get_isLvalue() ) {
    496542                                        // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning
    497543                                        // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the
     
    500546                                        // an AddressExpr.  Effectively, this turns
    501547                                        //   lvalue T f();
    502                                         //   &*f()
     548                                        //   &*f();
    503549                                        // into
     550                                        //   T * f();
    504551                                        //   T * tmp_cp_retN;
    505                                         //   tmp_cp_ret_N = &*(tmp_cp_ret_N = &*f(), tmp_cp_ret);
     552                                        //   &*(tmp_cp_retN = &*f(), tmp_cp_retN);              // the first * and second & are generated here
    506553                                        // which work out in terms of types, but is pretty messy. It would be nice to find a better way.
    507554                                        assign->get_args().back() = new AddressExpr( assign->get_args().back() );
    508555
    509                                         Type * resultType = returnDecl->get_type()->clone();
    510556                                        returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) );
    511                                         UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
    512                                         deref->get_args().push_back( retExpr );
    513                                         deref->add_result( resultType );
    514                                         retExpr = deref;
     557                                        retExpr->set_result( new PointerType( Type::Qualifiers(), retExpr->get_result() ) );
     558                                        retExpr = UntypedExpr::createDeref( retExpr );
    515559                                } // if
    516560                                retExpr->set_env( env->clone() );
     
    519563                                return callExpr;
    520564                        } // if
     565                }
     566
     567                Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
     568                        static std::unordered_map< int, UniqueExpr * > unqMap;
     569                        static std::unordered_set< int > addDeref;
     570                        // 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 ) );
     572                        if ( unqMap.count( unqExpr->get_id() ) ) {
     573                                // take data from other UniqueExpr to ensure consistency
     574                                delete unqExpr->get_expr();
     575                                unqExpr->set_expr( unqMap[unqExpr->get_id()]->get_expr()->clone() );
     576                                delete unqExpr->get_result();
     577                                unqExpr->set_result( maybeClone( unqExpr->get_expr()->get_result() ) );
     578                                if ( addDeref.count( unqExpr->get_id() ) ) {
     579                                        // other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too
     580                                        return UntypedExpr::createDeref( unqExpr );
     581                                }
     582                                return unqExpr;
     583                        }
     584                        unqMap[unqExpr->get_id()] = unqExpr;
     585                        if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) {
     586                                // unique expression is now a dereference, because the inner expression is an lvalue returning function call.
     587                                // Normalize the expression by dereferencing the unique expression, rather than the inner expression
     588                                // (i.e. move the dereference out a level)
     589                                assert( getFunctionName( deref ) == "*?" );
     590                                unqExpr->set_expr( getCallArg( deref, 0 ) );
     591                                getCallArg( deref, 0 ) = unqExpr;
     592                                addDeref.insert( unqExpr->get_id() );
     593                                return deref;
     594                        }
     595                        return unqExpr;
    521596                }
    522597
     
    9501025                Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) {
    9511026                        static UniqueName tempNamer( "_tmp_ctor_expr" );
    952                         assert( ctorExpr->get_results().size() == 1 );
    953                         ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, ctorExpr->get_results().front()->clone(), nullptr );
     1027                        // xxx - is the size check necessary?
     1028                        assert( ctorExpr->has_result() && ctorExpr->get_result()->size() == 1 );
     1029                        ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr );
    9541030                        addDeclaration( tmp );
    9551031
     
    9631039                        assign->get_args().push_back( new VariableExpr( tmp ) );
    9641040                        assign->get_args().push_back( firstArg );
    965                         cloneAll( ctorExpr->get_results(), assign->get_results() );
     1041                        assign->set_result( ctorExpr->get_result()->clone() );
    9661042                        firstArg = assign;
    9671043
  • src/InitTweak/GenInit.cc

    r3a2128f r1f44196  
    2929#include "GenPoly/DeclMutator.h"
    3030#include "GenPoly/ScopedSet.h"
     31#include "ResolvExpr/typeops.h"
    3132
    3233namespace InitTweak {
     
    5051
    5152          protected:
    52                 std::list<DeclarationWithType*> returnVals;
     53                FunctionType * ftype;
    5354                UniqueName tempNamer;
    5455                std::string funcName;
     
    8687
    8788                bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
     89                bool isManaged( Type * type ) const; // determine if type is managed
    8890                void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
    8991                GenPoly::ScopedSet< std::string > managedTypes;
     
    136138
    137139        Statement *ReturnFixer::mutate( ReturnStmt *returnStmt ) {
    138                 // update for multiple return values
     140                std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals();
    139141                assert( returnVals.size() == 0 || returnVals.size() == 1 );
    140142                // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
     
    158160
    159161        DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) {
    160                 ValueGuard< std::list<DeclarationWithType*> > oldReturnVals( returnVals );
     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
     171                ValueGuard< FunctionType * > oldFtype( ftype );
    161172                ValueGuard< std::string > oldFuncName( funcName );
    162173
    163                 FunctionType * type = functionDecl->get_functionType();
    164                 returnVals = type->get_returnVals();
     174                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                }
    165182                funcName = functionDecl->get_name();
    166183                DeclarationWithType * decl = Mutator::mutate( functionDecl );
     
    222239        }
    223240
     241        bool CtorDtor::isManaged( Type * type ) const {
     242                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
     243                        // tuple is also managed if any of its components are managed
     244                        if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {
     245                                return true;
     246                        }
     247                }
     248                return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
     249        }
     250
    224251        bool CtorDtor::isManaged( ObjectDecl * objDecl ) const {
    225252                Type * type = objDecl->get_type();
     
    227254                        type = at->get_base();
    228255                }
    229                 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
     256                return isManaged( type );
    230257        }
    231258
     
    238265                        managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) );
    239266                }
     267        }
     268
     269        ConstructorInit * genCtorInit( ObjectDecl * objDecl ) {
     270                // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
     271                // for each constructable object
     272                std::list< Statement * > ctor;
     273                std::list< Statement * > dtor;
     274
     275                InitExpander srcParam( objDecl->get_init() );
     276                InitExpander nullParam( (Initializer *)NULL );
     277                SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
     278                SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
     279
     280                // Currently genImplicitCall produces a single Statement - a CompoundStmt
     281                // which  wraps everything that needs to happen. As such, it's technically
     282                // possible to use a Statement ** in the above calls, but this is inherently
     283                // unsafe, so instead we take the slightly less efficient route, but will be
     284                // immediately informed if somehow the above assumption is broken. In this case,
     285                // we could always wrap the list of statements at this point with a CompoundStmt,
     286                // but it seems reasonable at the moment for this to be done by genImplicitCall
     287                // itself. It is possible that genImplicitCall produces no statements (e.g. if
     288                // an array type does not have a dimension). In this case, it's fine to ignore
     289                // the object for the purposes of construction.
     290                assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
     291                if ( ctor.size() == 1 ) {
     292                        // need to remember init expression, in case no ctors exist
     293                        // if ctor does exist, want to use ctor expression instead of init
     294                        // push this decision to the resolver
     295                        assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
     296                        return new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() );
     297                }
     298                return nullptr;
    240299        }
    241300
     
    250309                        if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl );
    251310
    252                         // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
    253                         // for each constructable object
    254                         std::list< Statement * > ctor;
    255                         std::list< Statement * > dtor;
    256 
    257                         InitExpander srcParam( objDecl->get_init() );
    258                         InitExpander nullParam( (Initializer *)NULL );
    259                         SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
    260                         SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
    261 
    262                         // Currently genImplicitCall produces a single Statement - a CompoundStmt
    263                         // which  wraps everything that needs to happen. As such, it's technically
    264                         // possible to use a Statement ** in the above calls, but this is inherently
    265                         // unsafe, so instead we take the slightly less efficient route, but will be
    266                         // immediately informed if somehow the above assumption is broken. In this case,
    267                         // we could always wrap the list of statements at this point with a CompoundStmt,
    268                         // but it seems reasonable at the moment for this to be done by genImplicitCall
    269                         // itself. It is possible that genImplicitCall produces no statements (e.g. if
    270                         // an array type does not have a dimension). In this case, it's fine to ignore
    271                         // the object for the purposes of construction.
    272                         assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
    273                         if ( ctor.size() == 1 ) {
    274                                 // need to remember init expression, in case no ctors exist
    275                                 // if ctor does exist, want to use ctor expression instead of init
    276                                 // push this decision to the resolver
    277                                 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
    278                                 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
    279                         }
     311                        objDecl->set_init( genCtorInit( objDecl ) );
    280312                }
    281313                return Parent::mutate( objDecl );
     
    290322                managedTypes.beginScope();
    291323                // go through assertions and recursively add seen ctor/dtors
    292                 for ( TypeDecl * tyDecl : functionDecl->get_functionType()->get_forall() ) {
     324                for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) {
    293325                        for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) {
    294326                                assertion = assertion->acceptMutator( *this );
  • src/InitTweak/GenInit.h

    r3a2128f r1f44196  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // RemoveInit.h --
     7// GenInit.h --
    88//
    99// Author           : Rodolfo G. Esteves
     
    2727        /// Adds return value temporaries and wraps Initializers in ConstructorInit nodes
    2828        void genInit( std::list< Declaration * > & translationUnit );
     29
     30        /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
     31        ConstructorInit * genCtorInit( ObjectDecl * objDecl );
    2932} // namespace
    3033
  • src/InitTweak/InitTweak.cc

    r3a2128f r1f44196  
    340340                return allofCtorDtor( stmt, []( Expression * callExpr ){
    341341                        if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
    342                                 assert( ! appExpr->get_function()->get_results().empty() );
    343                                 FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() );
     342                                FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_result() );
    344343                                assert( funcType );
    345344                                return funcType->get_parameters().size() == 1;
     
    388387                                return memberExpr->get_member()->get_name();
    389388                        } else if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * > ( func ) ) {
    390                                 return memberExpr->get_member();
     389                                return funcName( memberExpr->get_member() );
    391390                        } else {
    392391                                assertf( false, "Unexpected expression type being called as a function in call expression" );
     
    451450                // virtual void visit( LogicalExpr *logicalExpr );
    452451                // virtual void visit( ConditionalExpr *conditionalExpr );
    453                 virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
    454                 virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }
    455452                virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }
    456453                virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }
    457454                virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }
    458455                virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }
     456                virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
     457                virtual void visit( TupleAssignExpr *tupleExpr ) { isConstExpr = false; }
    459458
    460459                bool isConstExpr;
Note: See TracChangeset for help on using the changeset viewer.