.NAME Modification of loop counter in condition or statement

.DESCRIPTION
	The loop-counter shall not be modified within condition or statement. 

.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} {
  variable CurrentParameterList
  # Check all ... nodes
  utilities::filterTree $tree [list [namespace current]::check]
}

proc check { node } {
	set bigForStmt 0
	set hasDecl 0
	set hasTest 0
	set hasMod 0
	set hasBody 0

	# Look for "for" loop 
	if { [::utilities::isTreeOperator $node for] } {
		# Extract the three statements of the "for": declaration, test and modifier
		if {[expr [::logiscope::treeLength $node] > 0]} {
			set hasDecl 1
			set forDecl [::logiscope::treeDown $node 0]
		}
		if {[expr [::logiscope::treeLength $node] > 1]} {
			set hasTest 1
			set forTest [::logiscope::treeDown $node 1]
		}
		if {[expr [::logiscope::treeLength $node] > 2]} {
			set hasMod 1
			set forMod [::logiscope::treeDown $node 2]
		}
		if {[expr [::logiscope::treeLength $node] > 3]} {
			set hasBody 1
			set forBody [::logiscope::treeDown $node 3]
		}
		
		# Deduce the loop counter list from the Test statement
		# Test that modifiers don't set any counters using a function call
		set listOfCounters ""
		if  {[expr $hasTest == 1]} {
			set listOfCounters [getCounters $forTest]
			checkModifiers $forTest
		}
		# Test that the modifiers aren't set in the "for" body
		if  {[expr $hasBody == 1]} {
			checkBody $listOfCounters $forBody
		}	
	}
	return 1
}

	# This procedure deduces the counters from the test statement of a "for" loop
	proc getCounters {node} {
	set counters ""
		if { [::utilities::isTreeOperator $node expr] } {
			::logiscope::forobj son $node treeChild {
				lappend counters [getACounter $son]
			}
		} else {
			lappend counters [getACounter $node]
		}

		return $counters
	}
	
	# This procedure extracts the tested variable from a statement
	proc getACounter {node} {
		set modifiers [list lt le eq ge gt neq]
		if {[expr [lsearch $modifiers [::utilities::getName $node]] != -1]} {
		    set counterName [::utilities::getName [::logiscope::treeDown $node 0]]
			return $counterName
		}
	}
	
	# This procedure checks that the input statement does not use function calls to modify parameters
	proc checkModifiers {node} {
		::logiscope::forobj son $node treeChild {
			checkModifiers $son
		}
		if {[::utilities::isTreeOperator $node call]} {
			::logiscope::forobj attr [::logiscope::treeDown $node 1] treeChild {
				if {[::utilities::isTreeOperator $attr addr]} {
					::logiscope::addViolation $node
				}
			}
		}		
	}
	
	# This procedure checks that the "for" body does not modify any of the couters
	proc checkBody {counters node} {
		::logiscope::forobj son $node treeChild {
			checkBody $counters $son
		}
		# Define the list of operators able to modify a counter
		set setOperators [list ass plus_ass minus_ass post_incr post_decr pre_incr pre_decr]
		if {[expr [lsearch $setOperators [::utilities::getName $node]] != -1]} {
			# If a modifying operator was found, check if it applies to a counter
			if {[expr [lsearch $counters [::utilities::getName [::logiscope::treeDown $node 0]]] != -1]} {
				::logiscope::addViolation $node
			}
		}
	}


