Ignore:
Timestamp:
Aug 19, 2016, 2:42:04 PM (9 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, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
e85a8631
Parents:
03da511 (diff), ac71a86 (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' into ctor

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/StatementNode.cc

    r03da511 r04cdd9b  
    1010// Created On       : Sat May 16 14:59:41 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug  7 06:42:38 2016
    13 // Update Count     : 135
     12// Last Modified On : Mon Aug 15 20:47:11 2016
     13// Update Count     : 322
    1414//
    1515
     
    2626using namespace std;
    2727
    28 const char *StatementNode::StType[] = {
    29         "Exp",   "If",       "Switch", "Case",    "Default",  "Choose",   "Fallthru",
    30         "While", "Do",       "For",
    31         "Goto",  "Continue", "Break",  "Return",  "Throw",
    32         "Try",   "Catch",    "Finally", "Asm",
    33         "Decl"
    34 };
    35 
    36 StatementNode::StatementNode() : ParseNode(), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {}
    37 
    38 StatementNode::StatementNode( const string *name ) : ParseNode( name ), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {}
    39 
    40 StatementNode::StatementNode( DeclarationNode *decl ) : type( Decl ), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), isCatchRest ( false ) {
     28
     29StatementNode::StatementNode( DeclarationNode *decl ) {
    4130        if ( decl ) {
    42                 if ( DeclarationNode *agg = decl->extractAggregate() ) {
    43                         this->decl = agg;
    44                         StatementNode *nextStmt = new StatementNode;
    45                         nextStmt->type = Decl;
    46                         nextStmt->decl = decl;
    47                         next = nextStmt;
    48                         if ( decl->get_link() ) {
    49                                 next->set_next( new StatementNode( dynamic_cast< DeclarationNode* >( decl->get_link() ) ) );
     31                DeclarationNode *agg = decl->extractAggregate();
     32                if ( agg ) {
     33                        StatementNode *nextStmt = new StatementNode( new DeclStmt( noLabels, maybeBuild< Declaration >( decl ) ) );
     34                        set_next( nextStmt );
     35                        if ( decl->get_next() ) {
     36                                get_next()->set_next( new StatementNode( dynamic_cast< DeclarationNode * >(decl->get_next()) ) );
    5037                                decl->set_next( 0 );
    5138                        } // if
    5239                } else {
    53                         if ( decl->get_link() ) {
    54                                 next = new StatementNode( dynamic_cast< DeclarationNode* >( decl->get_link() ) );
     40                        if ( decl->get_next() ) {
     41                                set_next(new StatementNode( dynamic_cast< DeclarationNode * >( decl->get_next() ) ) );
    5542                                decl->set_next( 0 );
    5643                        } // if
    57                         this->decl = decl;
     44                        agg = decl;
    5845                } // if
     46                stmt.reset( new DeclStmt( noLabels, maybeBuild< Declaration >(agg) ) );
     47        } else {
     48                assert( false );
    5949        } // if
    6050}
    6151
    62 StatementNode::StatementNode( Type t, ExpressionNode *ctrl_label, StatementNode *block ) : type( t ), control( ctrl_label ), block( block ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {
    63         this->control = ( t == Default ) ? 0 : control;
    64 }
    65 
    66 StatementNode::StatementNode( Type t, string *target ) : type( t ), control( 0 ), block( 0 ), labels( 0 ), target( target ), decl( 0 ), isCatchRest ( false ) {}
    67 
    68 StatementNode::~StatementNode() {
    69         delete control;
    70         delete block;
    71         delete target;
    72         delete decl;
    73 }
    74 
    75 StatementNode * StatementNode::newCatchStmt( DeclarationNode *d, StatementNode *s, bool catchRestP ) {
    76         StatementNode *ret = new StatementNode( StatementNode::Catch, 0, s );
    77         ret->addDeclaration( d );
    78         ret->setCatchRest( catchRestP );
    79 
    80         return ret;
    81 }
    82 
    83 std::string StatementNode::get_target() const{
    84         if ( target )
    85                 return *target;
    86 
    87         return string("");
    88 }
    89 
    90 StatementNode * StatementNode::clone() const {
    91         StatementNode *newnode = new StatementNode( type, maybeClone( control ), maybeClone( block ) );
    92         if ( target ) {
    93                 newnode->target = new string( *target );
    94         } else {
    95                 newnode->target = 0;
     52StatementNode *StatementNode::append_last_case( StatementNode *stmt ) {
     53        StatementNode *prev = this;
     54        // find end of list and maintain previous pointer
     55        for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) {
     56                StatementNode *node = dynamic_cast< StatementNode * >(curr);
     57                assert( node );
     58                assert( dynamic_cast< CaseStmt * >(node->stmt.get()) );
     59                prev = curr;
     60        } // for
     61        // convert from StatementNode list to Statement list
     62        StatementNode *node = dynamic_cast< StatementNode * >(prev);
     63        std::list< Statement * > stmts;
     64        buildMoveList( stmt, stmts );
     65        // splice any new Statements to end of current Statements
     66        CaseStmt * caseStmt = dynamic_cast< CaseStmt * >(node->stmt.get());
     67        caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts );
     68        return this;
     69}
     70
     71Statement *build_expr( ExpressionNode *ctl ) {
     72        Expression *e = maybeMoveBuild< Expression >( ctl );
     73
     74        if ( e )
     75                return new ExprStmt( noLabels, e );
     76        else
     77                return new NullStmt( noLabels );
     78}
     79
     80Statement *build_if( ExpressionNode *ctl, StatementNode *then_stmt, StatementNode *else_stmt ) {
     81        Statement *thenb, *elseb = 0;
     82        std::list< Statement * > branches;
     83        buildMoveList< Statement, StatementNode >( then_stmt, branches );
     84        assert( branches.size() == 1 );
     85        thenb = branches.front();
     86
     87        if ( else_stmt ) {
     88                std::list< Statement * > branches;
     89                buildMoveList< Statement, StatementNode >( else_stmt, branches );
     90                assert( branches.size() == 1 );
     91                elseb = branches.front();
    9692        } // if
    97         newnode->decl = maybeClone( decl );
    98         return newnode;
    99 }
    100 
    101 StatementNode *StatementNode::add_label( const std::string *l ) {
    102         if ( l != 0 ) {
    103                 labels.push_front( *l );
    104                 delete l;
     93        return new IfStmt( noLabels, notZeroExpr( maybeMoveBuild< Expression >(ctl) ), thenb, elseb );
     94}
     95
     96Statement *build_switch( ExpressionNode *ctl, StatementNode *stmt ) {
     97        std::list< Statement * > branches;
     98        buildMoveList< Statement, StatementNode >( stmt, branches );
     99        assert( branches.size() >= 0 );                                         // size == 0 for switch (...) {}, i.e., no declaration or statements
     100        return new SwitchStmt( noLabels, maybeMoveBuild< Expression >(ctl), branches );
     101}
     102Statement *build_case( ExpressionNode *ctl ) {
     103        std::list< Statement * > branches;
     104        return new CaseStmt( noLabels, maybeMoveBuild< Expression >(ctl), branches );
     105}
     106Statement *build_default() {
     107        std::list< Statement * > branches;
     108        return new CaseStmt( noLabels, nullptr, branches, true );
     109}
     110
     111Statement *build_while( ExpressionNode *ctl, StatementNode *stmt, bool kind ) {
     112        std::list< Statement * > branches;
     113        buildMoveList< Statement, StatementNode >( stmt, branches );
     114        assert( branches.size() == 1 );
     115        return new WhileStmt( noLabels, notZeroExpr( maybeMoveBuild< Expression >(ctl) ), branches.front(), kind );
     116}
     117
     118Statement *build_for( ForCtl *forctl, StatementNode *stmt ) {
     119        std::list< Statement * > branches;
     120        buildMoveList< Statement, StatementNode >( stmt, branches );
     121        assert( branches.size() == 1 );
     122
     123        std::list< Statement * > init;
     124        if ( forctl->init != 0 ) {
     125                buildMoveList( forctl->init, init );
    105126        } // if
    106         return this;
    107 }
    108 
    109 StatementNode *StatementNode::append_block( StatementNode *stmt ) {
    110         if ( stmt != 0 ) {
    111                 if ( block == 0 )
    112                         block = stmt;
    113                 else
    114                         block->set_link( stmt );
    115         } // if
    116         return this;
    117 }
    118 
    119 StatementNode *StatementNode::append_last_case( StatementNode *stmt ) {
    120         if ( stmt != 0 ) {
    121                 StatementNode *next = ( StatementNode *)get_link();
    122                 if ( next && ( next->get_type() == StatementNode::Case || next->get_type() == StatementNode::Default ) )
    123                         next->append_last_case ( stmt );
    124                 else
    125                         if ( block == 0 )
    126                                 block = stmt;
    127                         else
    128                                 block->set_link( stmt );
    129         } // if
    130         return this;
    131 }
    132 
    133 void StatementNode::print( std::ostream &os, int indent ) const {
    134         if ( ! labels.empty() ) {
    135                 std::list<std::string>::const_iterator i;
    136 
    137                 os << string( indent, ' ' );
    138                 for ( i = labels.begin(); i != labels.end(); i++ )
    139                         os << *i << ":";
    140                 os << endl;
    141         } // if
    142 
    143         switch ( type ) {
    144           case Decl:
    145                 decl->print( os, indent );
    146                 break;
    147           case Exp:
    148                 if ( control ) {
    149                         os << string( indent, ' ' );
    150                         control->print( os, indent );
    151                         os << endl;
    152                 } else
    153                         os << string( indent, ' ' ) << "Null Statement" << endl;
    154                 break;
    155           default:
    156                 os << string( indent, ' ' ) << StatementNode::StType[type] << endl;
    157                 if ( type == Catch ) {
    158                         if ( decl ) {
    159                                 os << string( indent + ParseNode::indent_by, ' ' ) << "Declaration: " << endl;
    160                                 decl->print( os, indent + 2 * ParseNode::indent_by );
    161                         } else if ( isCatchRest ) {
    162                                 os << string( indent + ParseNode::indent_by, ' ' ) << "Catches the rest " << endl;
    163                         } else {
    164                                 ; // should never reach here
    165                         } // if
    166                 } // if
    167                 if ( control ) {
    168                         os << string( indent + ParseNode::indent_by, ' ' ) << "Control: " << endl;
    169                         control->printList( os, indent + 2 * ParseNode::indent_by );
    170                 } // if
    171                 if ( block ) {
    172                         os << string( indent + ParseNode::indent_by, ' ' ) << "Cases: " << endl;
    173                         block->printList( os, indent + 2 * ParseNode::indent_by );
    174                 } // if
    175                 if ( target ) {
    176                         os << string( indent + ParseNode::indent_by, ' ' ) << "Target: " << get_target() << endl;
    177                 } // if
    178                 break;
    179         } // switch
    180 }
    181 
    182 Statement *StatementNode::build() const {
    183         std::list<Statement *> branches;
    184         std::list<Expression *> exps;
    185         std::list<Label> labs;
    186 
    187         if ( ! labels.empty() ) {
    188                 std::back_insert_iterator< std::list<Label> > lab_it( labs );
    189                 copy( labels.begin(), labels.end(), lab_it );
    190         } // if
    191 
    192         // try {
    193         buildList<Statement, StatementNode>( get_block(), branches );
    194 
    195         switch ( type ) {
    196           case Decl:
    197                 return new DeclStmt( labs, maybeBuild< Declaration >( decl ) );
    198           case Exp:
    199                 {
    200                         Expression *e = maybeBuild< Expression >( get_control() );
    201 
    202                         if ( e )
    203                                 return new ExprStmt( labs, e );
    204                         else
    205                                 return new NullStmt( labs );
    206                 }
    207           case If:
    208                 {
    209                         Statement *thenb = 0, *elseb = 0;
    210                         assert( branches.size() >= 1 );
    211 
    212                         thenb = branches.front();
    213                         branches.pop_front();
    214                         if ( ! branches.empty() ) {
    215                                 elseb = branches.front();
    216                                 branches.pop_front();
    217                         } // if
    218                         return new IfStmt( labs, notZeroExpr( maybeBuild<Expression>(get_control()) ), thenb, elseb );
    219                 }
    220           case While:
    221                 assert( branches.size() == 1 );
    222                 return new WhileStmt( labs, notZeroExpr( maybeBuild<Expression>(get_control()) ), branches.front() );
    223           case Do:
    224                 assert( branches.size() == 1 );
    225                 return new WhileStmt( labs, notZeroExpr( maybeBuild<Expression>(get_control()) ), branches.front(), true );
    226           case For:
    227                 {
    228                         assert( branches.size() == 1 );
    229 
    230                         ForCtlExprNode *ctl = dynamic_cast<ForCtlExprNode *>( get_control() );
    231                         assert( ctl != 0 );
    232 
    233                         std::list<Statement *> init;
    234                         if ( ctl->get_init() != 0 ) {
    235                                 buildList( ctl->get_init(), init );
    236                         } // if
    237 
    238                         Expression *cond = 0;
    239                         if ( ctl->get_condition() != 0 )
    240                                 cond = notZeroExpr( maybeBuild<Expression>(ctl->get_condition()) );
    241 
    242                         Expression *incr = 0;
    243                         if ( ctl->get_change() != 0 )
    244                                 incr = maybeBuild<Expression>(ctl->get_change());
    245 
    246                         return new ForStmt( labs, init, cond, incr, branches.front() );
    247                 }
    248           case Switch:
    249                 return new SwitchStmt( labs, maybeBuild<Expression>(get_control()), branches );
    250           case Case:
    251                 return new CaseStmt( labs, maybeBuild<Expression>(get_control()), branches );
    252           case Default:
    253                 return new CaseStmt( labs, 0, branches, true );
    254           case Goto:
    255                 {
    256                         if ( get_target() == "" ) {                                     // computed goto
    257                                 assert( get_control() != 0 );
    258                                 return new BranchStmt( labs, maybeBuild<Expression>(get_control()), BranchStmt::Goto );
    259                         } // if
    260 
    261                         return new BranchStmt( labs, get_target(), BranchStmt::Goto );
    262                 }
    263           case Break:
    264                 return new BranchStmt( labs, get_target(), BranchStmt::Break );
    265           case Continue:
    266                 return new BranchStmt( labs, get_target(), BranchStmt::Continue );
    267           case Return:
    268           case Throw :
    269                 buildList( get_control(), exps );
    270                 if ( exps.size() ==0 )
    271                         return new ReturnStmt( labs, 0, type == Throw );
    272                 if ( exps.size() > 0 )
    273                         return new ReturnStmt( labs, exps.back(), type == Throw );
    274           case Try:
    275                 {
    276                         assert( branches.size() >= 0 );
    277                         CompoundStmt *tryBlock = dynamic_cast<CompoundStmt *>( branches.front());
    278                         branches.pop_front();
    279                         FinallyStmt *finallyBlock = 0;
    280                         if ( ( finallyBlock = dynamic_cast<FinallyStmt *>( branches.back())) ) {
    281                                 branches.pop_back();
    282                         } // if
    283                         return new TryStmt( labs, tryBlock, branches, finallyBlock );
    284                 }
    285           case Catch:
    286                 {
    287                         assert( branches.size() == 1 );
    288 
    289                         return new CatchStmt( labs, maybeBuild< Declaration >( decl ), branches.front(), isCatchRest );
    290                 }
    291           case Finally:
    292                 {
    293                         assert( branches.size() == 1 );
    294                         CompoundStmt *block = dynamic_cast<CompoundStmt *>( branches.front() );
    295                         assert( block != 0 );
    296 
    297                         return new FinallyStmt( labs, block );
    298                 }
    299           case Asm:
    300                 assert( false );
    301           default:
    302                 // shouldn't be here
    303                 return 0;
    304         } // switch
    305 }
    306 
    307 
    308 CompoundStmtNode::CompoundStmtNode() : first( 0 ), last( 0 ) {}
    309 
    310 CompoundStmtNode::CompoundStmtNode( const string *name_ ) : StatementNode( name_ ), first( 0 ), last( 0 ) {}
    311 
    312 CompoundStmtNode::CompoundStmtNode( StatementNode *stmt ) : first( stmt ) {
    313         if ( first ) {
    314                 last = ( StatementNode *)( stmt->get_last());
    315         } else {
    316                 last = 0;
    317         } // if
    318 }
    319 
    320 CompoundStmtNode::~CompoundStmtNode() {
    321         delete first;
    322 }
    323 
    324 void CompoundStmtNode::add_statement( StatementNode *stmt ) {
    325         if ( stmt != 0 ) {
    326                 last->set_link( stmt );
    327                 last = ( StatementNode *)( stmt->get_link());
    328         } // if
    329 }
    330 
    331 void CompoundStmtNode::print( ostream &os, int indent ) const {
    332         if ( first ) {
    333                 first->printList( os, indent+2 );
    334         } // if
    335 }
    336 
    337 Statement *CompoundStmtNode::build() const {
    338         std::list<Label> labs;
    339         const std::list<std::string> &labels = get_labels();
    340 
    341         if ( ! labels.empty() ) {
    342                 std::back_insert_iterator< std::list<Label> > lab_it( labs );
    343                 copy( labels.begin(), labels.end(), lab_it );
    344         } // if
    345 
    346         CompoundStmt *cs = new CompoundStmt( labs );
    347         buildList( first, cs->get_kids() );
     127
     128        Expression *cond = 0;
     129        if ( forctl->condition != 0 )
     130                cond = notZeroExpr( maybeMoveBuild< Expression >(forctl->condition) );
     131
     132        Expression *incr = 0;
     133        if ( forctl->change != 0 )
     134                incr = maybeMoveBuild< Expression >(forctl->change);
     135
     136        delete forctl;
     137        return new ForStmt( noLabels, init, cond, incr, branches.front() );
     138}
     139
     140Statement *build_branch( std::string identifier, BranchStmt::Type kind ) {
     141        return new BranchStmt( noLabels, identifier, kind );
     142}
     143Statement *build_computedgoto( ExpressionNode *ctl ) {
     144        return new BranchStmt( noLabels, maybeMoveBuild< Expression >(ctl), BranchStmt::Goto );
     145}
     146
     147Statement *build_return( ExpressionNode *ctl ) {
     148        std::list< Expression * > exps;
     149        buildMoveList( ctl, exps );
     150        return new ReturnStmt( noLabels, exps.size() > 0 ? exps.back() : nullptr );
     151}
     152Statement *build_throw( ExpressionNode *ctl ) {
     153        std::list< Expression * > exps;
     154        buildMoveList( ctl, exps );
     155        assertf( exps.size() < 2, "This means we are leaking memory");
     156        return new ReturnStmt( noLabels, !exps.empty() ? exps.back() : nullptr, true );
     157}
     158
     159Statement *build_try( StatementNode *try_stmt, StatementNode *catch_stmt, StatementNode *finally_stmt ) {
     160        std::list< Statement * > branches;
     161        buildMoveList< Statement, StatementNode >( catch_stmt, branches );
     162        CompoundStmt *tryBlock = dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >(try_stmt));
     163        assert( tryBlock );
     164        FinallyStmt *finallyBlock = dynamic_cast< FinallyStmt * >(maybeMoveBuild< Statement >(finally_stmt) );
     165        return new TryStmt( noLabels, tryBlock, branches, finallyBlock );
     166}
     167Statement *build_catch( DeclarationNode *decl, StatementNode *stmt, bool catchAny ) {
     168        std::list< Statement * > branches;
     169        buildMoveList< Statement, StatementNode >( stmt, branches );
     170        assert( branches.size() == 1 );
     171        return new CatchStmt( noLabels, maybeMoveBuild< Declaration >(decl), branches.front(), catchAny );
     172}
     173Statement *build_finally( StatementNode *stmt ) {
     174        std::list< Statement * > branches;
     175        buildMoveList< Statement, StatementNode >( stmt, branches );
     176        assert( branches.size() == 1 );
     177        return new FinallyStmt( noLabels, dynamic_cast< CompoundStmt * >( branches.front() ) );
     178}
     179
     180Statement *build_compound( StatementNode *first ) {
     181        CompoundStmt *cs = new CompoundStmt( noLabels );
     182        buildMoveList( first, cs->get_kids() );
    348183        return cs;
    349184}
    350185
    351 
    352 AsmStmtNode::AsmStmtNode( Type t, bool voltile, ConstantNode *instruction, ExpressionNode *output, ExpressionNode *input, ConstantNode *clobber, LabelNode *gotolabels ) :
    353         StatementNode( t ), voltile( voltile ), instruction( instruction ), output( output ), input( input ), clobber( clobber ) {
    354         if ( gotolabels ) {
    355                 this->gotolabels = gotolabels->get_labels();
    356                 delete gotolabels;
    357         } // if
    358 }
    359 
    360 AsmStmtNode::~AsmStmtNode() {
    361         delete instruction; delete output; delete input; delete clobber;
    362 }
    363 
    364 void AsmStmtNode::print( std::ostream &os, int indent ) const {
    365         StatementNode::print( os, indent );                                     // print statement labels
    366         os << string( indent + ParseNode::indent_by, ' ' ) << "volatile:" << voltile << endl;
    367         if ( instruction ) {
    368                 os << string( indent + ParseNode::indent_by, ' ' ) << "Instruction:" << endl;
    369                 instruction->printList( os, indent + 2 * ParseNode::indent_by );
    370         } // if
    371         if ( output ) {
    372                 os << string( indent + ParseNode::indent_by, ' ' ) << "Output:" << endl;
    373                 output->printList( os, indent + 2 * ParseNode::indent_by );
    374         } // if
    375         if ( input ) {
    376                 os << string( indent + ParseNode::indent_by, ' ' ) << "Input:" << endl;
    377                 input->printList( os, indent + 2 * ParseNode::indent_by );
    378         } // if
    379         if ( clobber ) {
    380                 os << string( indent + ParseNode::indent_by, ' ' ) << "Clobber:" << endl;
    381                 clobber->printList( os, indent + 2 * ParseNode::indent_by );
    382         } // if
    383         if ( ! gotolabels.empty() ) {
    384                 os << string( indent + ParseNode::indent_by, ' ' ) << "Goto Labels:" << endl;
    385                 os << string( indent + 2 * ParseNode::indent_by, ' ' );
    386                 for ( std::list<Label>::const_iterator i = gotolabels.begin();; ) {
    387                         os << *i;
    388                         i++;
    389                   if ( i == gotolabels.end() ) break;
    390                         os << ", ";
    391                 }
    392                 os << endl;
    393         } // if
    394 }
    395 
    396 Statement *AsmStmtNode::build() const {
    397         std::list<Label> labs;
    398 
    399         if ( ! get_labels().empty() ) {
    400                 std::back_insert_iterator< std::list<Label> > lab_it( labs );
    401                 copy( get_labels().begin(), get_labels().end(), lab_it );
    402         } // if
    403 
     186Statement *build_asmstmt( bool voltile, ConstantExpr *instruction, ExpressionNode *output, ExpressionNode *input, ExpressionNode *clobber, LabelNode *gotolabels ) {
    404187        std::list< Expression * > out, in;
    405188        std::list< ConstantExpr * > clob;
    406         buildList( output, out );
    407         buildList( input, in );
    408         buildList( clobber, clob );
    409         std::list< Label > gotolabs = gotolabels;
    410         return new AsmStmt( labs, voltile, (ConstantExpr *)maybeBuild< Expression >( instruction ), out, in, clob, gotolabs );
     189
     190        buildMoveList( output, out );
     191        buildMoveList( input, in );
     192        buildMoveList( clobber, clob );
     193        return new AsmStmt( noLabels, voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels );
    411194}
    412195
Note: See TracChangeset for help on using the changeset viewer.