.NAME Modification of loop counter

.DESCRIPTION
	The loop-counter shall be modified by one of: --, ++, 
-=n, or +=n; where n remains constant for the duration 
of the loop. 

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

# This procedure checks all "for" loops for invalid loop counter handling
proc check { node } {
	if { [::utilities::isTreeOperator $node for] } {
	    # Extract the modifier part of the "for" loop
		set modList [processForModifiers [::logiscope::treeDown $node 2]]
		# If the modifiers used one (or more) variables as increments, we must check that this increment is not modified in the for body
		if {[expr [llength $modList] > 0]} {
			checkVarUsage [::logiscope::treeDown $node 3] $modList
		}
	}
	return 1
}

# This procedure analyzes a "for" loop modifier statement and produces a list of action/identifier for actions that can lead to a violation
# These actions are +=, -= and function calls
# Example: for ( i = 1, j = 0, k = 0; j!=3 , i != 10, k != 100; --i, j+=n, k = f());
# The modifier statement is --i, j+=n
# This procedure 
# - adds a violation on the k = f() affectation 
# - and returns n, which mustn't be modified within the for body
proc processForModifiers {node} {
  set resultList ""
  if { [::utilities::isTreeOperator $node expr] } {
	::logiscope::forobj son $node treeChild {
		# For each expression term, check the modifier
		set newItem [checkModifier $son]
		if {[expr [lsearch $resultList $newItem] == -1]} {
			set resultList [concat $resultList $newItem]
		}
	}
  } else {
	set newItem [checkModifier $node]
	if {[expr [lsearch $resultList $newItem] == -1]} {
		set resultList [concat $resultList $newItem]
	}
  }
  return $resultList
}

# This procedure checks a single "for" modifier, detecting
# - actual violations (usage of function calls)
# - potential violations (usage of variables as increments)
# It raises a violation when needed, and returns the variable name if necessary
proc checkModifier {node} {
  set resultList ""
  # Retrieve the node's operator and name
  set curOpe [::logiscope::treeOperator $node]
  set curOpeName [::logiscope::opName $curOpe]
  # If the operator is a +=, -= or =, process it
  if {[expr [lsearch [list plus_ass minus_ass ass ] $curOpeName] != -1]} {
	set actionNode [::logiscope::treeDown $node 1]
	# Using function calls in modifiers is forbidden
	if { [::utilities::isTreeOperator $actionNode call] } {
		::logiscope::addViolation $actionNode
	} else {
	    # Find the parameter value	
		set paramValue [::utilities::getName [::logiscope::treeDown $node 1]]
		# Non-numerical parameters (i.e variables) can lead to a violation if the variable is modified in the "for" body
		# These variable names are added to the return list
		if {[expr ![string is integer $paramValue] && ![string is double $paramValue]]} {
			set resultList $paramValue
		}
	}
  }
  
  return $resultList
 }
 
 # This procedure checks if a given set of variables are modified in a sub-tree
 # Modification means being left part of a =, += or -= statement, or argument of a function call
 proc checkVarUsage {node varList} {
	# Check if function calls use variables from varList as parameters 
	if {[::utilities::isTreeOperator $node call]} {
		::logiscope::forobj curExpr [::logiscope::treeGetSon $node EXPRLIST] treeChild {
			if {[expr [lsearch $varList [::utilities::getName $curExpr]] != -1]} {
				::logiscope::addViolation $node
			}
		}
	}

	# Recurse
	::logiscope::forobj son $node treeChild {
		checkVarUsage $son $varList
	}
	
	# Check if variables from varList are modified
	if {[expr [lsearch [list ass plus_ass minus_ass] [::utilities::getName $node]] != -1]} {
		set affectedVar [::utilities::getName [::logiscope::treeDown $node 0]]
		if {[expr [lsearch $varList $affectedVar] != -1]} {
			::logiscope::addViolation $node
		}
	}
 }
 
