#This script is designed to run with Understand - CodeCheck use base ("Understand::Codecheck"); use strict; use constant MULT => 'Multiple exit points from function'; use constant NOEXIT => 'No exit point in function'; use constant NOTEND => 'Exit point not at end of function'; sub register_tr_text() { my $check = shift; $check->add_tr_text(MULT); $check->add_tr_text(NOEXIT); $check->add_tr_text(NOTEND); } sub name { return "14.7 A function shall have a single point of exit at the end of the function";} sub description { return "14.7 (Required) A function shall have a single point of exit at the end of the function.";} sub detailed_description { return <<"END_DESC" This is required by IEC 61508, under good programming style. END_DESC } sub test_language { my $language = shift; return $language =~ /C\+\+/; #Handles C and C++ } sub test_entity { return 1;} sub test_global { return 0;} sub define_options{} sub check { my $check = shift; my $file = shift; return unless $file->kind->check("file"); my @funcEnds =$file->filerefs("end","function"); return unless @funcEnds; my $lexer = $file->lexer; return unless $lexer; #Start at the end of the function and walk through it backwards; FUNCTIONLOOP:foreach my $funcEnd (@funcEnds){ my $start = $funcEnd->ent->ref("definein"); my $atEnd = 0; my $statementCount; my $exitCount; my $lexeme = $lexer->lexeme($funcEnd->line,$funcEnd->column); while($lexeme && $lexeme->line_begin >= $start->line){ $exitCount++ if $lexeme->token eq "Keyword" && $lexeme->text =~ /Exit|return|goto/i; $statementCount++ if $lexeme->token eq "Punctuation" && $lexeme->text =~ /[;}]/; if ($statementCount && $statementCount == 2 && $exitCount){ $atEnd = 1; } }continue{ $lexeme=$lexeme->previous; } if ($exitCount && $exitCount > 1){ $check->violation($funcEnd->ent,$file,$start->line,$start->column,MULT); }elsif(! $exitCount && $funcEnd->ent->type ne "void"){ $check->violation($funcEnd->ent,$file,$start->line,$start->column,NOEXIT); }elsif($exitCount==1 && ! $atEnd){ $check->violation($funcEnd->ent,$file,$start->line,$start->column,NOTEND); } } # $check->violation($entity,$file,$line,$column,ERR1,%1,%2); # the %1 and %2 are optional parameters # $check->violation(0,0,-1,-1,ERR1,%1,%2) #if no entity or location #my $optionVal = $check->option->lookup($name); }