Changeset adcc065
- Timestamp:
- Jul 6, 2016, 6:06:27 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 3f869f0
- Parents:
- e04c5ff
- Location:
- src
- Files:
-
- 1 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/MLEMutator.cc
re04c5ff radcc065 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Mon Jul 20 13:58:35 2015 13 // Update Count : 176 14 // 15 16 // NOTE: There are two known subtle differences from the code that uC++ 17 // generates for the same input 18 // -CFA puts the break label inside at the end of a switch, uC++ puts it after 19 // -CFA puts the break label after a block, uC++ puts it inside at the end 20 // we don't yet know if these differences are important, but if they are then 21 // the fix would go in this file, since this is where these labels are generated. 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 6 17:40:02 2016 13 // Update Count : 196 14 // 15 16 // NOTE: There are two known subtle differences from the code that uC++ generates for the same input 17 // -CFA puts the break label inside at the end of a switch, uC++ puts it after 18 // -CFA puts the break label after a block, uC++ puts it inside at the end 19 // It is unclear if these differences are important, but if they are, then the fix would go in this file, since this is 20 // where these labels are generated. 22 21 23 22 #include <cassert> … … 38 37 } 39 38 40 // break labels have to come after the statement they break out of, 41 // so mutate a statement, then if they inform us through the breakLabel field 42 // tha they need a place to jump to on a break statement, add the break label 43 // to the body of statements 39 // break labels have to come after the statement they break out of, so mutate a statement, then if they inform us 40 // through the breakLabel field tha they need a place to jump to on a break statement, add the break label to the 41 // body of statements 44 42 void MLEMutator::fixBlock( std::list< Statement * > &kids ) { 45 43 for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) { … … 62 60 } // if 63 61 64 // a child statement may set the break label 65 // - if they do, attach it to the next statement 62 // a child statement may set the break label - if they do, attach it to the next statement 66 63 std::list< Statement * > &kids = cmpndStmt->get_kids(); 67 64 fixBlock( kids ); … … 71 68 if ( ! enclosingControlStructures.back().useBreakExit().empty() ) { 72 69 set_breakLabel( enclosingControlStructures.back().useBreakExit() ); 73 } 70 } // if 74 71 enclosingControlStructures.pop_back(); 75 72 } // if … … 80 77 template< typename LoopClass > 81 78 Statement *MLEMutator::handleLoopStmt( LoopClass *loopStmt ) { 82 // remember this as the most recent enclosing loop, then mutate 83 // the body of the loop -- this will determine whether brkLabel 84 // and contLabel are used with branch statements 85 // and will recursively do the same to nested loops 79 // remember this as the most recent enclosing loop, then mutate the body of the loop -- this will determine 80 // whether brkLabel and contLabel are used with branch statements and will recursively do the same to nested 81 // loops 86 82 Label brkLabel = generator->newLabel("loopBreak"); 87 83 Label contLabel = generator->newLabel("loopContinue"); … … 89 85 loopStmt->set_body ( loopStmt->get_body()->acceptMutator( *this ) ); 90 86 87 Entry &e = enclosingControlStructures.back(); 91 88 // sanity check that the enclosing loops have been popped correctly 92 Entry &e = enclosingControlStructures.back();93 89 assert ( e == loopStmt ); 94 90 95 // this will take the necessary steps to add definitions of the previous 96 // two labels, if they are used. 91 // this will take the necessary steps to add definitions of the previous two labels, if they are used. 97 92 loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) ); 98 93 enclosingControlStructures.pop_back(); … … 106 101 107 102 return caseStmt; 103 } 104 105 template< typename IfClass > 106 Statement *MLEMutator::handleIfStmt( IfClass *ifStmt ) { 107 // generate a label for breaking out of a labeled if 108 bool labeledBlock = !(ifStmt->get_labels().empty()); 109 if ( labeledBlock ) { 110 Label brkLabel = generator->newLabel("blockBreak"); 111 enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) ); 112 } // if 113 114 Parent::mutate( ifStmt ); 115 116 if ( labeledBlock ) { 117 if ( ! enclosingControlStructures.back().useBreakExit().empty() ) { 118 set_breakLabel( enclosingControlStructures.back().useBreakExit() ); 119 } // if 120 enclosingControlStructures.pop_back(); 121 } // if 122 return ifStmt; 108 123 } 109 124 … … 119 134 120 135 // only generate break label if labeled break is used 121 if ( e.isBreakUsed()) {122 // for the purposes of keeping switch statements uniform (i.e. all statements that are 123 // direct children of a switch should be CastStmts), append the exit label + break to the124 // last case statement; create a defaultcase if there are no cases136 if ( e.isBreakUsed() ) { 137 // for the purposes of keeping switch statements uniform (i.e. all statements that are direct children of a 138 // switch should be CastStmts), append the exit label + break to the last case statement; create a default 139 // case if there are no cases 125 140 std::list< Statement * > &branches = switchStmt->get_branches(); 126 141 if ( branches.empty() ) { 127 142 branches.push_back( CaseStmt::makeDefault() ); 128 } 143 } // if 129 144 130 145 if ( CaseStmt * c = dynamic_cast< CaseStmt * >( branches.back() ) ) { … … 132 147 c->get_statements().push_back( new BranchStmt( temp, Label("brkLabel"), BranchStmt::Break ) ); 133 148 } else assert(0); // as of this point, all branches of a switch are still CaseStmts 134 } 149 } // if 135 150 136 151 assert ( enclosingControlStructures.back() == switchStmt ); … … 152 167 // labelled continue - lookup label in table ot find attached control structure 153 168 targetEntry = std::find( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), (*targetTable)[branchStmt->get_target()] ); 154 } 169 } // if 155 170 if ( targetEntry == enclosingControlStructures.rend() || ! isLoop( targetEntry->get_controlStructure() ) ) { 156 171 throw SemanticError( "'continue' target must be an enclosing loop: " + originalTarget ); 157 } 172 } // if 158 173 } else if ( branchStmt->get_type() == BranchStmt::Break ) { 159 174 if ( enclosingControlStructures.empty() ) throw SemanticError( "'break' outside a loop, switch, or labelled block" ); … … 161 176 } else { 162 177 assert( false ); 163 } 178 } // if 164 179 165 180 if ( branchStmt->get_target() != "" && targetTable->find( branchStmt->get_target() ) == targetTable->end() ) { 166 181 throw SemanticError("The label defined in the exit loop statement does not exist: " + originalTarget ); // shouldn't happen (since that's already checked) 167 } 182 } // if 168 183 169 184 // branch error checks, get the appropriate label name and create a goto … … 191 206 delete branchStmt; 192 207 return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto ); 193 } 208 } // if 194 209 } 195 210 … … 208 223 std::list< Label > labels; labels.push_back( e.useContExit() ); 209 224 newBody->get_kids().push_back( new NullStmt( labels ) ); 210 } 225 } // if 211 226 212 227 if ( e.isBreakUsed() ) { 213 // break label goes after the loop -- it'll get set by the 214 // outer mutator if we do this 228 // break label goes after the loop -- it'll get set by the outer mutator if we do this 215 229 set_breakLabel( e.useBreakExit() ); 216 } 230 } // if 217 231 218 232 return newBody; … … 227 241 } 228 242 243 Statement *MLEMutator::mutate( IfStmt *ifStmt ) { 244 return handleIfStmt( ifStmt ); 245 } 246 229 247 Statement *MLEMutator::mutate( SwitchStmt *switchStmt ) { 230 248 return handleSwitchStmt( switchStmt ); … … 234 252 return handleSwitchStmt( switchStmt ); 235 253 } 236 237 254 } // namespace ControlStruct 238 255 -
src/ControlStruct/MLEMutator.h
re04c5ff radcc065 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Ju n 03 15:06:36 201513 // Update Count : 2511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 6 16:49:52 2016 13 // Update Count : 31 14 14 // 15 15 … … 30 30 class MLEMutator : public Mutator { 31 31 class Entry; 32 typedef Mutator Parent; 32 33 public: 33 34 MLEMutator( std::map<Label, Statement *> *t, LabelGenerator *gen = 0 ) : targetTable( t ), breakLabel(std::string("")), generator( gen ) {} … … 35 36 36 37 CompoundStmt *mutate( CompoundStmt *cmpndStmt ); 37 Statement *mutate( WhileStmt *whileStmt );38 Statement *mutate( ForStmt *forStmt );39 Statement *mutate( BranchStmt *branchStmt ) throw ( SemanticError );38 virtual Statement *mutate( WhileStmt *whileStmt ) override; 39 virtual Statement *mutate( ForStmt *forStmt ) override; 40 virtual Statement *mutate( BranchStmt *branchStmt ) throw ( SemanticError ) override; 40 41 41 Statement *mutate( CaseStmt *caseStmt ); 42 Statement *mutate( SwitchStmt *switchStmt ); 43 Statement *mutate( ChooseStmt *switchStmt ); 42 virtual Statement *mutate( CaseStmt *caseStmt ) override; 43 virtual Statement *mutate( IfStmt *ifStmt ) override; 44 virtual Statement *mutate( SwitchStmt *switchStmt ) override; 45 virtual Statement *mutate( ChooseStmt *switchStmt ) override; 44 46 45 47 Statement *mutateLoop( Statement *bodyLoop, Entry &e ); … … 65 67 bool isContUsed() const { return contUsed; } 66 68 bool isBreakUsed() const { return breakUsed; } 67 68 69 private: 69 70 Statement *loop; … … 79 80 template< typename LoopClass > 80 81 Statement *handleLoopStmt( LoopClass *loopStmt ); 82 83 template< typename IfClass > 84 Statement *handleIfStmt( IfClass *switchStmt ); 81 85 82 86 template< typename SwitchClass > -
src/InitTweak/FixInit.cc
re04c5ff radcc065 9 9 // Author : Rob Schluntz 10 10 // Created On : Wed Jan 13 16:29:30 2016 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Fri May 13 11:44:26 201613 // Update Count : 3 011 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 6 17:34:46 2016 13 // Update Count : 33 14 14 // 15 15 … … 47 47 class InsertImplicitCalls : public GenPoly::PolyMutator { 48 48 public: 49 /// wrap function application expressions as ImplicitCopyCtorExpr nodes 50 /// so that it is easy to identify which function calls need their parameters 51 /// to be copy constructed 49 /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which 50 /// function calls need their parameters to be copy constructed 52 51 static void insert( std::list< Declaration * > & translationUnit ); 53 52 … … 57 56 class ResolveCopyCtors : public SymTab::Indexer { 58 57 public: 59 /// generate temporary ObjectDecls for each argument and return value of each 60 /// ImplicitCopyCtorExpr, generate/resolve copy construction expressions for each,61 /// a nd generate/resolve destructors for both arguments and return value temporaries58 /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr, 59 /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both 60 /// arguments and return value temporaries 62 61 static void resolveImplicitCalls( std::list< Declaration * > & translationUnit ); 63 62 … … 93 92 for ( ObjectDecl * obj : set.objs ) { 94 93 out << obj->get_name() << ", " ; 95 } 94 } // for 96 95 out << " }"; 97 96 return out; … … 108 107 109 108 // xxx - This needs to be done better. 110 // allow some generalization among different kinds of nodes with 111 // with similar parentage (e.g. all expressions, all statements, etc.) 112 // important to have this to provide a single entry point so that as 113 // new subclasses are added, there is only one place that the code has 114 // to be updated, rather than ensure that every specialized class knows 115 // about every new kind of statement that might be added. 109 // allow some generalization among different kinds of nodes with with similar parentage (e.g. all 110 // expressions, all statements, etc.) important to have this to provide a single entry point so that as new 111 // subclasses are added, there is only one place that the code has to be updated, rather than ensure that 112 // every specialized class knows about every new kind of statement that might be added. 116 113 virtual void visit( CompoundStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 117 114 virtual void visit( ExprStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } … … 136 133 class InsertDtors : public ObjDeclCollector { 137 134 public: 138 /// insert destructor calls at the appropriate places. 139 /// must happen before CtorInit nodes are removed(currently by FixInit)135 /// insert destructor calls at the appropriate places. must happen before CtorInit nodes are removed 136 /// (currently by FixInit) 140 137 static void insert( std::list< Declaration * > & translationUnit ); 141 138 … … 168 165 class FixCopyCtors : public GenPoly::PolyMutator { 169 166 public: 170 /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, 171 /// call expression,and destructors167 /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, call expression, 168 /// and destructors 172 169 static void fixCopyCtors( std::list< Declaration * > &translationUnit ); 173 170 … … 235 232 // assignment operator 236 233 return appExpr; 237 } 234 } // if 238 235 } else if ( funcDecl->get_name() == "^?{}" ) { 239 236 // correctness: never copy construct arguments to a destructor 240 237 return appExpr; 241 } 242 } 243 } 238 } // if 239 } // if 240 } // if 244 241 CP_CTOR_PRINT( std::cerr << "InsertImplicitCalls: adding a wrapper " << appExpr << std::endl; ) 245 242 … … 270 267 271 268 // resolve copy constructor 272 // should only be one alternative for copy ctor and dtor expressions, since 273 // all arguments are fixed(VariableExpr and already resolved expression)269 // should only be one alternative for copy ctor and dtor expressions, since all arguments are fixed 270 // (VariableExpr and already resolved expression) 274 271 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; ) 275 272 ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) ); 276 273 if ( resolved->get_env() ) { 277 274 env->add( *resolved->get_env() ); 278 } 275 } // if 279 276 280 277 assert( resolved ); … … 319 316 impCpCtorExpr->get_tempDecls().push_back( tmp ); 320 317 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) ); 321 } 322 } 323 324 // each return value from the call needs to be connected with an ObjectDecl 325 // at the call site, which is initialized with the return value and is destructed 326 // later 318 } // if 319 } // for 320 321 // each return value from the call needs to be connected with an ObjectDecl at the call site, which is 322 // initialized with the return value and is destructed later 327 323 // xxx - handle multiple return values 328 324 ApplicationExpr * callExpr = impCpCtorExpr->get_callExpr(); 329 // xxx - is this right? callExpr may not have the right environment, because it was attached 330 // at a higherlevel. Trying to pass that environment along.325 // xxx - is this right? callExpr may not have the right environment, because it was attached at a higher 326 // level. Trying to pass that environment along. 331 327 callExpr->set_env( impCpCtorExpr->get_env()->clone() ); 332 328 for ( Type * result : appExpr->get_results() ) { … … 338 334 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 339 335 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) ); 340 } 336 } // for 341 337 CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; ) 342 338 } … … 356 352 for ( ObjectDecl * obj : tempDecls ) { 357 353 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) ); 358 } 354 } // for 359 355 for ( ObjectDecl * obj : returnDecls ) { 360 356 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) ); 361 } 357 } // for 362 358 363 359 // add destructors after current statement 364 360 for ( Expression * dtor : dtors ) { 365 361 stmtsToAddAfter.push_back( new ExprStmt( noLabels, dtor ) ); 366 } 362 } // for 367 363 368 364 // xxx - update to work with multiple return values … … 390 386 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) ); 391 387 if ( callExpr->get_results().front()->get_isLvalue() ) { 392 // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any 393 // lvalue returning non-intrinsic function. Add an AddressExpr to the call to negate 394 // the derefence and change the type of the return temporary from T to T* to properly 395 // capture the return value. Then dereference the result of the comma expression, since 396 // the lvalue returning call was originally wrapped with an AddressExpr. 397 // Effectively, this turns 388 // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning 389 // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the 390 // type of the return temporary from T to T* to properly capture the return value. Then dereference 391 // the result of the comma expression, since the lvalue returning call was originally wrapped with 392 // an AddressExpr. Effectively, this turns 398 393 // lvalue T f(); 399 394 // &*f() … … 410 405 deref->add_result( resultType ); 411 406 retExpr = deref; 412 } 407 } // if 413 408 // xxx - might need to set env on retExpr... 414 409 // retExpr->set_env( env->clone() ); … … 416 411 } else { 417 412 return callExpr; 418 } 413 } // if 419 414 } 420 415 421 416 DeclarationWithType *FixInit::mutate( ObjectDecl *objDecl ) { 422 // first recursively handle pieces of ObjectDecl so that they aren't missed by other visitors 423 // when the initis removed from the ObjectDecl417 // first recursively handle pieces of ObjectDecl so that they aren't missed by other visitors when the init 418 // is removed from the ObjectDecl 424 419 objDecl = dynamic_cast< ObjectDecl * >( Mutator::mutate( objDecl ) ); 425 420 … … 474 469 } else { 475 470 stmtsToAddAfter.push_back( ctor ); 476 } 471 } // if 477 472 objDecl->set_init( NULL ); 478 473 ctorInit->set_ctor( NULL ); … … 483 478 // no constructor and no initializer, which is okay 484 479 objDecl->set_init( NULL ); 485 } 480 } // if 486 481 delete ctorInit; 487 } 482 } // if 488 483 return objDecl; 489 484 } … … 499 494 if ( ObjectDecl * objDecl = dynamic_cast< ObjectDecl * > ( stmt->get_decl() ) ) { 500 495 curVars.insert( objDecl ); 501 } 496 } // if 502 497 Parent::visit( stmt ); 503 498 } … … 507 502 for ( Label l : stmt->get_labels() ) { 508 503 vars[l] = curVars; 509 } 504 } // for 510 505 } 511 506 … … 513 508 void insertDtors( Iterator begin, Iterator end, OutputIterator out ) { 514 509 for ( Iterator it = begin ; it != end ; ++it ) { 515 // extract destructor statement from the object decl and 516 // insert it into the output. Note that this is only called 517 // on lists of non-static objects with implicit non-intrinsic 518 // dtors, so if the user manually calls an intrinsic dtor 519 // then the call must (and will) still be generated since 520 // the argument may contain side effects. 510 // extract destructor statement from the object decl and insert it into the output. Note that this is 511 // only called on lists of non-static objects with implicit non-intrinsic dtors, so if the user manually 512 // calls an intrinsic dtor then the call must (and will) still be generated since the argument may 513 // contain side effects. 521 514 ObjectDecl * objDecl = *it; 522 515 ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ); 523 516 assert( ctorInit && ctorInit->get_dtor() ); 524 517 *out++ = ctorInit->get_dtor()->clone(); 525 } 518 } // for 526 519 } 527 520 … … 537 530 // non-intrinsic dtors must be called 538 531 reverseDeclOrder.front().push_front( objDecl ); 539 } 540 } 541 } 532 } // if 533 } // if 534 } // if 542 535 Parent::visit( objDecl ); 543 536 } 544 537 545 538 void InsertDtors::visit( CompoundStmt * compoundStmt ) { 546 // visit statements - this will also populate reverseDeclOrder list. 547 // don't want to dump all destructors when block is left, 548 // just the destructors associated with variables defined in this block, 549 // so push a new list to the top of the stack so that we can differentiate scopes 539 // visit statements - this will also populate reverseDeclOrder list. don't want to dump all destructors 540 // when block is left, just the destructors associated with variables defined in this block, so push a new 541 // list to the top of the stack so that we can differentiate scopes 550 542 reverseDeclOrder.push_front( OrderedDecls() ); 551 543 Parent::visit( compoundStmt ); … … 561 553 for ( OrderedDecls & od : reverseDeclOrder ) { 562 554 insertDtors( od.begin(), od.end(), back_inserter( stmtsToAdd ) ); 563 } 564 } 565 566 // Handle break/continue/goto in the same manner as C++. 567 // Basic idea: any objects that are in scope at the BranchStmt 568 // but not at the labelled (target) statement must be destructed. 569 // If there are any objects in scope at the target location but 570 // not at the BranchStmt then those objects would be uninitialized 571 // so notify the user of the error. 572 // See C++ Reference 6.6 Jump Statements for details. 555 } // for 556 } 557 558 // Handle break/continue/goto in the same manner as C++. Basic idea: any objects that are in scope at the 559 // BranchStmt but not at the labelled (target) statement must be destructed. If there are any objects in scope 560 // at the target location but not at the BranchStmt then those objects would be uninitialized so notify the user 561 // of the error. See C++ Reference 6.6 Jump Statements for details. 573 562 void InsertDtors::handleGoto( BranchStmt * stmt ) { 574 563 assert( stmt->get_target() != "" && "BranchStmt missing a label" ); … … 591 580 if ( ! diff.empty() ) { 592 581 throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt ); 593 } 582 } // if 594 583 // S_G-S_L results in set of objects that must be destructed 595 584 diff.clear(); … … 604 593 // add elements from reverseDeclOrder into ordered if they occur in diff - it is key that this happens in reverse declaration order. 605 594 copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return diff.count( objDecl ); } ); 606 } 595 } // for 607 596 insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAdd ) ); 608 } 597 } // if 609 598 } 610 599 611 600 void InsertDtors::visit( BranchStmt * stmt ) { 612 601 switch( stmt->get_type() ) { 613 case BranchStmt::Continue: 614 case BranchStmt::Break: 615 // could optimize the break/continue case, because the S_L-S_G check 616 // is unnecessary (this set should always be empty), but it serves 617 // as a small sanity check. 618 case BranchStmt::Goto: 619 handleGoto( stmt ); 620 break; 621 default: 622 assert( false ); 623 } 602 case BranchStmt::Continue: 603 case BranchStmt::Break: 604 // could optimize the break/continue case, because the S_L-S_G check is unnecessary (this set should 605 // always be empty), but it serves as a small sanity check. 606 case BranchStmt::Goto: 607 handleGoto( stmt ); 608 break; 609 default: 610 assert( false ); 611 } // switch 624 612 } 625 613 } // namespace -
src/tests/random.c
re04c5ff radcc065 10 10 // Created On : Tue Jul 5 21:29:30 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Jul 5 21:29:54201613 // Update Count : 112 // Last Modified On : Wed Jul 6 18:00:29 2016 13 // Update Count : 3 14 14 // 15 15 … … 19 19 20 20 int main() { 21 rand48seed( getpid() ); // set random seed 21 //rand48seed( getpid() ); // set random seed 22 rand48seed( 1003 ); // fixed seed for repeatable tests 22 23 23 24 // test polymorphic calls to random and stream
Note: See TracChangeset
for help on using the changeset viewer.