Changeset 4d2434a


Ignore:
Timestamp:
Aug 2, 2016, 6:37:08 PM (8 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
8a443f4
Parents:
39f84a4
Message:

major reorganization of constructor generation from initializer list so that it now works with multi-dimensional arrays

Location:
src
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    r39f84a4 r4d2434a  
    270270                printDesignators( init->get_designators() );
    271271                output << "{ ";
    272                 if ( init->begin_initializers() == init->end_initializers() ) {
     272                if ( init->begin() == init->end() ) {
    273273                        // illegal to leave initializer list empty for scalar initializers, but always legal to have 0
    274274                        output << "0";
    275275                } else {
    276                         genCommaList( init->begin_initializers(), init->end_initializers() );
     276                        genCommaList( init->begin(), init->end() );
    277277                }
    278278                output << " }";
  • src/InitTweak/GenInit.cc

    r39f84a4 r4d2434a  
    154154        }
    155155
     156        // precompute array dimension expression, because constructor generation may duplicate it,
     157        // which would be incorrect if it is a side-effecting computation.
    156158        void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
    157159                HoistArrayDimension hoister;
     
    215217                // hands off if designated, if @=, or if extern
    216218                if ( tryConstruct( objDecl ) ) {
    217                         if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
    218                                 // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array
    219                                 // TODO: walk initializers and generate appropriate ctor if element has initializer.
    220                                 // Initializer could be nested (depends on the depth of the array type on the object)
    221 
    222                                 std::list< Expression * > args = makeInitList( objDecl->get_init() );
    223                                 if ( args.empty() ) {
    224                                         std::list< Statement * > ctor;
    225                                         std::list< Statement * > dtor;
    226 
    227                                         InitExpander srcParam( (Expression *)NULL );
    228                                         SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
    229                                         SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
    230 
    231                                         // Currently genImplicitCall produces a single Statement - a CompoundStmt
    232                                         // which  wraps everything that needs to happen. As such, it's technically
    233                                         // possible to use a Statement ** in the above calls, but this is inherently
    234                                         // unsafe, so instead we take the slightly less efficient route, but will be
    235                                         // immediately informed if somehow the above assumption is broken. In this case,
    236                                         // we could always wrap the list of statements at this point with a CompoundStmt,
    237                                         // but it seems reasonable at the moment for this to be done by genImplicitCall
    238                                         // itself. It is possible that genImplicitCall produces no statements (e.g. if
    239                                         // an array type does not have a dimension). In this case, it's fine to ignore
    240                                         // the object for the purposes of construction.
    241                                         assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
    242                                         if ( ctor.size() == 1 ) {
    243                                                 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
    244                                                 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
    245                                         }
    246                                 } else {
    247                                         // array came with an initializer list: initialize each element
    248                                         // may have more initializers than elements in the array - need to check at each index that
    249                                         // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting
    250                                         // computation.
    251                                         // may have fewer initializers than elements in the array - need to default construct
    252                                         // remaining elements.
    253                                         // might be able to merge this with the case above.
    254 
    255                                 }
    256                         } else {
    257                                 // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer
    258                                 Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
    259                                 Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );
    260 
     219                        // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
     220                        // for each constructable object
     221                        std::list< Statement * > ctor;
     222                        std::list< Statement * > dtor;
     223
     224                        InitExpander srcParam( objDecl->get_init() );
     225                        InitExpander nullParam( (Initializer *)NULL );
     226                        SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
     227                        SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
     228
     229                        // Currently genImplicitCall produces a single Statement - a CompoundStmt
     230                        // which  wraps everything that needs to happen. As such, it's technically
     231                        // possible to use a Statement ** in the above calls, but this is inherently
     232                        // unsafe, so instead we take the slightly less efficient route, but will be
     233                        // immediately informed if somehow the above assumption is broken. In this case,
     234                        // we could always wrap the list of statements at this point with a CompoundStmt,
     235                        // but it seems reasonable at the moment for this to be done by genImplicitCall
     236                        // itself. It is possible that genImplicitCall produces no statements (e.g. if
     237                        // an array type does not have a dimension). In this case, it's fine to ignore
     238                        // the object for the purposes of construction.
     239                        assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
     240                        if ( ctor.size() == 1 ) {
    261241                                // need to remember init expression, in case no ctors exist
    262242                                // if ctor does exist, want to use ctor expression instead of init
    263243                                // push this decision to the resolver
    264                                 ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );
    265                                 ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor );
    266                                 objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) );
     244                                assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
     245                                objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
    267246                        }
    268247                }
  • src/InitTweak/InitTweak.cc

    r39f84a4 r4d2434a  
     1#include <algorithm>
    12#include "InitTweak.h"
    23#include "SynTree/Visitor.h"
     
    2021                };
    2122
    22                 class InitExpander_OLD : public Visitor {
     23                class InitFlattener : public Visitor {
    2324                        public:
    2425                        virtual void visit( SingleInit * singleInit );
     
    2728                };
    2829
    29                 void InitExpander_OLD::visit( SingleInit * singleInit ) {
     30                void InitFlattener::visit( SingleInit * singleInit ) {
    3031                        argList.push_back( singleInit->get_value()->clone() );
    3132                }
    3233
    33                 void InitExpander_OLD::visit( ListInit * listInit ) {
    34                         // xxx - for now, assume no nested list inits
    35                         std::list<Initializer*>::iterator it = listInit->begin_initializers();
    36                         for ( ; it != listInit->end_initializers(); ++it ) {
     34                void InitFlattener::visit( ListInit * listInit ) {
     35                        // flatten nested list inits
     36                        std::list<Initializer*>::iterator it = listInit->begin();
     37                        for ( ; it != listInit->end(); ++it ) {
    3738                                (*it)->accept( *this );
    3839                        }
     
    4142
    4243        std::list< Expression * > makeInitList( Initializer * init ) {
    43                 InitExpander_OLD expander;
    44                 maybeAccept( init, expander );
    45                 return expander.argList;
     44                InitFlattener flattener;
     45                maybeAccept( init, flattener );
     46                return flattener.argList;
    4647        }
    4748
     
    5556        public:
    5657                virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0;
     58                virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0;
    5759        };
    5860
    5961        class InitImpl : public InitExpander::ExpanderImpl {
    6062        public:
    61                 InitImpl( Initializer * init ) {
    62                         if ( init ) inits.push_back( init );
    63                 }
     63                InitImpl( Initializer * init ) : init( init ) {}
    6464
    6565                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
    6666                        // this is wrong, but just a placeholder for now
    67                         return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();
    68                 }
     67                        // if ( ! flattened ) flatten( indices );
     68                        // return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();
     69                        return makeInitList( init );
     70                }
     71
     72                virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
    6973        private:
    70                 std::list< Initializer * > inits;
     74                Initializer * init;
    7175        };
    7276
     
    9195                        return ret;
    9296                }
     97
     98                virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
    9399        private:
    94100                Expression * arg;
     
    114120        }
    115121
    116         template< typename OutIterator >
    117         void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator end, OutIterator out ) {
    118                 if ( idx == end ) return;
    119                 Expression * index = *idx++;
    120                 assert( idx != end );
    121                 Expression * dimension = *idx++;
    122 
    123                 // if ( idx == end ) {
    124                 //      // loop through list of expressions belonging to the current initializer
    125                 //      UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
    126                 //      cond->get_args().push_back( index->clone() );
    127                 //      cond->get_args().push_back( dimension->clone() );
    128 
    129                 //      UntypedExpr * call = callExpr->clone();
    130                 //      std::list< Expression * > args = *++expander; // xxx - need a way to indentify the end of an init list
    131                 //      call->get_args().splice( args );
    132 
    133                 //      *out++ = new IfStmt( noLabels, cond, new ExprStmt( call ), NULL );
    134 
    135                 //      UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
    136                 //      increment->get_args().push_back( index->clone() );
    137                 //      *out++ = new ExprStmt( increment );
    138                 // } else {
    139                 //      std::list< Statement * > branches;
    140                 //      for (...) { // loop over conditions?
    141                 //              std::list< Statement * > stmts;
    142                 //              build( idx, end, back_inserter( stmts ) );
    143                 //              CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
    144                 //              branches.push_back( caseStmt );
    145                 //      }
    146                 //      *out++ = new SwitchStmt( noLabels, index->clone(), branches );
    147                 // }
    148         }
    149 
    150         // generate switch statement, consuming all of expander's elements
     122        void InitExpander::clearArrayIndices() {
     123                indices.clear();
     124        }
     125
     126        namespace {
     127                template< typename OutIterator >
     128                void dothething( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
     129                        UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
     130                        cond->get_args().push_back( index->clone() );
     131                        cond->get_args().push_back( dimension->clone() );
     132
     133                        std::list< Expression * > args = makeInitList( init );
     134                        callExpr->get_args().splice( callExpr->get_args().end(), args );
     135
     136                        *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL );
     137
     138                        UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
     139                        increment->get_args().push_back( new AddressExpr( index->clone() ) );
     140                        *out++ = new ExprStmt( noLabels, increment );
     141                }
     142
     143                template< typename OutIterator >
     144                void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
     145                        if ( idx == idxEnd ) return;
     146                        Expression * index = *idx++;
     147                        assert( idx != idxEnd );
     148                        Expression * dimension = *idx++;
     149
     150                        if ( idx == idxEnd ) {
     151                                if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) {
     152                                        for ( Initializer * init : *listInit ) {
     153                                                dothething( callExpr->clone(), index, dimension, init, out );
     154                                        }
     155                                } else {
     156                                        dothething( callExpr->clone(), index, dimension, init, out );
     157                                }
     158                        } else {
     159                                std::list< Statement * > branches;
     160
     161                                unsigned long cond = 0;
     162                                ListInit * listInit = dynamic_cast< ListInit * >( init );
     163                                if ( ! listInit ) {
     164                                        // xxx - this shouldn't be an error, but need a way to
     165                                        // terminate without creating output, so should catch this error
     166                                        throw SemanticError( "unbalanced list initializers" );
     167                                }
     168                                for ( Initializer * init : *listInit ) {
     169                                        Expression * condition;
     170                                        // check for designations
     171                                        // if ( init-> ) {
     172                                                condition = new ConstantExpr( Constant::from_ulong( cond ) );
     173                                                ++cond;
     174                                        // } else {
     175                                        //      condition = // ... take designation
     176                                        //      cond = // ... take designation+1
     177                                        // }
     178                                        std::list< Statement * > stmts;
     179                                        build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
     180                                        CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
     181                                        branches.push_back( caseStmt );
     182                                }
     183                                *out++ = new SwitchStmt( noLabels, index->clone(), branches );
     184                        }
     185                }
     186        }
     187
     188        // if array came with an initializer list: initialize each element
     189        // may have more initializers than elements in the array - need to check at each index that
     190        // we haven't exceeded size.
     191        // may have fewer initializers than elements in the array - need to default construct
     192        // remaining elements.
     193        // To accomplish this, generate switch statement, consuming all of expander's elements
     194        Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
     195                if ( ! init ) return NULL;
     196                std::list< Statement * > results;
     197                build( dst, indices.begin(), indices.end(), init, back_inserter( results ) );
     198                assert( results.size() <= 1 );
     199                if ( results.empty() ) {
     200                        return NULL;
     201                } else {
     202                        init = NULL; // init was consumed in creating the list init
     203                        return results.front();
     204                }
     205                return ! results.empty() ? results.front() : NULL;
     206        }
     207
     208        Statement * ExprImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
     209                return NULL;
     210        }
     211
    151212        Statement * InitExpander::buildListInit( UntypedExpr * dst ) {
    152                 std::list< Statement * > results;
    153                 build( dst, indices.begin(), indices.end(), back_inserter( results ) );
    154                 assert( results.size() <= 1 );
    155                 return ! results.empty() ? results.front() : NULL;
     213                return expander->buildListInit( dst, indices );
    156214        }
    157215
     
    164222        }
    165223
     224        class CallFinder : public Visitor {
     225        public:
     226                typedef Visitor Parent;
     227                CallFinder( const std::list< std::string > & names ) : names( names ) {}
     228
     229                virtual void visit( ApplicationExpr * appExpr ) {
     230                        handleCallExpr( appExpr );
     231                }
     232
     233                virtual void visit( UntypedExpr * untypedExpr ) {
     234                        handleCallExpr( untypedExpr );
     235                }
     236
     237                std::list< Expression * > * matches;
     238        private:
     239                const std::list< std::string > names;
     240
     241                template< typename CallExpr >
     242                void handleCallExpr( CallExpr * expr ) {
     243                        Parent::visit( expr );
     244                        std::string fname = getFunctionName( expr );
     245                        if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
     246                                matches->push_back( expr );
     247                        }
     248                }
     249        };
     250
     251        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
     252                static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } );
     253                finder.matches = &matches;
     254                maybeAccept( stmt, finder );
     255        }
     256
    166257        Expression * getCtorDtorCall( Statement * stmt ) {
    167                 if ( stmt == NULL ) return NULL;
    168                 if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
    169                         return exprStmt->get_expr();
    170                 } else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) {
    171                         // could also be a compound statement with a loop, in the case of an array
    172                         if( compoundStmt->get_kids().size() == 2 ) {
    173                                 // loop variable and loop
    174                                 ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() );
    175                                 assert( forStmt && forStmt->get_body() );
    176                                 return getCtorDtorCall( forStmt->get_body() );
    177                         } else if ( compoundStmt->get_kids().size() == 1 ) {
    178                                 // should be the call statement, but in any case there's only one option
    179                                 return getCtorDtorCall( compoundStmt->get_kids().front() );
    180                         } else {
    181                                 assert( false && "too many statements in compoundStmt for getCtorDtorCall" );
    182                         }
    183                 } if ( ImplicitCtorDtorStmt * impCtorDtorStmt = dynamic_cast< ImplicitCtorDtorStmt * > ( stmt ) ) {
    184                         return getCtorDtorCall( impCtorDtorStmt->get_callStmt() );
    185                 } else {
    186                         // should never get here
    187                         assert( false && "encountered unknown call statement" );
    188                 }
    189         }
     258                std::list< Expression * > matches;
     259                collectCtorDtorCalls( stmt, matches );
     260                assert( matches.size() <= 1 );
     261                return matches.size() == 1 ? matches.front() : NULL;
     262        }
     263
    190264        namespace {
    191265                VariableExpr * getCalledFunction( ApplicationExpr * appExpr ) {
    192266                        assert( appExpr );
     267                        // xxx - it's possible this can be other things, e.g. MemberExpr, so this is insufficient
    193268                        return dynamic_cast< VariableExpr * >( appExpr->get_function() );
    194269                }
     
    206281
    207282        bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
    208                 Expression * callExpr = getCtorDtorCall( stmt );
    209                 if ( ! callExpr ) return false;
    210                 if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
    211                         assert( ! appExpr->get_function()->get_results().empty() );
    212                         FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() );
    213                         assert( funcType );
    214                         return funcType->get_parameters().size() == 1;
    215                 }
    216                 return false;
     283                std::list< Expression * > callExprs;
     284                collectCtorDtorCalls( stmt, callExprs );
     285                // if ( callExprs.empty() ) return false; // xxx - do I still need this check?
     286                return std::all_of( callExprs.begin(), callExprs.end(), []( Expression * callExpr ){
     287                        if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
     288                                assert( ! appExpr->get_function()->get_results().empty() );
     289                                FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() );
     290                                assert( funcType );
     291                                return funcType->get_parameters().size() == 1;
     292                        }
     293                        return false;
     294                });
    217295        }
    218296
  • src/InitTweak/InitTweak.h

    r39f84a4 r4d2434a  
    4343        bool isInstrinsicSingleArgCallStmt( Statement * expr );
    4444
     45        /// get all Ctor/Dtor call expressions from a Statement
     46        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
     47
    4548        /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
    4649        Expression * getCtorDtorCall( Statement * stmt );
     
    7881                Statement * buildListInit( UntypedExpr * callExpr );
    7982                void addArrayIndex( Expression * index, Expression * dimension );
     83                void clearArrayIndices();
    8084
    8185                class ExpanderImpl;
  • src/ResolvExpr/Resolver.cc

    r39f84a4 r4d2434a  
    5454                virtual void visit( BranchStmt *branchStmt );
    5555                virtual void visit( ReturnStmt *returnStmt );
    56                 virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt );
    5756
    5857                virtual void visit( SingleInit *singleInit );
     
    436435
    437436        void Resolver::visit( ListInit * listInit ) {
    438                 InitIterator iter = listInit->begin_initializers();
    439                 InitIterator end = listInit->end_initializers();
     437                InitIterator iter = listInit->begin();
     438                InitIterator end = listInit->end();
    440439
    441440                if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
     
    539538                        ctorInit->set_ctor( NULL );
    540539                }
    541                 if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
     540                if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_dtor() ) ) {
    542541                        delete ctorInit->get_dtor();
    543542                        ctorInit->set_dtor( NULL );
    544543                }
    545         }
    546 
    547         void Resolver::visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) {
    548                 // before resolving ctor/dtor, need to remove type qualifiers from the first argument (the object being constructed).
    549                 // Do this through a cast expression to greatly simplify the code.
    550                 Expression * callExpr = InitTweak::getCtorDtorCall( impCtorDtorStmt );
    551                 assert( callExpr );
    552                 Expression *& constructee = InitTweak::getCallArg( callExpr, 0 );
    553 
    554                 // the first argument will always be &<expr>
    555                 AddressExpr * addrExpr = dynamic_cast< AddressExpr * > ( constructee );
    556                 assert( addrExpr );
    557 
    558                 // need to find the type of the first argument. In the case of an array,
    559                 // need to remove one ArrayType layer from the type for each subscript expression.
    560                 Expression * addressee = addrExpr->get_arg();
    561                 int numLayers = 0;
    562                 while ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( addressee ) ) {
    563                         assert( InitTweak::getFunctionName( untypedExpr ) == "?[?]" );
    564                         addressee = InitTweak::getCallArg( untypedExpr, 0 );
    565                         numLayers++;
    566                 }
    567                 assert( addressee->get_results().size() == 1 );
    568                 Type * type = addressee->get_results().front();
    569                 for ( int i = 0; i < numLayers; i++ ) {
    570                         type = InitTweak::getPointerBase( type );
    571                         assert( type && "Expected pointer or array type. May have generated too many ?[?] calls." );
    572                 }
    573 
    574                 // cast to T* with qualifiers removed.
    575                 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
    576                 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
    577                 // remove lvalue as a qualifier, this can change to
    578                 //   type->get_qualifiers() = Type::Qualifiers();
    579                 assert( type );
    580                 type = type->clone();
    581                 type->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
    582                 type = new PointerType( Type::Qualifiers(), type );
    583                 constructee = new CastExpr( constructee, type );
    584 
    585                 // finally, resolve the ctor/dtor
    586                 impCtorDtorStmt->get_callStmt()->accept( *this );
    587544        }
    588545} // namespace ResolvExpr
  • src/SymTab/Autogen.h

    r39f84a4 r4d2434a  
    3737        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    3838        template< typename OutputIterator >
    39         void genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool forward = true );
     39        void genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
    4040
    4141        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
    4242        template< typename OutputIterator >
    43         void genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out ) {
     43        void genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
    4444                // want to be able to generate assignment, ctor, and dtor generically,
    4545                // so fname is either ?=?, ?{}, or ^?{}
     
    4747
    4848                // do something special for unnamed members
    49                 fExpr->get_args().push_back( new AddressExpr( dstParam ) );
     49                dstParam = new AddressExpr( dstParam );
     50                if ( addCast ) {
     51                        // cast to T* with qualifiers removed, so that qualified objects can be constructed
     52                        // and destructed with the same functions as non-qualified objects.
     53                        // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
     54                        // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
     55                        // remove lvalue as a qualifier, this can change to
     56                        //   type->get_qualifiers() = Type::Qualifiers();
     57                        assert( type );
     58                        Type * castType = type->clone();
     59                        castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
     60                        castType->set_isLvalue( true ); // xxx - might not need this
     61                        dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
     62                }
     63                fExpr->get_args().push_back( dstParam );
    5064
    5165    Statement * listInit = srcParam.buildListInit( fExpr );
     
    5670    std::list< Expression * > args = *++srcParam;
    5771    fExpr->get_args().splice( fExpr->get_args().end(), args );
    58 /*              if ( srcParam ) {
    59                         // xxx -
    60                         // make srcParam more complicated
    61                         // if srcParam contains
    62                         fExpr->get_args().push_back( srcParam );
    63                 }
    64 */
     72
    6573                *out++ = new ExprStmt( noLabels, fExpr );
     74
     75    srcParam.clearArrayIndices();
    6676        }
    6777
     
    6979        /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    7080        template< typename OutputIterator >
    71         void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool forward = true ) {
     81        void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
    7282                static UniqueName indexName( "_index" );
    7383
     
    124134                // for stmt's body, eventually containing call
    125135                CompoundStmt * body = new CompoundStmt( noLabels );
    126                 genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), forward );
     136                genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
    127137
    128138                // block containing for stmt and index variable
     
    136146
    137147        template< typename OutputIterator >
    138         void genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool forward ) {
     148        void genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
    139149                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    140                         genArrayCall( srcParam, dstParam, fname, out, at, forward );
     150                        genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
    141151                } else {
    142                         genScalarCall( srcParam, dstParam, fname, out );
     152                        genScalarCall( srcParam, dstParam, fname, out, type, addCast );
    143153                }
    144154        }
     
    155165                if ( isUnnamedBitfield( obj ) ) return;
    156166
     167                bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) );
    157168                std::list< Statement * > stmts;
    158                 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), forward );
     169                genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
    159170
    160171                // currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call
     
    162173    if ( stmts.size() == 1 ) {
    163174                Statement * callStmt = stmts.front();
    164                 if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) {
     175                if ( addCast ) {
    165176                        // implicitly generated ctor/dtor calls should be wrapped
    166177                        // so that later passes are aware they were generated.
  • src/SynTree/Initializer.h

    r39f84a4 r4d2434a  
    9393        std::list<Initializer*> &get_initializers() { return initializers; }
    9494
    95         std::list<Initializer*>::iterator begin_initializers() { return initializers.begin(); }
    96         std::list<Initializer*>::iterator end_initializers() { return initializers.end(); }
     95        typedef std::list<Initializer*>::iterator iterator;
     96        iterator begin() { return initializers.begin(); }
     97        iterator end() { return initializers.end(); }
    9798
    9899        virtual ListInit *clone() const { return new ListInit( *this ); }
Note: See TracChangeset for help on using the changeset viewer.