.NAME Unreachable code

.DESCRIPTION
 A project shall not contain unreachable code. 

.COMMENT V7.0

.SEVERITY Required

.COMMENT
Please refer to the MISRA C++:2008 document for further details (www.misra-cpp.com)

.COMMAND tcl

.CODE

::logiscope::include -once common utilities.tcl

proc compute {standardName tree} {
 # Checking all goto, break nodes and calls to specific functions
 utilities::filterTree $tree [list [namespace current]::check ]
 
 # Checking switch
 utilities::filterTree $tree [list [namespace current]::checkSwitch]
}

proc checkBrother { node } {
	set brother [::logiscope::treeRight $node]
	if { ![::utilities::isNullObject $brother] && 
	     ![::utilities::isTreeOperator $brother label] &&
		 ![::utilities::isTreeOperator $brother case] &&
		 ![::utilities::isTreeOperator $brother default]} {
		::logiscope::addViolation $brother
	}
}

# checking if current branch ends with goto return exit or abrt 
# return 0 if no statement possible after node
proc checkIfContinue { node } {
    if {[::utilities::isNullObject $node]} {
        return 0
    }
	set ret 1
	switch -- [::utilities::treeOperatorName $node] {
		goto -
		break - 
		return {
			# end of current branch
			set ret 0
		}
		call {
			set name [::utilities::getName [::logiscope::treeGetSon $node PRIMARY]]
			if { "$name" == "exit" || "$name" == "abrt" } {
				set ret 0
			}
		}
		if {
			set thenPart [::logiscope::treeGetSon $node STMTS]
			set p1 [checkIfContinue $thenPart]
			set elsePart [::logiscope::treeGetSon $node STMTS_OPT]
			set p2 [checkIfContinue $elsePart]
			if { !$p1 && !$p2 } {
				set ret 0
			}
		}
		switch {
			# it will be better, for switch to verify if all cases have an exit
			# it is not done in this version
			checkIfContinue [::logiscope::treeGetSon $node STMTS]
			set ret 1
		}
		expr_stmt -
		stmts -
		compound {
			::logiscope::forobj stmt $node treeChild {
				set ret [checkIfContinue $stmt]
				if { !$ret } {
					checkBrother $stmt
				}
			}
		}
	}
	return $ret
}

# checking all branches of a switch
proc checkSwitch { node } {
	if { [::utilities::isTreeOperator $node switch] } {
        foreach son [::logiscope::treeGetSonFromPath $node {
            {STMTS stmts}
            {STMT* compound}
            {STMTS stmts}
            }] {
                set node [::logiscope::treeDown $son 0]
                if { ![::utilities::isTreeOperator $node case] &&
                     ![::utilities::isTreeOperator $node default] } {
					 ::logiscope::addViolation $node
                }
		}	
	}
	return 1
}

proc check { node } {
	if { [::utilities::isTreeOperator $node fndef] } {
		set stmts [::logiscope::treeGetSon $node FNBODY]
		::logiscope::forobj stmt $stmts treeChild {
			set ret [checkIfContinue $stmt]
			if { !$ret } {
				checkBrother $stmt
			}
		}
		return 0
	}
	return 1
}
