.NAME Return of reference to automatic variable

.DESCRIPTION
A function shall not return a reference or a pointer to 
an automatic variable (including parameters), defined 
within the function. 

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

proc check { node } {
	if { [::utilities::isTreeOperator $node return] } {
		set expr [::logiscope::treeDown $node 0]
		set type [::Semantic::getTypeOf $expr]
		set check 0
		set type [::Types::getRealType $type]
		if { $type != -1 } {
			if { [expr [::Semantic::exists $type typeKind] && [string equal [::Semantic::getAttribute $type typeKind] "TypeReference"]] } {
				set pointedData [::Types::getRealType [::Semantic::getAttribute $type type]]
				if { "[::Semantic::getAttribute $pointedData name]" != "CString" } {
					set check 1
				}
			} else {
				# maybe return type of the function is reference
				set functionScope [::Scopes::getScopeOfCurrentFunction $node]
				set type [::Semantic::getAttribute $functionScope type]
				if {[string is integer "$type"]} {
					if {$type != -1} {
						if { [expr [::Semantic::exists $type typeKind] && [string equal [::Semantic::getAttribute $type typeKind] "TypeReference"]] } {
							set pointedData [::Types::getRealType [::Semantic::getAttribute $type type]]
							if { "[::Semantic::getAttribute $pointedData name]" != "CString" } {
								set check 1
							}
							set check 1
						}				
					}
				}
			}
		}
		if { $check } {
			# check if this is a reference to a local variable
			# ignoring parenthesis and addr after return
			# for dot, keeping only first identifier
			while { [::utilities::isTreeOperator $expr parenth_expr] ||
					[::utilities::isTreeOperator $expr dot] ||
					[::utilities::isTreeOperator $expr addr] } {
				set expr [::logiscope::treeDown $expr 0]
			}
			if { [::utilities::isTreeOperator $expr identifier] } {
				set var [::Scopes::getWithName [::Semantic::getScopeOfNode $expr] variables [::utilities::treeAtomString $expr] -1]
				if { $var != -1 } {
					if { [lsearch [::Semantic::getAttribute $var qualifier] static] < 0 } {
						set scopeKind [::Semantic::getAttribute [::Semantic::getAttribute $var scope] scopeKind]
						if { "$scopeKind" == "LOCAL" || "$scopeKind" == "FUNCTION" } {
							::logiscope::addViolation $expr
						}
					}
				}
			}
		}
		return 0
	}
	return 1
}
