.NAME Unused type declarations

.DESCRIPTION
	A project shall not contain unused type declarations. 

.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 typedef types as unused
  if {[utilities::isFirstFile]} {
    initUsedTypes
  }
  
  # Check all ... nodes
  utilities::filterTree $tree [list [namespace current]::check]

  # Look for unused types
  if {[utilities::isLastFile]} {
    checkUnusedTypes
  }
}

proc initUsedTypes {} {
	foreach curScope [::Scopes::getAllScopes] {
		foreach curType [::Semantic::getAttribute $curScope types] {
			if {[string equal [::Semantic::getAttribute $curType typeKind] Typedef]} {
				::Semantic::setAttribute $curType used 0
			
			}
		}
	}
}

proc check { node } {
	if {[::utilities::isTreeOperator $node declaration_specifiers]} {
        foreach type [::logiscope::treeGetSonFromPath $node { {DECLARATION_SPECIFIER* *} }] {
			set curType [::Semantic::getTypeOf $type]
			if { $curType != -1 } {
                ::Semantic::setAttribute $curType used 1
            }
		}		
	}
	if {[::utilities::isTreeOperator $node scope]} {
		foreach subScope [::logiscope::treeGetSonFromPath $node { {TYPE_NAME+ *} }] {
			set foundType [processType [::utilities::getName $subScope] [::Semantic::getScopeOfNode $node]]
			if { $foundType != -1 } {
                ::Semantic::setAttribute $foundType used 1
            }			
		}
	}
	
	if {[::utilities::isTreeOperator $node template_arg_list]} {
		utilities::filterTree $node [list [namespace current]::checkTemplateTypes ]
	}
	
	return 1
}

proc checkTemplateTypes {node} {
	if {[::utilities::isTreeOperator $node type_specifiers]} {
	foreach typeId [::logiscope::treeGetSonFromPath $node { {TYPE_SPECIFIER* *} }] {
			set foundType [processType [::utilities::getName $typeId] [::Semantic::getScopeOfNode $node]]
			if { $foundType != -1 } {
				::Semantic::setAttribute $foundType used 1
			}			
		}
	}
	return 1
}

proc processType {typeName curScope} {
	set curType [::Scopes::getWithName $curScope types $typeName -1]
	if {$curType == -1} {
		if {$curScope != -1} {
			set fatherScope [::Semantic::getAttribute $curScope super]
				if {$fatherScope != -1} {
					return [processType $typeName $fatherScope]
				}
		} else {
			return -1
		}
	}
	return $curType
}

# Parse all types of all scopes, and add violation for each unused variable (i.e declared but not used)
proc checkUnusedTypes {} {
	foreach curScope [::Scopes::getAllScopes] {
		foreach curType [::Semantic::getAttribute $curScope types] {
			if {[string equal [::Semantic::getAttribute $curType typeKind] Typedef]} {
				if {[expr [::Semantic::getAttribute $curType used] == 0]} {
					#::logiscope::addViolation 
					# Violation $filename $pos $end $numLine $standardName "message" 
					::Semantic::violation $curType "MISRA_0_1_5" "MISRA_0_1_5 - A project shall not contain unused type declarations."
				}
			}
		}
	}
}
