|
13 | 13 |
|
14 | 14 | #include <ostream>
|
15 | 15 |
|
| 16 | +#include <util/message.h> |
16 | 17 | #include <util/std_expr.h>
|
17 | 18 |
|
18 | 19 | #include <langapi/language_util.h>
|
@@ -483,3 +484,129 @@ std::string as_string(
|
483 | 484 |
|
484 | 485 | return "";
|
485 | 486 | }
|
| 487 | + |
| 488 | +/// Ensure the current goto_programt satisfies all assumptions |
| 489 | +/// about consistent goto programs. |
| 490 | +/// \param msg Message output |
| 491 | +/// \return True, iff at least one invariant is violated |
| 492 | +bool goto_programt::check_internal_invariants(messaget &msg) const |
| 493 | +{ |
| 494 | + if(empty()) |
| 495 | + return false; |
| 496 | + |
| 497 | + unsigned prev_loc_number=0; |
| 498 | + bool prev_loc_number_set=false; |
| 499 | + |
| 500 | + forall_goto_program_instructions(it, *this) |
| 501 | + { |
| 502 | + const goto_programt::instructiont &ins=*it; |
| 503 | + |
| 504 | + if(ins.check_internal_invariants(msg)) |
| 505 | + return true; |
| 506 | + |
| 507 | + if(prev_loc_number_set && |
| 508 | + ins.location_number<=prev_loc_number) |
| 509 | + { |
| 510 | + msg.error().source_location=ins.source_location; |
| 511 | + msg.error() << "location number not strictly increasing" |
| 512 | + << messaget::eom; |
| 513 | + return true; |
| 514 | + } |
| 515 | + else if(!prev_loc_number_set) |
| 516 | + { |
| 517 | + prev_loc_number=ins.location_number; |
| 518 | + prev_loc_number_set=true; |
| 519 | + } |
| 520 | + |
| 521 | + switch(ins.type) |
| 522 | + { |
| 523 | + case GOTO: |
| 524 | + case ASSUME: |
| 525 | + case ASSERT: |
| 526 | + if(ins.guard.type()!=bool_typet()) |
| 527 | + { |
| 528 | + msg.error().source_location=ins.source_location; |
| 529 | + msg.error() << ins.type << " has non-Boolean guard" |
| 530 | + << messaget::eom; |
| 531 | + return true; |
| 532 | + } |
| 533 | + break; |
| 534 | + case OTHER: |
| 535 | + case SKIP: |
| 536 | + case LOCATION: |
| 537 | + case END_FUNCTION: |
| 538 | + case START_THREAD: |
| 539 | + case END_THREAD: |
| 540 | + case ATOMIC_BEGIN: |
| 541 | + case ATOMIC_END: |
| 542 | + case RETURN: |
| 543 | + break; |
| 544 | + case ASSIGN: |
| 545 | + if(ins.code.get_statement()!=ID_assign) |
| 546 | + { |
| 547 | + msg.error().source_location=ins.source_location; |
| 548 | + msg.error() << ins.type << " instruction has code " |
| 549 | + << ins.code.get_statement() |
| 550 | + << messaget::eom; |
| 551 | + return true; |
| 552 | + } |
| 553 | + return false; |
| 554 | + case DECL: |
| 555 | + if(ins.code.get_statement()!=ID_decl) |
| 556 | + { |
| 557 | + msg.error().source_location=ins.source_location; |
| 558 | + msg.error() << ins.type << " instruction has code " |
| 559 | + << ins.code.get_statement() |
| 560 | + << messaget::eom; |
| 561 | + return true; |
| 562 | + } |
| 563 | + else if(to_code_decl(ins.code).symbol().id()!=ID_symbol) |
| 564 | + { |
| 565 | + msg.error().source_location=ins.source_location; |
| 566 | + msg.error() << "declaration operand is not a symbol" |
| 567 | + << messaget::eom; |
| 568 | + return true; |
| 569 | + } |
| 570 | + break; |
| 571 | + case DEAD: |
| 572 | + if(ins.code.get_statement()!=ID_dead) |
| 573 | + { |
| 574 | + msg.error().source_location=ins.source_location; |
| 575 | + msg.error() << ins.type << " instruction has code " |
| 576 | + << ins.code.get_statement() |
| 577 | + << messaget::eom; |
| 578 | + return true; |
| 579 | + } |
| 580 | + break; |
| 581 | + case FUNCTION_CALL: |
| 582 | + if(ins.code.get_statement()!=ID_function_call) |
| 583 | + { |
| 584 | + msg.error().source_location=ins.source_location; |
| 585 | + msg.error() << ins.type << " instruction has code " |
| 586 | + << ins.code.get_statement() |
| 587 | + << messaget::eom; |
| 588 | + return true; |
| 589 | + } |
| 590 | + break; |
| 591 | + case THROW: |
| 592 | + case CATCH: |
| 593 | + break; |
| 594 | + case NO_INSTRUCTION_TYPE: |
| 595 | + msg.error().source_location=ins.source_location; |
| 596 | + msg.error() << ins.type << " not permitted" |
| 597 | + << messaget::eom; |
| 598 | + return true; |
| 599 | + } |
| 600 | + } |
| 601 | + |
| 602 | + // the last instruction must be END_FUNCTION |
| 603 | + if(!get_end_function()->is_end_function()) |
| 604 | + { |
| 605 | + msg.error().source_location=get_end_function()->source_location; |
| 606 | + msg.error() << "end of function is of type " |
| 607 | + << get_end_function()->type << messaget::eom; |
| 608 | + return true; |
| 609 | + } |
| 610 | + |
| 611 | + return false; |
| 612 | +} |
0 commit comments