Changes in / [39fea2f:47b5b63]


Ignore:
Location:
src
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    r39fea2f r47b5b63  
    7979        }
    8080
    81         /* Using updateLocation at the beginning of a node and nextLine
     81        /* Using updateLocation at the beginning of a node and endl
    8282         * within a node should become the method of formating.
    8383         */
    8484        void CodeGenerator::updateLocation( CodeLocation const & to ) {
    85                 if ( !lineMarks ) {
    86                         return;
    87                 } else if ( currentLocation.followedBy( to, 0 ) ) {
     85                // skip if linemarks shouldn't appear or if codelocation is unset
     86                if ( !lineMarks || to.isUnset() ) return;
     87
     88                if ( currentLocation.followedBy( to, 0 ) ) {
    8889                        return;
    8990                } else if ( currentLocation.followedBy( to, 1 ) ) {
    9091                        output << "\n" << indent;
    91                         currentLocation.linenumber += 1;
     92                        currentLocation.first_line += 1;
    9293                } else if ( currentLocation.followedBy( to, 2 ) ) {
    9394                        output << "\n\n" << indent;
    94                         currentLocation.linenumber += 2;
    95                 } else {
    96                         output << "\n# " << to.linenumber << " \"" << to.filename
     95                        currentLocation.first_line += 2;
     96                } else {
     97                        output << "\n# " << to.first_line << " \"" << to.filename
    9798                               << "\"\n" << indent;
    9899                        currentLocation = to;
     
    105106        }
    106107
    107         void CodeGenerator::nextLine() {
    108                 if ( !lineMarks ) {
    109                         output << "\n" << indent << std::flush;
    110                 }
    111         }
    112 
    113         CodeGenerator::CodeGenerator( std::ostream & os, bool pretty, bool genC, bool lineMarks ) : indent( CodeGenerator::tabsize ), insideFunction( false ), output( os ), printLabels( *this ), pretty( pretty ), genC( genC ), lineMarks( lineMarks ) {}
     108        // replace endl
     109        ostream & CodeGenerator::LineEnder::operator()( ostream & os ) const {
     110                // if ( !cg.lineMarks ) {
     111                //      os << "\n" << cg.indent << std::flush;
     112                // }
     113                os << "\n" << std::flush;
     114                cg.currentLocation.first_line++;
     115                // os << "/* did endl; current loc is: " << cg.currentLocation.first_line << "*/";
     116                return os;
     117        }
     118
     119        CodeGenerator::CodeGenerator( std::ostream & os, bool pretty, bool genC, bool lineMarks ) : indent( CodeGenerator::tabsize ), output( os ), printLabels( *this ), pretty( pretty ), genC( genC ), lineMarks( lineMarks ), endl( *this ) {}
    114120
    115121        string CodeGenerator::mangleName( DeclarationWithType * decl ) {
     
    139145        } // CodeGenerator::genAttributes
    140146
     147        // *** BaseSyntaxNode
     148        void CodeGenerator::previsit( BaseSyntaxNode * node ) {
     149                // turn off automatic recursion for all nodes, to allow each visitor to
     150                // precisely control the order in which its children are visited.
     151                visit_children = false;
     152                updateLocation( node );
     153        }
     154
     155        // *** BaseSyntaxNode
     156        void CodeGenerator::postvisit( BaseSyntaxNode * node ) {
     157                std::stringstream ss;
     158                node->print( ss );
     159                assertf( false, "Unhandled node reached in CodeGenerator: %s", ss.str().c_str() );
     160        }
    141161
    142162        // *** Declarations
    143         void CodeGenerator::visit( FunctionDecl * functionDecl ) {
     163        void CodeGenerator::postvisit( FunctionDecl * functionDecl ) {
    144164                extension( functionDecl );
    145165                genAttributes( functionDecl->get_attributes() );
     
    152172                asmName( functionDecl );
    153173
    154                 // acceptAll( functionDecl->get_oldDecls(), *this );
    155174                if ( functionDecl->get_statements() ) {
    156                         functionDecl->get_statements()->accept( *this );
    157                 } // if
    158         }
    159 
    160         void CodeGenerator::visit( ObjectDecl * objectDecl ) {
     175                        functionDecl->get_statements()->accept( *visitor );
     176                } // if
     177        }
     178
     179        void CodeGenerator::postvisit( ObjectDecl * objectDecl ) {
    161180                if (objectDecl->get_name().empty() && genC ) {
    162181                        // only generate an anonymous name when generating C code, otherwise it clutters the output too much
     
    175194                if ( objectDecl->get_init() ) {
    176195                        output << " = ";
    177                         objectDecl->get_init()->accept( *this );
     196                        objectDecl->get_init()->accept( *visitor );
    178197                } // if
    179198
    180199                if ( objectDecl->get_bitfieldWidth() ) {
    181200                        output << ":";
    182                         objectDecl->get_bitfieldWidth()->accept( *this );
     201                        objectDecl->get_bitfieldWidth()->accept( *visitor );
    183202                } // if
    184203        }
     
    203222                        ++indent;
    204223                        for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end(); i++ ) {
    205                                 updateLocation( *i );
    206224                                output << indent;
    207                                 (*i)->accept( *this );
     225                                (*i)->accept( *visitor );
    208226                                output << ";" << endl;
    209227                        } // for
     
    215233        }
    216234
    217         void CodeGenerator::visit( StructDecl * structDecl ) {
     235        void CodeGenerator::postvisit( StructDecl * structDecl ) {
    218236                extension( structDecl );
    219237                handleAggregate( structDecl, "struct " );
    220238        }
    221239
    222         void CodeGenerator::visit( UnionDecl * unionDecl ) {
     240        void CodeGenerator::postvisit( UnionDecl * unionDecl ) {
    223241                extension( unionDecl );
    224242                handleAggregate( unionDecl, "union " );
    225243        }
    226244
    227         void CodeGenerator::visit( EnumDecl * enumDecl ) {
     245        void CodeGenerator::postvisit( EnumDecl * enumDecl ) {
    228246                extension( enumDecl );
    229                 updateLocation( enumDecl );
    230247                output << "enum ";
    231248                genAttributes( enumDecl->get_attributes() );
     
    242259                                ObjectDecl * obj = dynamic_cast< ObjectDecl* >( *i );
    243260                                assert( obj );
    244                                 updateLocation( obj );
    245261                                output << indent << mangleName( obj );
    246262                                if ( obj->get_init() ) {
    247263                                        output << " = ";
    248                                         obj->get_init()->accept( *this );
     264                                        obj->get_init()->accept( *visitor );
    249265                                } // if
    250266                                output << "," << endl;
     
    257273        }
    258274
    259         void CodeGenerator::visit( TraitDecl * traitDecl ) {
     275        void CodeGenerator::postvisit( TraitDecl * traitDecl ) {
    260276                assertf( ! genC, "TraitDecls should not reach code generation." );
    261277                extension( traitDecl );
     
    263279        }
    264280
    265         void CodeGenerator::visit( TypedefDecl * typeDecl ) {
     281        void CodeGenerator::postvisit( TypedefDecl * typeDecl ) {
    266282                assertf( ! genC, "Typedefs are removed and substituted in earlier passes." );
    267                 updateLocation( typeDecl );
    268283                output << "typedef ";
    269284                output << genType( typeDecl->get_base(), typeDecl->get_name(), pretty, genC ) << endl;
    270285        }
    271286
    272         void CodeGenerator::visit( TypeDecl * typeDecl ) {
     287        void CodeGenerator::postvisit( TypeDecl * typeDecl ) {
    273288                assertf( ! genC, "TypeDecls should not reach code generation." );
    274289                output << typeDecl->genTypeString() << " " << typeDecl->get_name();
     
    283298        }
    284299
    285         void CodeGenerator::visit( Designation * designation ) {
     300        void CodeGenerator::postvisit( Designation * designation ) {
    286301                std::list< Expression * > designators = designation->get_designators();
    287302                if ( designators.size() == 0 ) return;
     
    290305                                // if expression is a NameExpr or VariableExpr, then initializing aggregate member
    291306                                output << ".";
    292                                 des->accept( *this );
     307                                des->accept( *visitor );
    293308                        } else {
    294309                                // otherwise, it has to be a ConstantExpr or CastExpr, initializing array eleemnt
    295310                                output << "[";
    296                                 des->accept( *this );
     311                                des->accept( *visitor );
    297312                                output << "]";
    298313                        } // if
     
    301316        }
    302317
    303         void CodeGenerator::visit( SingleInit * init ) {
    304                 init->get_value()->accept( *this );
    305         }
    306 
    307         void CodeGenerator::visit( ListInit * init ) {
     318        void CodeGenerator::postvisit( SingleInit * init ) {
     319                init->get_value()->accept( *visitor );
     320        }
     321
     322        void CodeGenerator::postvisit( ListInit * init ) {
    308323                auto initBegin = init->begin();
    309324                auto initEnd = init->end();
     
    313328                output << "{ ";
    314329                for ( ; initBegin != initEnd && desigBegin != desigEnd; ) {
    315                         (*desigBegin)->accept( *this );
    316                         (*initBegin)->accept( *this );
     330                        (*desigBegin)->accept( *visitor );
     331                        (*initBegin)->accept( *visitor );
    317332                        ++initBegin, ++desigBegin;
    318333                        if ( initBegin != initEnd ) {
     
    324339        }
    325340
    326         void CodeGenerator::visit( __attribute__((unused)) ConstructorInit * init ){
     341        void CodeGenerator::postvisit( ConstructorInit * init ){
    327342                assertf( ! genC, "ConstructorInit nodes should not reach code generation." );
    328343                // pseudo-output for constructor/destructor pairs
    329                 output << "<ctorinit>{" << std::endl << ++indent << "ctor: ";
    330                 maybeAccept( init->get_ctor(), *this );
    331                 output << ", " << std::endl << indent << "dtor: ";
    332                 maybeAccept( init->get_dtor(), *this );
    333                 output << std::endl << --indent << "}";
    334         }
    335 
    336         void CodeGenerator::visit( Constant * constant ) {
     344                output << "<ctorinit>{" << endl << ++indent << "ctor: ";
     345                maybeAccept( init->get_ctor(), *visitor );
     346                output << ", " << endl << indent << "dtor: ";
     347                maybeAccept( init->get_dtor(), *visitor );
     348                output << endl << --indent << "}";
     349        }
     350
     351        void CodeGenerator::postvisit( Constant * constant ) {
    337352                output << constant->get_value() ;
    338353        }
    339354
    340355        // *** Expressions
    341         void CodeGenerator::visit( ApplicationExpr * applicationExpr ) {
     356        void CodeGenerator::postvisit( ApplicationExpr * applicationExpr ) {
    342357                extension( applicationExpr );
    343358                if ( VariableExpr * varExpr = dynamic_cast< VariableExpr* >( applicationExpr->get_function() ) ) {
     
    348363                                  case OT_INDEX:
    349364                                        assert( applicationExpr->get_args().size() == 2 );
    350                                         (*arg++)->accept( *this );
     365                                        (*arg++)->accept( *visitor );
    351366                                        output << "[";
    352                                         (*arg)->accept( *this );
     367                                        (*arg)->accept( *visitor );
    353368                                        output << "]";
    354369                                        break;
     
    365380                                                // effects, so must still output this expression
    366381                                                output << "(";
    367                                                 (*arg++)->accept( *this );
     382                                                (*arg++)->accept( *visitor );
    368383                                                output << ") /* " << opInfo.inputName << " */";
    369384                                        } else if ( applicationExpr->get_args().size() == 2 ) {
    370385                                                // intrinsic two parameter constructors are essentially bitwise assignment
    371386                                                output << "(";
    372                                                 (*arg++)->accept( *this );
     387                                                (*arg++)->accept( *visitor );
    373388                                                output << opInfo.symbol;
    374                                                 (*arg)->accept( *this );
     389                                                (*arg)->accept( *visitor );
    375390                                                output << ") /* " << opInfo.inputName << " */";
    376391                                        } else {
     
    385400                                        output << "(";
    386401                                        output << opInfo.symbol;
    387                                         (*arg)->accept( *this );
     402                                        (*arg)->accept( *visitor );
    388403                                        output << ")";
    389404                                        break;
     
    392407                                  case OT_POSTFIXASSIGN:
    393408                                        assert( applicationExpr->get_args().size() == 1 );
    394                                         (*arg)->accept( *this );
     409                                        (*arg)->accept( *visitor );
    395410                                        output << opInfo.symbol;
    396411                                        break;
     
    401416                                        assert( applicationExpr->get_args().size() == 2 );
    402417                                        output << "(";
    403                                         (*arg++)->accept( *this );
     418                                        (*arg++)->accept( *visitor );
    404419                                        output << opInfo.symbol;
    405                                         (*arg)->accept( *this );
     420                                        (*arg)->accept( *visitor );
    406421                                        output << ")";
    407422                                        break;
     
    413428                                } // switch
    414429                        } else {
    415                                 varExpr->accept( *this );
     430                                varExpr->accept( *visitor );
    416431                                output << "(";
    417432                                genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
     
    419434                        } // if
    420435                } else {
    421                         applicationExpr->get_function()->accept( *this );
     436                        applicationExpr->get_function()->accept( *visitor );
    422437                        output << "(";
    423438                        genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
     
    426441        }
    427442
    428         void CodeGenerator::visit( UntypedExpr * untypedExpr ) {
     443        void CodeGenerator::postvisit( UntypedExpr * untypedExpr ) {
    429444                extension( untypedExpr );
    430445                if ( NameExpr * nameExpr = dynamic_cast< NameExpr* >( untypedExpr->get_function() ) ) {
     
    435450                                  case OT_INDEX:
    436451                                        assert( untypedExpr->get_args().size() == 2 );
    437                                         (*arg++)->accept( *this );
     452                                        (*arg++)->accept( *visitor );
    438453                                        output << "[";
    439                                         (*arg)->accept( *this );
     454                                        (*arg)->accept( *visitor );
    440455                                        output << "]";
    441456                                        break;
     
    450465                                                // effects, so must still output this expression
    451466                                                output << "(";
    452                                                 (*arg++)->accept( *this );
     467                                                (*arg++)->accept( *visitor );
    453468                                                output << ") /* " << opInfo.inputName << " */";
    454469                                        } else if ( untypedExpr->get_args().size() == 2 ) {
    455470                                                // intrinsic two parameter constructors are essentially bitwise assignment
    456471                                                output << "(";
    457                                                 (*arg++)->accept( *this );
     472                                                (*arg++)->accept( *visitor );
    458473                                                output << opInfo.symbol;
    459                                                 (*arg)->accept( *this );
     474                                                (*arg)->accept( *visitor );
    460475                                                output << ") /* " << opInfo.inputName << " */";
    461476                                        } else {
    462477                                                // no constructors with 0 or more than 2 parameters
    463                                                 assert( false );
     478                                                assertf( ! genC, "UntypedExpr constructor/destructor with 0 or more than 2 parameters." );
     479                                                output << "(";
     480                                                (*arg++)->accept( *visitor );
     481                                                output << opInfo.symbol << "{ ";
     482                                                genCommaList( arg, untypedExpr->get_args().end() );
     483                                                output << "}) /* " << opInfo.inputName << " */";
    464484                                        } // if
    465485                                        break;
     
    471491                                        output << "(";
    472492                                        output << opInfo.symbol;
    473                                         (*arg)->accept( *this );
     493                                        (*arg)->accept( *visitor );
    474494                                        output << ")";
    475495                                        break;
     
    478498                                  case OT_POSTFIXASSIGN:
    479499                                        assert( untypedExpr->get_args().size() == 1 );
    480                                         (*arg)->accept( *this );
     500                                        (*arg)->accept( *visitor );
    481501                                        output << opInfo.symbol;
    482502                                        break;
     
    486506                                        assert( untypedExpr->get_args().size() == 2 );
    487507                                        output << "(";
    488                                         (*arg++)->accept( *this );
     508                                        (*arg++)->accept( *visitor );
    489509                                        output << opInfo.symbol;
    490                                         (*arg)->accept( *this );
     510                                        (*arg)->accept( *visitor );
    491511                                        output << ")";
    492512                                        break;
     
    499519                                if ( nameExpr->get_name() == "..." ) { // case V1 ... V2 or case V1~V2
    500520                                        assert( untypedExpr->get_args().size() == 2 );
    501                                         (*untypedExpr->get_args().begin())->accept( *this );
     521                                        (*untypedExpr->get_args().begin())->accept( *visitor );
    502522                                        output << " ... ";
    503                                         (*--untypedExpr->get_args().end())->accept( *this );
     523                                        (*--untypedExpr->get_args().end())->accept( *visitor );
    504524                                } else {                                                                // builtin routines
    505                                         nameExpr->accept( *this );
     525                                        nameExpr->accept( *visitor );
    506526                                        output << "(";
    507527                                        genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
     
    510530                        } // if
    511531                } else {
    512                         untypedExpr->get_function()->accept( *this );
     532                        untypedExpr->get_function()->accept( *visitor );
    513533                        output << "(";
    514534                        genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
     
    517537        }
    518538
    519         void CodeGenerator::visit( RangeExpr * rangeExpr ) {
    520                 rangeExpr->get_low()->accept( *this );
     539        void CodeGenerator::postvisit( RangeExpr * rangeExpr ) {
     540                rangeExpr->get_low()->accept( *visitor );
    521541                output << " ... ";
    522                 rangeExpr->get_high()->accept( *this );
    523         }
    524 
    525         void CodeGenerator::visit( NameExpr * nameExpr ) {
     542                rangeExpr->get_high()->accept( *visitor );
     543        }
     544
     545        void CodeGenerator::postvisit( NameExpr * nameExpr ) {
    526546                extension( nameExpr );
    527547                OperatorInfo opInfo;
     
    534554        }
    535555
    536         void CodeGenerator::visit( AddressExpr * addressExpr ) {
     556        void CodeGenerator::postvisit( AddressExpr * addressExpr ) {
    537557                extension( addressExpr );
    538558                output << "(&";
    539                 addressExpr->arg->accept( *this );
     559                addressExpr->arg->accept( *visitor );
    540560                output << ")";
    541561        }
    542562
    543         void CodeGenerator::visit( LabelAddressExpr *addressExpr ) {
     563        void CodeGenerator::postvisit( LabelAddressExpr *addressExpr ) {
    544564                extension( addressExpr );
    545565                output << "(&&" << addressExpr->arg << ")";
    546566        }
    547567
    548         void CodeGenerator::visit( CastExpr * castExpr ) {
     568        void CodeGenerator::postvisit( CastExpr * castExpr ) {
    549569                extension( castExpr );
    550570                output << "(";
     
    559579                        output << ")";
    560580                } // if
    561                 castExpr->get_arg()->accept( *this );
     581                castExpr->get_arg()->accept( *visitor );
    562582                output << ")";
    563583        }
    564584
    565         void CodeGenerator::visit( VirtualCastExpr * castExpr ) {
     585        void CodeGenerator::postvisit( VirtualCastExpr * castExpr ) {
    566586                assertf( ! genC, "VirtualCastExpr should not reach code generation." );
    567587                extension( castExpr );
    568588                output << "(virtual ";
    569                 castExpr->get_arg()->accept( *this );
     589                castExpr->get_arg()->accept( *visitor );
    570590                output << ")";
    571591        }
    572592
    573         void CodeGenerator::visit( UntypedMemberExpr * memberExpr ) {
     593        void CodeGenerator::postvisit( UntypedMemberExpr * memberExpr ) {
    574594                assertf( ! genC, "UntypedMemberExpr should not reach code generation." );
    575595                extension( memberExpr );
    576                 memberExpr->get_aggregate()->accept( *this );
     596                memberExpr->get_aggregate()->accept( *visitor );
    577597                output << ".";
    578                 memberExpr->get_member()->accept( *this );
    579         }
    580 
    581         void CodeGenerator::visit( MemberExpr * memberExpr ) {
     598                memberExpr->get_member()->accept( *visitor );
     599        }
     600
     601        void CodeGenerator::postvisit( MemberExpr * memberExpr ) {
    582602                extension( memberExpr );
    583                 memberExpr->get_aggregate()->accept( *this );
     603                memberExpr->get_aggregate()->accept( *visitor );
    584604                output << "." << mangleName( memberExpr->get_member() );
    585605        }
    586606
    587         void CodeGenerator::visit( VariableExpr * variableExpr ) {
     607        void CodeGenerator::postvisit( VariableExpr * variableExpr ) {
    588608                extension( variableExpr );
    589609                OperatorInfo opInfo;
     
    595615        }
    596616
    597         void CodeGenerator::visit( ConstantExpr * constantExpr ) {
     617        void CodeGenerator::postvisit( ConstantExpr * constantExpr ) {
    598618                assert( constantExpr->get_constant() );
    599619                extension( constantExpr );
    600                 constantExpr->get_constant()->accept( *this );
    601         }
    602 
    603         void CodeGenerator::visit( SizeofExpr * sizeofExpr ) {
     620                constantExpr->get_constant()->accept( *visitor );
     621        }
     622
     623        void CodeGenerator::postvisit( SizeofExpr * sizeofExpr ) {
    604624                extension( sizeofExpr );
    605625                output << "sizeof(";
     
    607627                        output << genType( sizeofExpr->get_type(), "", pretty, genC );
    608628                } else {
    609                         sizeofExpr->get_expr()->accept( *this );
     629                        sizeofExpr->get_expr()->accept( *visitor );
    610630                } // if
    611631                output << ")";
    612632        }
    613633
    614         void CodeGenerator::visit( AlignofExpr * alignofExpr ) {
     634        void CodeGenerator::postvisit( AlignofExpr * alignofExpr ) {
    615635                // use GCC extension to avoid bumping std to C11
    616636                extension( alignofExpr );
     
    619639                        output << genType( alignofExpr->get_type(), "", pretty, genC );
    620640                } else {
    621                         alignofExpr->get_expr()->accept( *this );
     641                        alignofExpr->get_expr()->accept( *visitor );
    622642                } // if
    623643                output << ")";
    624644        }
    625645
    626         void CodeGenerator::visit( UntypedOffsetofExpr * offsetofExpr ) {
     646        void CodeGenerator::postvisit( UntypedOffsetofExpr * offsetofExpr ) {
    627647                assertf( ! genC, "UntypedOffsetofExpr should not reach code generation." );
    628648                output << "offsetof(";
     
    632652        }
    633653
    634         void CodeGenerator::visit( OffsetofExpr * offsetofExpr ) {
     654        void CodeGenerator::postvisit( OffsetofExpr * offsetofExpr ) {
    635655                // use GCC builtin
    636656                output << "__builtin_offsetof(";
     
    640660        }
    641661
    642         void CodeGenerator::visit( OffsetPackExpr * offsetPackExpr ) {
     662        void CodeGenerator::postvisit( OffsetPackExpr * offsetPackExpr ) {
    643663                assertf( ! genC, "OffsetPackExpr should not reach code generation." );
    644664                output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", pretty, genC ) << ")";
    645665        }
    646666
    647         void CodeGenerator::visit( LogicalExpr * logicalExpr ) {
     667        void CodeGenerator::postvisit( LogicalExpr * logicalExpr ) {
    648668                extension( logicalExpr );
    649669                output << "(";
    650                 logicalExpr->get_arg1()->accept( *this );
     670                logicalExpr->get_arg1()->accept( *visitor );
    651671                if ( logicalExpr->get_isAnd() ) {
    652672                        output << " && ";
     
    654674                        output << " || ";
    655675                } // if
    656                 logicalExpr->get_arg2()->accept( *this );
     676                logicalExpr->get_arg2()->accept( *visitor );
    657677                output << ")";
    658678        }
    659679
    660         void CodeGenerator::visit( ConditionalExpr * conditionalExpr ) {
     680        void CodeGenerator::postvisit( ConditionalExpr * conditionalExpr ) {
    661681                extension( conditionalExpr );
    662682                output << "(";
    663                 conditionalExpr->get_arg1()->accept( *this );
     683                conditionalExpr->get_arg1()->accept( *visitor );
    664684                output << " ? ";
    665                 conditionalExpr->get_arg2()->accept( *this );
     685                conditionalExpr->get_arg2()->accept( *visitor );
    666686                output << " : ";
    667                 conditionalExpr->get_arg3()->accept( *this );
     687                conditionalExpr->get_arg3()->accept( *visitor );
    668688                output << ")";
    669689        }
    670690
    671         void CodeGenerator::visit( CommaExpr * commaExpr ) {
     691        void CodeGenerator::postvisit( CommaExpr * commaExpr ) {
    672692                extension( commaExpr );
    673693                output << "(";
     
    676696                        commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) );
    677697                }
    678                 commaExpr->get_arg1()->accept( *this );
     698                commaExpr->get_arg1()->accept( *visitor );
    679699                output << " , ";
    680                 commaExpr->get_arg2()->accept( *this );
     700                commaExpr->get_arg2()->accept( *visitor );
    681701                output << ")";
    682702        }
    683703
    684         void CodeGenerator::visit( TupleAssignExpr * tupleExpr ) {
     704        void CodeGenerator::postvisit( TupleAssignExpr * tupleExpr ) {
    685705                assertf( ! genC, "TupleAssignExpr should not reach code generation." );
    686                 tupleExpr->stmtExpr->accept( *this );
    687         }
    688 
    689         void CodeGenerator::visit( UntypedTupleExpr * tupleExpr ) {
     706                tupleExpr->stmtExpr->accept( *visitor );
     707        }
     708
     709        void CodeGenerator::postvisit( UntypedTupleExpr * tupleExpr ) {
    690710                assertf( ! genC, "UntypedTupleExpr should not reach code generation." );
    691711                extension( tupleExpr );
     
    695715        }
    696716
    697         void CodeGenerator::visit( TupleExpr * tupleExpr ) {
     717        void CodeGenerator::postvisit( TupleExpr * tupleExpr ) {
    698718                assertf( ! genC, "TupleExpr should not reach code generation." );
    699719                extension( tupleExpr );
     
    703723        }
    704724
    705         void CodeGenerator::visit( TupleIndexExpr * tupleExpr ) {
     725        void CodeGenerator::postvisit( TupleIndexExpr * tupleExpr ) {
    706726                assertf( ! genC, "TupleIndexExpr should not reach code generation." );
    707727                extension( tupleExpr );
    708                 tupleExpr->get_tuple()->accept( *this );
     728                tupleExpr->get_tuple()->accept( *visitor );
    709729                output << "." << tupleExpr->get_index();
    710730        }
    711731
    712         void CodeGenerator::visit( TypeExpr * typeExpr ) {
     732        void CodeGenerator::postvisit( TypeExpr * typeExpr ) {
    713733                // if ( genC ) std::cerr << "typeexpr still exists: " << typeExpr << std::endl;
    714734                // assertf( ! genC, "TypeExpr should not reach code generation." );
     
    718738        }
    719739
    720         void CodeGenerator::visit( AsmExpr * asmExpr ) {
     740        void CodeGenerator::postvisit( AsmExpr * asmExpr ) {
    721741                if ( asmExpr->get_inout() ) {
    722742                        output << "[ ";
    723                         asmExpr->get_inout()->accept( *this );
     743                        asmExpr->get_inout()->accept( *visitor );
    724744                        output << " ] ";
    725745                } // if
    726                 asmExpr->get_constraint()->accept( *this );
     746                asmExpr->get_constraint()->accept( *visitor );
    727747                output << " ( ";
    728                 asmExpr->get_operand()->accept( *this );
     748                asmExpr->get_operand()->accept( *visitor );
    729749                output << " )";
    730750        }
    731751
    732         void CodeGenerator::visit( CompoundLiteralExpr *compLitExpr ) {
     752        void CodeGenerator::postvisit( CompoundLiteralExpr *compLitExpr ) {
    733753                assert( compLitExpr->get_result() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) );
    734754                output << "(" << genType( compLitExpr->get_result(), "", pretty, genC ) << ")";
    735                 compLitExpr->get_initializer()->accept( *this );
    736         }
    737 
    738         void CodeGenerator::visit( UniqueExpr * unqExpr ) {
     755                compLitExpr->get_initializer()->accept( *visitor );
     756        }
     757
     758        void CodeGenerator::postvisit( UniqueExpr * unqExpr ) {
    739759                assertf( ! genC, "Unique expressions should not reach code generation." );
    740760                output << "unq<" << unqExpr->get_id() << ">{ ";
    741                 unqExpr->get_expr()->accept( *this );
     761                unqExpr->get_expr()->accept( *visitor );
    742762                output << " }";
    743763        }
    744764
    745         void CodeGenerator::visit( StmtExpr * stmtExpr ) {
     765        void CodeGenerator::postvisit( StmtExpr * stmtExpr ) {
    746766                std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
    747                 updateLocation( stmtExpr );
    748                 output << "({" << std::endl;
     767                output << "({" << endl;
    749768                ++indent;
    750769                unsigned int numStmts = stmts.size();
    751770                unsigned int i = 0;
    752771                for ( Statement * stmt : stmts ) {
    753                         updateLocation( stmt );
    754772                        output << indent << printLabels( stmt->get_labels() );
    755773                        if ( i+1 == numStmts ) {
     
    757775                                // cannot cast to void, otherwise the expression statement has no value
    758776                                if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
    759                                         exprStmt->get_expr()->accept( *this );
     777                                        exprStmt->get_expr()->accept( *visitor );
    760778                                        output << ";" << endl;
    761779                                        ++i;
     
    763781                                }
    764782                        }
    765                         stmt->accept( *this );
     783                        stmt->accept( *visitor );
    766784                        output << endl;
    767785                        if ( wantSpacing( stmt ) ) {
     
    774792        }
    775793
     794        void CodeGenerator::postvisit( ConstructorExpr * expr ) {
     795                assertf( ! genC, "Unique expressions should not reach code generation." );
     796                expr->callExpr->accept( *visitor );
     797        }
     798
    776799        // *** Statements
    777         void CodeGenerator::visit( CompoundStmt * compoundStmt ) {
     800        void CodeGenerator::postvisit( CompoundStmt * compoundStmt ) {
    778801                std::list<Statement*> ks = compoundStmt->get_kids();
    779802                output << "{" << endl;
     
    783806                for ( std::list<Statement *>::iterator i = ks.begin(); i != ks.end();  i++ ) {
    784807                        output << indent << printLabels( (*i)->get_labels() );
    785                         (*i)->accept( *this );
     808                        (*i)->accept( *visitor );
    786809
    787810                        output << endl;
     
    795818        }
    796819
    797         void CodeGenerator::visit( ExprStmt * exprStmt ) {
     820        void CodeGenerator::postvisit( ExprStmt * exprStmt ) {
    798821                assert( exprStmt );
    799822                if ( genC ) {
     
    801824                        exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) );
    802825                }
    803                 exprStmt->get_expr()->accept( *this );
     826                exprStmt->get_expr()->accept( *visitor );
    804827                output << ";";
    805828        }
    806829
    807         void CodeGenerator::visit( AsmStmt * asmStmt ) {
     830        void CodeGenerator::postvisit( AsmStmt * asmStmt ) {
    808831                output << "asm ";
    809832                if ( asmStmt->get_voltile() ) output << "volatile ";
    810833                if ( ! asmStmt->get_gotolabels().empty()  ) output << "goto ";
    811834                output << "( ";
    812                 if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *this );
     835                if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *visitor );
    813836                output << " : ";
    814837                genCommaList( asmStmt->get_output().begin(), asmStmt->get_output().end() );
     
    828851        }
    829852
    830         void CodeGenerator::visit( AsmDecl * asmDecl ) {
     853        void CodeGenerator::postvisit( AsmDecl * asmDecl ) {
    831854                output << "asm ";
    832855                AsmStmt * asmStmt = asmDecl->get_stmt();
    833856                output << "( ";
    834                 if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *this );
     857                if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *visitor );
    835858                output << " )" ;
    836859        }
    837860
    838         void CodeGenerator::visit( IfStmt * ifStmt ) {
    839                 updateLocation( ifStmt );
     861        void CodeGenerator::postvisit( IfStmt * ifStmt ) {
    840862                output << "if ( ";
    841                 ifStmt->get_condition()->accept( *this );
     863                ifStmt->get_condition()->accept( *visitor );
    842864                output << " ) ";
    843865
    844                 ifStmt->get_thenPart()->accept( *this );
     866                ifStmt->get_thenPart()->accept( *visitor );
    845867
    846868                if ( ifStmt->get_elsePart() != 0) {
    847869                        output << " else ";
    848                         ifStmt->get_elsePart()->accept( *this );
    849                 } // if
    850         }
    851 
    852         void CodeGenerator::visit( SwitchStmt * switchStmt ) {
    853                 updateLocation( switchStmt );
     870                        ifStmt->get_elsePart()->accept( *visitor );
     871                } // if
     872        }
     873
     874        void CodeGenerator::postvisit( SwitchStmt * switchStmt ) {
    854875                output << "switch ( " ;
    855                 switchStmt->get_condition()->accept( *this );
     876                switchStmt->get_condition()->accept( *visitor );
    856877                output << " ) ";
    857878
    858                 output << "{" << std::endl;
     879                output << "{" << endl;
    859880                ++indent;
    860                 acceptAll( switchStmt->get_statements(), *this );
     881                acceptAll( switchStmt->get_statements(), *visitor );
    861882                --indent;
    862883                output << indent << "}";
    863884        }
    864885
    865         void CodeGenerator::visit( CaseStmt * caseStmt ) {
    866                 updateLocation( caseStmt );
     886        void CodeGenerator::postvisit( CaseStmt * caseStmt ) {
    867887                if ( caseStmt->isDefault()) {
    868888                        output << "default";
    869889                } else {
    870890                        output << "case ";
    871                         caseStmt->get_condition()->accept( *this );
    872                 } // if
    873                 output << ":\n";
     891                        caseStmt->get_condition()->accept( *visitor );
     892                } // if
     893                output << ":" << endl;
    874894
    875895                std::list<Statement *> sts = caseStmt->get_statements();
     
    878898                for ( std::list<Statement *>::iterator i = sts.begin(); i != sts.end();  i++) {
    879899                        output << indent << printLabels( (*i)->get_labels() )  ;
    880                         (*i)->accept( *this );
     900                        (*i)->accept( *visitor );
    881901                        output << endl;
    882902                } // for
     
    884904        }
    885905
    886         void CodeGenerator::visit( BranchStmt * branchStmt ) {
     906        void CodeGenerator::postvisit( BranchStmt * branchStmt ) {
    887907                switch ( branchStmt->get_type()) {
    888908                  case BranchStmt::Goto:
     
    892912                                if ( branchStmt->get_computedTarget() != 0 ) {
    893913                                        output << "goto *";
    894                                         branchStmt->get_computedTarget()->accept( *this );
     914                                        branchStmt->get_computedTarget()->accept( *visitor );
    895915                                } // if
    896916                        } // if
     
    906926        }
    907927
    908         void CodeGenerator::visit( ReturnStmt * returnStmt ) {
     928        void CodeGenerator::postvisit( ReturnStmt * returnStmt ) {
    909929                output << "return ";
    910                 maybeAccept( returnStmt->get_expr(), *this );
     930                maybeAccept( returnStmt->get_expr(), *visitor );
    911931                output << ";";
    912932        }
    913933
    914         void CodeGenerator::visit( ThrowStmt * throwStmt ) {
     934        void CodeGenerator::postvisit( ThrowStmt * throwStmt ) {
    915935                assertf( ! genC, "Throw statements should not reach code generation." );
    916936
     
    919939                if (throwStmt->get_expr()) {
    920940                        output << " ";
    921                         throwStmt->get_expr()->accept( *this );
     941                        throwStmt->get_expr()->accept( *visitor );
    922942                }
    923943                if (throwStmt->get_target()) {
    924944                        output << " _At ";
    925                         throwStmt->get_target()->accept( *this );
     945                        throwStmt->get_target()->accept( *visitor );
    926946                }
    927947                output << ";";
    928948        }
    929949
    930         void CodeGenerator::visit( WhileStmt * whileStmt ) {
     950        void CodeGenerator::postvisit( WhileStmt * whileStmt ) {
    931951                if ( whileStmt->get_isDoWhile() ) {
    932952                        output << "do" ;
    933953                } else {
    934954                        output << "while (" ;
    935                         whileStmt->get_condition()->accept( *this );
     955                        whileStmt->get_condition()->accept( *visitor );
    936956                        output << ")";
    937957                } // if
     
    939959
    940960                output << CodeGenerator::printLabels( whileStmt->get_body()->get_labels() );
    941                 whileStmt->get_body()->accept( *this );
     961                whileStmt->get_body()->accept( *visitor );
    942962
    943963                output << indent;
     
    945965                if ( whileStmt->get_isDoWhile() ) {
    946966                        output << " while (" ;
    947                         whileStmt->get_condition()->accept( *this );
     967                        whileStmt->get_condition()->accept( *visitor );
    948968                        output << ");";
    949969                } // if
    950970        }
    951971
    952         void CodeGenerator::visit( ForStmt * forStmt ) {
     972        void CodeGenerator::postvisit( ForStmt * forStmt ) {
    953973                // initialization is always hoisted, so don't bother doing anything with that
    954974                output << "for (;";
    955975
    956976                if ( forStmt->get_condition() != 0 ) {
    957                         forStmt->get_condition()->accept( *this );
     977                        forStmt->get_condition()->accept( *visitor );
    958978                } // if
    959979                output << ";";
     
    962982                        // cast the top-level expression to void to reduce gcc warnings.
    963983                        Expression * expr = new CastExpr( forStmt->get_increment() );
    964                         expr->accept( *this );
     984                        expr->accept( *visitor );
    965985                } // if
    966986                output << ") ";
     
    968988                if ( forStmt->get_body() != 0 ) {
    969989                        output << CodeGenerator::printLabels( forStmt->get_body()->get_labels() );
    970                         forStmt->get_body()->accept( *this );
    971                 } // if
    972         }
    973 
    974         void CodeGenerator::visit( __attribute__((unused)) NullStmt * nullStmt ) {
     990                        forStmt->get_body()->accept( *visitor );
     991                } // if
     992        }
     993
     994        void CodeGenerator::postvisit( __attribute__((unused)) NullStmt * nullStmt ) {
    975995                //output << indent << CodeGenerator::printLabels( nullStmt->get_labels() );
    976996                output << "/* null statement */ ;";
    977997        }
    978998
    979         void CodeGenerator::visit( DeclStmt * declStmt ) {
    980                 declStmt->get_decl()->accept( *this );
     999        void CodeGenerator::postvisit( DeclStmt * declStmt ) {
     1000                declStmt->get_decl()->accept( *visitor );
    9811001
    9821002                if ( doSemicolon( declStmt->get_decl() ) ) {
    9831003                        output << ";";
    9841004                } // if
     1005        }
     1006
     1007        void CodeGenerator::postvisit( ImplicitCtorDtorStmt * stmt ) {
     1008                assertf( ! genC, "ImplicitCtorDtorStmts should not reach code generation." );
     1009                stmt->callStmt->accept( *visitor );
    9851010        }
    9861011
  • src/CodeGen/CodeGenerator.h

    r39fea2f r47b5b63  
    2121
    2222#include "Common/Indenter.h"      // for Indenter
     23#include "Common/PassVisitor.h"   // for PassVisitor
    2324#include "SynTree/Declaration.h"  // for DeclarationWithType (ptr only), Fun...
    2425#include "SynTree/Visitor.h"      // for Visitor
     
    2627
    2728namespace CodeGen {
    28         class CodeGenerator : public Visitor {
    29           public:
    30                 static int tabsize;
     29        struct CodeGenerator : public WithShortCircuiting, public WithVisitorRef<CodeGenerator> {
     30          static int tabsize;
    3131
    3232                CodeGenerator( std::ostream &os, bool pretty = false, bool genC = false, bool lineMarks = false );
    33                 CodeGenerator( std::ostream &os, std::string, int indent = 0, bool infun = false );
    34                 CodeGenerator( std::ostream &os, char *, int indent = 0, bool infun = false );
     33
     34                //*** Turn off visit_children for all nodes
     35                void previsit( BaseSyntaxNode * );
     36
     37                //*** Error for unhandled node types
     38                void postvisit( BaseSyntaxNode * );
    3539
    3640                //*** Declaration
    37                 virtual void visit( StructDecl * );
    38                 virtual void visit( FunctionDecl * );
    39                 virtual void visit( ObjectDecl * );
    40                 virtual void visit( UnionDecl *aggregateDecl );
    41                 virtual void visit( EnumDecl *aggregateDecl );
    42                 virtual void visit( TraitDecl *aggregateDecl );
    43                 virtual void visit( TypedefDecl *typeDecl );
    44                 virtual void visit( TypeDecl *typeDecl );
     41                void postvisit( StructDecl * );
     42                void postvisit( FunctionDecl * );
     43                void postvisit( ObjectDecl * );
     44                void postvisit( UnionDecl *aggregateDecl );
     45                void postvisit( EnumDecl *aggregateDecl );
     46                void postvisit( TraitDecl *aggregateDecl );
     47                void postvisit( TypedefDecl *typeDecl );
     48                void postvisit( TypeDecl *typeDecl );
    4549
    4650                //*** Initializer
    47                 virtual void visit( Designation * );
    48                 virtual void visit( SingleInit * );
    49                 virtual void visit( ListInit * );
    50                 virtual void visit( ConstructorInit * );
     51                void postvisit( Designation * );
     52                void postvisit( SingleInit * );
     53                void postvisit( ListInit * );
     54                void postvisit( ConstructorInit * );
    5155
    5256                //*** Constant
    53                 virtual void visit( Constant * );
     57                void postvisit( Constant * );
    5458
    5559                //*** Expression
    56                 virtual void visit( ApplicationExpr *applicationExpr );
    57                 virtual void visit( UntypedExpr *untypedExpr );
    58                 virtual void visit( RangeExpr * rangeExpr );
    59                 virtual void visit( NameExpr *nameExpr );
    60                 virtual void visit( AddressExpr *addressExpr );
    61                 virtual void visit( LabelAddressExpr *addressExpr );
    62                 virtual void visit( CastExpr *castExpr );
    63                 virtual void visit( VirtualCastExpr *castExpr );
    64                 virtual void visit( UntypedMemberExpr *memberExpr );
    65                 virtual void visit( MemberExpr *memberExpr );
    66                 virtual void visit( VariableExpr *variableExpr );
    67                 virtual void visit( ConstantExpr *constantExpr );
    68                 virtual void visit( SizeofExpr *sizeofExpr );
    69                 virtual void visit( AlignofExpr *alignofExpr );
    70                 virtual void visit( UntypedOffsetofExpr *offsetofExpr );
    71                 virtual void visit( OffsetofExpr *offsetofExpr );
    72                 virtual void visit( OffsetPackExpr *offsetPackExpr );
    73                 virtual void visit( LogicalExpr *logicalExpr );
    74                 virtual void visit( ConditionalExpr *conditionalExpr );
    75                 virtual void visit( CommaExpr *commaExpr );
    76                 virtual void visit( CompoundLiteralExpr *compLitExpr );
    77                 virtual void visit( UniqueExpr * );
    78                 virtual void visit( TupleAssignExpr * tupleExpr );
    79                 virtual void visit( UntypedTupleExpr *tupleExpr );
    80                 virtual void visit( TupleExpr *tupleExpr );
    81                 virtual void visit( TupleIndexExpr * tupleExpr );
    82                 virtual void visit( TypeExpr *typeExpr );
    83                 virtual void visit( AsmExpr * );
    84                 virtual void visit( StmtExpr * );
     60                void postvisit( ApplicationExpr *applicationExpr );
     61                void postvisit( UntypedExpr *untypedExpr );
     62                void postvisit( RangeExpr * rangeExpr );
     63                void postvisit( NameExpr *nameExpr );
     64                void postvisit( AddressExpr *addressExpr );
     65                void postvisit( LabelAddressExpr *addressExpr );
     66                void postvisit( CastExpr *castExpr );
     67                void postvisit( VirtualCastExpr *castExpr );
     68                void postvisit( UntypedMemberExpr *memberExpr );
     69                void postvisit( MemberExpr *memberExpr );
     70                void postvisit( VariableExpr *variableExpr );
     71                void postvisit( ConstantExpr *constantExpr );
     72                void postvisit( SizeofExpr *sizeofExpr );
     73                void postvisit( AlignofExpr *alignofExpr );
     74                void postvisit( UntypedOffsetofExpr *offsetofExpr );
     75                void postvisit( OffsetofExpr *offsetofExpr );
     76                void postvisit( OffsetPackExpr *offsetPackExpr );
     77                void postvisit( LogicalExpr *logicalExpr );
     78                void postvisit( ConditionalExpr *conditionalExpr );
     79                void postvisit( CommaExpr *commaExpr );
     80                void postvisit( CompoundLiteralExpr *compLitExpr );
     81                void postvisit( UniqueExpr * );
     82                void postvisit( TupleAssignExpr * tupleExpr );
     83                void postvisit( UntypedTupleExpr *tupleExpr );
     84                void postvisit( TupleExpr *tupleExpr );
     85                void postvisit( TupleIndexExpr * tupleExpr );
     86                void postvisit( TypeExpr *typeExpr );
     87                void postvisit( AsmExpr * );
     88                void postvisit( StmtExpr * );
     89                void postvisit( ConstructorExpr * );
    8590
    8691                //*** Statements
    87                 virtual void visit( CompoundStmt * );
    88                 virtual void visit( ExprStmt * );
    89                 virtual void visit( AsmStmt * );
    90                 virtual void visit( AsmDecl * );                                // special: statement in declaration context
    91                 virtual void visit( IfStmt * );
    92                 virtual void visit( SwitchStmt * );
    93                 virtual void visit( CaseStmt * );
    94                 virtual void visit( BranchStmt * );
    95                 virtual void visit( ReturnStmt * );
    96                 virtual void visit( ThrowStmt * );
    97                 virtual void visit( WhileStmt * );
    98                 virtual void visit( ForStmt * );
    99                 virtual void visit( NullStmt * );
    100                 virtual void visit( DeclStmt * );
     92                void postvisit( CompoundStmt * );
     93                void postvisit( ExprStmt * );
     94                void postvisit( AsmStmt * );
     95                void postvisit( AsmDecl * );                            // special: statement in declaration context
     96                void postvisit( IfStmt * );
     97                void postvisit( SwitchStmt * );
     98                void postvisit( CaseStmt * );
     99                void postvisit( BranchStmt * );
     100                void postvisit( ReturnStmt * );
     101                void postvisit( ThrowStmt * );
     102                void postvisit( WhileStmt * );
     103                void postvisit( ForStmt * );
     104                void postvisit( NullStmt * );
     105                void postvisit( DeclStmt * );
     106                void postvisit( ImplicitCtorDtorStmt * );
    101107
    102108                void genAttributes( std::list< Attribute * > & attributes );
     
    117123
    118124                void updateLocation( BaseSyntaxNode const * to );
     125                struct LineEnder {
     126                        CodeGenerator & cg;
     127                        LineEnder( CodeGenerator & cg ) : cg( cg ) {}
     128                        std::ostream & operator()(std::ostream &) const;
     129                };
    119130          private:
    120131                Indenter indent;
    121                 bool insideFunction;
    122                 std::ostream &output;
     132                std::ostream & output;
    123133                LabelPrinter printLabels;
    124134                bool pretty = false;  // pretty print
    125135                bool genC = false;    // true if output has to be C code
    126136                bool lineMarks = false;
     137        public:
     138                LineEnder endl;
     139        private:
    127140
    128141                CodeLocation currentLocation;
    129142                void updateLocation( CodeLocation const & to );
    130                 void nextLine();
    131143
    132144                void handleStorageClass( DeclarationWithType *decl );
     
    140152          if ( begin == end ) return;
    141153                for ( ;; ) {
    142                         (*begin++)->accept( *this );
     154                        (*begin++)->accept( *visitor );
    143155                  if ( begin == end ) break;
    144156                        output << ", ";                                                         // separator
     
    155167        /// returns C-compatible name of declaration
    156168        std::string genName( DeclarationWithType * decl );
     169
     170        inline std::ostream & operator<<( std::ostream & os, const CodeGenerator::LineEnder & endl ) {
     171                return endl( os );
     172        }
    157173} // namespace CodeGen
    158174
  • src/CodeGen/GenType.cc

    r39fea2f r47b5b63  
    6363
    6464                if ( ! type->get_attributes().empty() ) {
    65                         CodeGenerator cg( os, pretty, genC, lineMarks );
    66                         cg.genAttributes( type->get_attributes() );
     65                        PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
     66                        cg.pass.genAttributes( type->get_attributes() );
    6767                } // if
    6868
     
    116116                } // if
    117117                if ( dimension != 0 ) {
    118                         CodeGenerator cg( os, pretty, genC, lineMarks );
     118                        PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
    119119                        dimension->accept( cg );
    120120                } else if ( isVarLen ) {
     
    178178                        } // if
    179179                } else {
    180                         CodeGenerator cg( os, pretty, genC, lineMarks );
     180                        PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
    181181                        os << "(" ;
    182182
    183                         cg.genCommaList( pars.begin(), pars.end() );
     183                        cg.pass.genCommaList( pars.begin(), pars.end() );
    184184
    185185                        if ( funcType->get_isVarArgs() ) {
     
    201201                        // assertf( ! genC, "Aggregate type parameters should not reach code generation." );
    202202                        std::ostringstream os;
    203                         CodeGenerator cg( os, pretty, genC, lineMarks );
     203                        PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
    204204                        os << "forall(";
    205                         cg.genCommaList( funcType->get_forall().begin(), funcType->get_forall().end() );
     205                        cg.pass.genCommaList( funcType->get_forall().begin(), funcType->get_forall().end() );
    206206                        os << ")" << std::endl;
    207207                        typeString = os.str() + typeString;
     
    212212                if ( ! refType->get_parameters().empty() ) {
    213213                        std::ostringstream os;
    214                         CodeGenerator cg( os, pretty, genC, lineMarks );
     214                        PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
    215215                        os << "(";
    216                         cg.genCommaList( refType->get_parameters().begin(), refType->get_parameters().end() );
     216                        cg.pass.genCommaList( refType->get_parameters().begin(), refType->get_parameters().end() );
    217217                        os << ") ";
    218218                        return os.str();
  • src/CodeGen/Generate.cc

    r39fea2f r47b5b63  
    3333                /// Removes misc. nodes that should not exist in CodeGen
    3434                struct TreeCleaner {
    35                         void previsit( CompoundStmt * stmt );
     35                        void premutate( CompoundStmt * stmt );
     36                        Statement * postmutate( ImplicitCtorDtorStmt * stmt );
    3637
    3738                        static bool shouldClean( Declaration * );
     
    4142                        PassVisitor<TreeCleaner> cleaner;
    4243                        filter( translationUnit, [](Declaration * decl) { return TreeCleaner::shouldClean(decl); }, false );
    43                         acceptAll( translationUnit, cleaner );
     44                        mutateAll( translationUnit, cleaner );
    4445                } // cleanTree
    4546        } // namespace
     
    4849                cleanTree( translationUnit );
    4950
    50                 CodeGen::CodeGenerator cgv( os, pretty, generateC, lineMarks );
     51                PassVisitor<CodeGenerator> cgv( os, pretty, generateC, lineMarks );
    5152                for ( auto & dcl : translationUnit ) {
    5253                        if ( LinkageSpec::isGeneratable( dcl->get_linkage() ) && (doIntrinsics || ! LinkageSpec::isBuiltin( dcl->get_linkage() ) ) ) {
    53                                 cgv.updateLocation( dcl );
     54                                cgv.pass.updateLocation( dcl );
    5455                                dcl->accept(cgv);
    5556                                if ( doSemicolon( dcl ) ) {
    5657                                        os << ";";
    5758                                } // if
    58                                 os << std::endl;
     59                                os << cgv.pass.endl;
    5960                        } // if
    6061                } // for
     
    6566                        os << CodeGen::genPrettyType( type, "" );
    6667                } else {
    67                         CodeGen::CodeGenerator cgv( os, true, false, false );
     68                        PassVisitor<CodeGenerator> cgv( os, true, false, false );
    6869                        node->accept( cgv );
    6970                }
     
    7273
    7374        namespace {
    74                 void TreeCleaner::previsit( CompoundStmt * cstmt ) {
     75                void TreeCleaner::premutate( CompoundStmt * cstmt ) {
    7576                        filter( cstmt->kids, [](Statement * stmt) {
    7677                                if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
     
    7980                                return false;
    8081                        }, false );
     82                }
     83
     84                Statement * TreeCleaner::postmutate( ImplicitCtorDtorStmt * stmt ) {
     85                        Statement * callStmt = nullptr;
     86                        std::swap( stmt->callStmt, callStmt );
     87                        delete stmt;
     88                        return callStmt;
    8189                }
    8290
  • src/CodeTools/TrackLoc.cc

    r39fea2f r47b5b63  
    3333
    3434namespace CodeTools {
    35 
    36         std::ostream & operator<<(std::ostream & out, CodeLocation const & loc) {
    37                 return out << loc.filename << '[' << loc.linenumber << ']';
    38         }
    39 
    4035        class LocationPrinter {
    4136                size_t printLevel;
     
    6964                                }
    7065                                else {
    71                                         std::cerr << "Top level node has no CodeLocation " << name << std::endl;
    72                                         exit(EXIT_FAILURE);
     66                                        assertf( false, "Top level node has no CodeLocation %s", name.c_str() );
    7367                                }
    7468                        }
     
    9589                acceptAll( translationUnit, printer );
    9690        }
    97 
    9891} // namespace CodeTools
    9992
  • src/Common/CodeLocation.h

    r39fea2f r47b5b63  
    1616#pragma once
    1717
     18#include <iostream>
    1819#include <string>
    1920
    2021struct CodeLocation {
    21         int linenumber;
    22         std::string filename;
     22        int first_line = -1, first_column = -1, last_line = -1, last_column = -1;
     23        std::string filename = "";
    2324
    2425        /// Create a new unset CodeLocation.
    25                 CodeLocation()
    26                 : linenumber( -1 )
    27                 , filename("")
    28         {}
     26        CodeLocation() = default;
    2927
    3028        /// Create a new CodeLocation with the given values.
    3129        CodeLocation( const char* filename, int lineno )
    32                 : linenumber( lineno )
     30                : first_line( lineno )
    3331                , filename(filename ? filename : "")
    3432        {}
     
    3735
    3836        bool isSet () const {
    39                 return -1 != linenumber;
     37                return -1 != first_line;
    4038        }
    4139
     
    4442        }
    4543
    46         void unset () {
    47                 linenumber = -1;
    48                 filename = "";
    49         }
    50 
    51         // Use field access for set.
    52 
    5344        bool followedBy( CodeLocation const & other, int seperation ) {
    54                 return (linenumber + seperation == other.linenumber &&
     45                return (first_line + seperation == other.first_line &&
    5546                        filename == other.filename);
    5647        }
     
    6556};
    6657
    67 inline std::string to_string( const CodeLocation& location ) {
    68     // Column number ":1" allows IDEs to parse the error message and position the cursor in the source text.
    69     return location.isSet() ? location.filename + ":" + std::to_string(location.linenumber) + ":1 " : "";
     58inline std::ostream & operator<<( std::ostream & out, const CodeLocation & location ) {
     59        // Column number ":1" allows IDEs to parse the error message and position the cursor in the source text.
     60        return location.isSet() ? out << location.filename << ":" << location.first_line << ":1 " : out;
    7061}
    71 
  • src/Common/PassVisitor.h

    r39fea2f r47b5b63  
    133133        virtual void visit( OneType *oneType ) override final;
    134134
     135        virtual void visit( Designation *designation ) override final;
    135136        virtual void visit( SingleInit *singleInit ) override final;
    136137        virtual void visit( ListInit *listInit ) override final;
     
    221222        virtual Type* mutate( OneType *oneType ) override final;
    222223
     224        virtual Designation* mutate( Designation *designation ) override final;
    223225        virtual Initializer* mutate( SingleInit *singleInit ) override final;
    224226        virtual Initializer* mutate( ListInit *listInit ) override final;
  • src/Common/PassVisitor.impl.h

    r39fea2f r47b5b63  
    19261926}
    19271927
     1928template< typename pass_type >
     1929void PassVisitor< pass_type >::visit( Designation * node ) {
     1930        VISIT_START( node );
     1931
     1932        maybeAccept( node->get_designators(), *this );
     1933
     1934        VISIT_END( node );
     1935}
     1936
     1937template< typename pass_type >
     1938Designation * PassVisitor< pass_type >::mutate( Designation * node ) {
     1939        MUTATE_START( node );
     1940
     1941        maybeMutateRef( node->get_designators(), *this );
     1942
     1943        MUTATE_END( Designation, node );
     1944}
     1945
    19281946//--------------------------------------------------------------------------
    19291947// SingleInit
  • src/Common/SemanticError.cc

    r39fea2f r47b5b63  
    4545        using std::to_string;
    4646        for( auto err : errors ) {
    47                 os << to_string( err.location ) << err.description << std::endl;
     47                os << err.location << err.description << std::endl;
    4848        }
    4949}
  • src/Common/SemanticError.h

    r39fea2f r47b5b63  
    3232
    3333        void maybeSet( const CodeLocation & location ) {
    34                 if( this->location.linenumber < 0 ) {
     34                if( this->location.isUnset() ) {
    3535                        this->location = location;
    3636                }
  • src/ControlStruct/ExceptTranslate.cc

    r39fea2f r47b5b63  
    622622                                assertf(false, "Invalid throw in %s at %i\n",
    623623                                        throwStmt->location.filename.c_str(),
    624                                         throwStmt->location.linenumber);
     624                                        throwStmt->location.first_line);
    625625                                return nullptr;
    626626                        }
     
    633633                                assertf(false, "Invalid throwResume in %s at %i\n",
    634634                                        throwStmt->location.filename.c_str(),
    635                                         throwStmt->location.linenumber);
     635                                        throwStmt->location.first_line);
    636636                                return nullptr;
    637637                        }
  • src/InitTweak/FixInit.cc

    r39fea2f r47b5b63  
    105105
    106106                /// collects constructed object decls - used as a base class
    107                 class ObjDeclCollector : public AddStmtVisitor {
    108                   public:
    109                         typedef AddStmtVisitor Parent;
    110                         using Parent::visit;
     107                struct ObjDeclCollector : public WithGuards, public WithShortCircuiting {
    111108                        // use ordered data structure to maintain ordering for set_difference and for consistent error messages
    112109                        typedef std::list< ObjectDecl * > ObjectSet;
    113                         virtual void visit( CompoundStmt *compoundStmt ) override;
    114                         virtual void visit( DeclStmt *stmt ) override;
     110                        void previsit( CompoundStmt *compoundStmt );
     111                        void previsit( DeclStmt *stmt );
    115112
    116113                        // don't go into other functions
    117                         virtual void visit( FunctionDecl * ) override {}
     114                        void previsit( FunctionDecl * ) { visit_children = false; }
    118115
    119116                  protected:
     
    139136                }
    140137
    141                 class LabelFinder final : public ObjDeclCollector {
    142                   public:
    143                         typedef ObjDeclCollector Parent;
     138                struct LabelFinder final : public ObjDeclCollector {
    144139                        typedef std::map< Label, ObjectSet > LabelMap;
    145140                        // map of Label -> live variables at that label
    146141                        LabelMap vars;
    147142
    148                         void handleStmt( Statement * stmt );
    149 
    150                         // xxx - This needs to be done better.
    151                         // allow some generalization among different kinds of nodes with with similar parentage (e.g. all
    152                         // expressions, all statements, etc.)  important to have this to provide a single entry point so that as new
    153                         // subclasses are added, there is only one place that the code has to be updated, rather than ensure that
    154                         // every specialized class knows about every new kind of statement that might be added.
    155                         using Parent::visit;
    156                         virtual void visit( CompoundStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    157                         virtual void visit( ExprStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    158                         virtual void visit( AsmStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    159                         virtual void visit( IfStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    160                         virtual void visit( WhileStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    161                         virtual void visit( ForStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    162                         virtual void visit( SwitchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    163                         virtual void visit( CaseStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    164                         virtual void visit( BranchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    165                         virtual void visit( ReturnStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    166                         virtual void visit( TryStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    167                         virtual void visit( CatchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    168                         virtual void visit( FinallyStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    169                         virtual void visit( NullStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    170                         virtual void visit( DeclStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
    171                         virtual void visit( ImplicitCtorDtorStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
     143                        typedef ObjDeclCollector Parent;
     144                        using Parent::previsit;
     145                        void previsit( Statement * stmt );
     146
     147                        void previsit( CompoundStmt *compoundStmt );
     148                        void previsit( DeclStmt *stmt );
    172149                };
    173150
    174                 class InsertDtors final : public ObjDeclCollector {
    175                 public:
     151                struct InsertDtors final : public ObjDeclCollector, public WithStmtsToAdd {
    176152                        /// insert destructor calls at the appropriate places.  must happen before CtorInit nodes are removed
    177153                        /// (currently by FixInit)
    178154                        static void insert( std::list< Declaration * > & translationUnit );
    179155
    180                         typedef ObjDeclCollector Parent;
    181156                        typedef std::list< ObjectDecl * > OrderedDecls;
    182157                        typedef std::list< OrderedDecls > OrderedDeclsStack;
    183158
    184                         InsertDtors( LabelFinder & finder ) : finder( finder ), labelVars( finder.vars ) {}
    185 
    186                         using Parent::visit;
    187 
    188                         virtual void visit( ObjectDecl * objDecl ) override;
    189                         virtual void visit( FunctionDecl * funcDecl ) override;
    190 
    191                         virtual void visit( CompoundStmt * compoundStmt ) override;
    192                         virtual void visit( ReturnStmt * returnStmt ) override;
    193                         virtual void visit( BranchStmt * stmt ) override;
     159                        InsertDtors( PassVisitor<LabelFinder> & finder ) : finder( finder ), labelVars( finder.pass.vars ) {}
     160
     161                        typedef ObjDeclCollector Parent;
     162                        using Parent::previsit;
     163
     164                        void previsit( ObjectDecl * objDecl );
     165                        void previsit( FunctionDecl * funcDecl );
     166
     167                        void previsit( CompoundStmt * compoundStmt );
     168                        void postvisit( CompoundStmt * compoundStmt );
     169                        void previsit( ReturnStmt * returnStmt );
     170                        void previsit( BranchStmt * stmt );
    194171                private:
    195172                        void handleGoto( BranchStmt * stmt );
    196173
    197                         LabelFinder & finder;
     174                        PassVisitor<LabelFinder> & finder;
    198175                        LabelFinder::LabelMap & labelVars;
    199176                        OrderedDeclsStack reverseDeclOrder;
     
    333310
    334311                void InsertDtors::insert( std::list< Declaration * > & translationUnit ) {
    335                         LabelFinder finder;
    336                         InsertDtors inserter( finder );
     312                        PassVisitor<LabelFinder> finder;
     313                        PassVisitor<InsertDtors> inserter( finder );
    337314                        acceptAll( translationUnit, inserter );
    338315                }
     
    792769                }
    793770
    794                 void ObjDeclCollector::visit( CompoundStmt * compoundStmt ) {
    795                         ObjectSet prevVars = curVars;
    796                         Parent::visit( compoundStmt );
    797                         curVars = prevVars;
    798                 }
    799 
    800                 void ObjDeclCollector::visit( DeclStmt * stmt ) {
     771                void ObjDeclCollector::previsit( CompoundStmt * ) {
     772                        GuardValue( curVars );
     773                }
     774
     775                void ObjDeclCollector::previsit( DeclStmt * stmt ) {
    801776                        // keep track of all variables currently in scope
    802777                        if ( ObjectDecl * objDecl = dynamic_cast< ObjectDecl * > ( stmt->get_decl() ) ) {
    803778                                curVars.push_back( objDecl );
    804779                        } // if
    805                         Parent::visit( stmt );
    806                 }
    807 
    808                 void LabelFinder::handleStmt( Statement * stmt ) {
     780                }
     781
     782                void LabelFinder::previsit( Statement * stmt ) {
    809783                        // for each label, remember the variables in scope at that label.
    810784                        for ( Label l : stmt->get_labels() ) {
     
    812786                        } // for
    813787                }
     788
     789                void LabelFinder::previsit( CompoundStmt * stmt ) {
     790                        previsit( (Statement *)stmt );
     791                        Parent::previsit( stmt );
     792                }
     793
     794                void LabelFinder::previsit( DeclStmt * stmt ) {
     795                        previsit( (Statement *)stmt );
     796                        Parent::previsit( stmt );
     797                }
     798
    814799
    815800                template<typename Iterator, typename OutputIterator>
     
    827812                }
    828813
    829                 void InsertDtors::visit( ObjectDecl * objDecl ) {
     814                void InsertDtors::previsit( ObjectDecl * objDecl ) {
    830815                        // remember non-static destructed objects so that their destructors can be inserted later
    831816                        if ( ! objDecl->get_storageClasses().is_static ) {
     
    841826                                } // if
    842827                        } // if
    843                         Parent::visit( objDecl );
    844                 }
    845 
    846                 template< typename Visitor >
    847                 void handleFuncDecl( FunctionDecl * funcDecl, Visitor & visitor ) {
    848                         maybeAccept( funcDecl->get_functionType(), visitor );
    849                         maybeAccept( funcDecl->get_statements(), visitor );
    850                 }
    851 
    852                 void InsertDtors::visit( FunctionDecl * funcDecl ) {
     828                }
     829
     830                void InsertDtors::previsit( FunctionDecl * funcDecl ) {
    853831                        // each function needs to have its own set of labels
    854                         ValueGuard< LabelFinder::LabelMap > oldLabels( labelVars );
     832                        GuardValue( labelVars );
    855833                        labelVars.clear();
    856                         handleFuncDecl( funcDecl, finder );
    857 
    858                         // all labels for this function have been collected, insert destructors as appropriate.
    859                         // can't be Parent::mutate, because ObjDeclCollector bottoms out on FunctionDecl
    860                         handleFuncDecl( funcDecl, *this );
    861                 }
    862 
    863                 void InsertDtors::visit( CompoundStmt * compoundStmt ) {
     834                        maybeAccept( funcDecl->type, finder );
     835                        maybeAccept( funcDecl->statements, finder );
     836
     837                        // all labels for this function have been collected, insert destructors as appropriate via implicit recursion.
     838                }
     839
     840                void InsertDtors::previsit( CompoundStmt * compoundStmt ) {
    864841                        // visit statements - this will also populate reverseDeclOrder list.  don't want to dump all destructors
    865842                        // when block is left, just the destructors associated with variables defined in this block, so push a new
    866843                        // list to the top of the stack so that we can differentiate scopes
    867844                        reverseDeclOrder.push_front( OrderedDecls() );
    868                         Parent::visit( compoundStmt );
    869 
     845                        Parent::previsit( compoundStmt );
     846                }
     847
     848                void InsertDtors::postvisit( CompoundStmt * compoundStmt ) {
    870849                        // add destructors for the current scope that we're exiting, unless the last statement is a return, which
    871850                        // causes unreachable code warnings
     
    877856                }
    878857
    879                 void InsertDtors::visit( __attribute((unused)) ReturnStmt * returnStmt ) {
     858                void InsertDtors::previsit( ReturnStmt * ) {
    880859                        // return exits all scopes, so dump destructors for all scopes
    881860                        for ( OrderedDecls & od : reverseDeclOrder ) {
    882                                 insertDtors( od.begin(), od.end(), back_inserter( stmtsToAdd ) );
     861                                insertDtors( od.begin(), od.end(), back_inserter( stmtsToAddBefore ) );
    883862                        } // for
    884863                }
     
    928907                                        copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return needsDestructor.count( objDecl ); } );
    929908                                } // for
    930                                 insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAdd ) );
     909                                insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAddBefore ) );
    931910                        } // if
    932911                }
    933912
    934                 void InsertDtors::visit( BranchStmt * stmt ) {
     913                void InsertDtors::previsit( BranchStmt * stmt ) {
    935914                        switch( stmt->get_type() ) {
    936915                          case BranchStmt::Continue:
  • src/Parser/ParseNode.h

    r39fea2f r47b5b63  
    4444//##############################################################################
    4545
     46typedef CodeLocation YYLTYPE;
     47#define YYLTYPE_IS_DECLARED 1 /* alert the parser that we have our own definition */
     48
    4649extern char * yyfilename;
    4750extern int yylineno;
     51extern YYLTYPE yylloc;
    4852
    4953class ParseNode {
     
    7377        ParseNode * next = nullptr;
    7478        std::string * name = nullptr;
    75         CodeLocation location = { yyfilename, yylineno };
     79        CodeLocation location = yylloc;
    7680}; // ParseNode
    7781
  • src/Parser/lex.ll

    r39fea2f r47b5b63  
    2626
    2727unsigned int column = 0;                                                                // position of the end of the last token parsed
    28 #define YY_USER_ACTION column += yyleng;                                // trigger before each matching rule's action
     28#define YY_USER_ACTION yylloc.first_line = yylineno; yylloc.first_column = column; column += yyleng; yylloc.last_column = column; yylloc.last_line = yylineno; yylloc.filename = yyfilename ? yyfilename : "";                          // trigger before each matching rule's action
    2929
    3030#include <string>
  • src/Parser/parser.yy

    r39fea2f r47b5b63  
    116116
    117117bool forall = false;                                                                    // aggregate have one or more forall qualifiers ?
     118
     119# define YYLLOC_DEFAULT(Cur, Rhs, N)                            \
     120do                                                              \
     121        if (N) {                                                      \
     122                (Cur).first_line   = YYRHSLOC(Rhs, 1).first_line;           \
     123                (Cur).first_column = YYRHSLOC(Rhs, 1).first_column;         \
     124                (Cur).last_line    = YYRHSLOC(Rhs, N).last_line;            \
     125                (Cur).last_column  = YYRHSLOC(Rhs, N).last_column;          \
     126                (Cur).filename     = YYRHSLOC(Rhs, 1).filename;             \
     127        } else {                                                      \
     128                (Cur).first_line   = (Cur).last_line   =                    \
     129                        YYRHSLOC(Rhs, 0).last_line;                               \
     130                (Cur).first_column = (Cur).last_column =                    \
     131                        YYRHSLOC(Rhs, 0).last_column;                             \
     132                (Cur).filename     = YYRHSLOC(Rhs, 0).filename;             \
     133        }                                                             \
     134while (0)
    118135%}
    119136
     
    346363%precedence ELSE        // token precedence for start of else clause in IF/WAITFOR statement
    347364
     365%locations
    348366
    349367%start translation_unit                                                                 // parse-tree root
  • src/SymTab/Autogen.cc

    r39fea2f r47b5b63  
    223223                        FunctionType * ftype = data.genType( refType );
    224224
    225                         if(concurrent_type && CodeGen::isDestructor( data.fname )) {
     225                        if ( concurrent_type && CodeGen::isDestructor( data.fname ) ) {
    226226                                ftype->parameters.front()->get_type()->set_mutex( true );
    227227                        }
  • src/SynTree/BaseSyntaxNode.h

    r39fea2f r47b5b63  
    2626
    2727        virtual void accept( Visitor & v ) = 0;
     28  virtual void print( std::ostream & os, int indent = 0 ) const = 0;
    2829};
    2930
  • src/tests/.expect/dtor-early-exit-ERR1.txt

    r39fea2f r47b5b63  
    1 dtor-early-exit.c:142:1 error: jump to label 'L1' crosses initialization of y Branch (Goto)
     1dtor-early-exit.c:153:1 error: jump to label 'L1' crosses initialization of y Branch (Goto)
    22  with target: L1
    33  with original target: L1
  • src/tests/.expect/dtor-early-exit-ERR2.txt

    r39fea2f r47b5b63  
    1 dtor-early-exit.c:142:1 error: jump to label 'L2' crosses initialization of y Branch (Goto)
     1dtor-early-exit.c:220:1 error: jump to label 'L2' crosses initialization of y Branch (Goto)
    22  with target: L2
    33  with original target: L2
Note: See TracChangeset for help on using the changeset viewer.