.NAME All defined functions called

.DESCRIPTION
	Every defined function shall be called at least once. 

.COMMENT V7.0

.SEVERITY Required

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

.COMMAND tcl

.REQUIRED cpp_semantic

.CODE

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

proc compute {standardName tree} {
  # Initialize the functions declarations as unused
	if {[utilities::isFirstFile]} {
		initUsedFunctions
	}
#::Scopes::dump "" [::Scopes::getScopeGlobalId]
	# Check all ... nodes
	utilities::filterTree $tree [list [namespace current]::check]
  
	# Look for unused functions
	if {[utilities::isLastFile]} {
		checkUnusedFunctions  
	}
}

proc initUsedFunctions {} {
	foreach curScope [::Scopes::getAllScopes] {
		foreach curFunction [::Semantic::getAttribute $curScope functions] {
			# Prototypes are not concerned by this rule
			if {[::Semantic::exists $curFunction withStatements]} {
				# Main functions are not concerned by this rule
				set fName [::Semantic::getAttribute $curFunction name]
				# destructors are automatically called
				if { [string range $fName 0 0] == "~" } {
					::Semantic::setAttribute $curFunction used 1
				} else {
					if {[expr [lsearch [list main WinMain DllMain] $fName] == -1]} {
						::Semantic::setAttribute $curFunction used 0
					}
				}
			}
		}
	}
}

proc check { node } {
	# checking all nodes associated to an identifier
	switch -- [::utilities::treeOperatorName $node] {
		identifier -
		dot -
		arrow -
		qualified_id {
			# ignored if declaration of function
			set father [::logiscope::treeUp $node]
			if { ![::utilities::isTreeOperator $father func_dcltr] } {
				# searching associated semantic object
				set semObj [::Semantic::getSemanticObject $node]
				if { $semObj != -1 } {
					# if function, then setting it as used
					if { "[::Semantic::getAttribute $semObj kind]" == "scope" &&
					     "[::Semantic::getAttribute $semObj scopeKind]" == "FUNCTION"} {
						::Semantic::setAttribute $semObj used 1
					}
				}
				return 0
			}
		}
	}
	return 1
}

# Parse all variables of all scopes, and add violation for each unused function (i.e declared but not used)
proc checkUnusedFunctions {} {
	foreach curScope [::Scopes::getAllScopes] {
		foreach curFunc [::Semantic::getAttribute $curScope functions] {
			if {[::Semantic::exists $curFunc used] && [expr [::Semantic::getAttribute $curFunc used] == 0]} {
				#::logiscope::addViolation 
				# Violation $filename $pos $end $numLine $standardName "message" 
				::Semantic::violation $curFunc "MISRA_Rule0-1-10" "MISRA_Rule0-1-10 - Every defined function shall be called at least once."
			}
		}
	}
}
