.NAME Default clause in switch

.DESCRIPTION
The final clause of a switch statement shall be the  default-clause.

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

proc check { node } {
	if { [::utilities::isTreeOperator $node switch] } {
		set defaultSeen 0
		set stmts [::logiscope::treeDown $node 1]
		set compound [::logiscope::treeDown $stmts 0]
		if { "$compound" != "NULL" && [::utilities::isTreeOperator $compound compound] } {
			# switch with compounds
			set listCases {}
			::logiscope::forobj inst [::logiscope::treeDown $compound 0] treeChild {
				set instName [::utilities::treeOperatorName $inst]
				if { "$instName" == "case" } {
					# remember: default has to be the last one
					set defaultSeen 0
					lappend listCases [::utilities::treeAtomString [::logiscope::treeDown $inst 0]]
				} elseif { "$instName" == "default" } {
					set defaultSeen 1
				}
			}
		}
		if { !$defaultSeen } {
			# is it an enum ?
			set identifier [::logiscope::treeDown $node 0]
			set type [::Semantic::getTypeOf $identifier]
			if { $type != -1 } {
				while { "[::Semantic::getAttribute $type typeKind]" == "Typedef" } {
					set type [::Semantic::getAttribute $type type]
				}
				if { "[::Semantic::getAttribute $type typeKind]" == "TypeEnum" } {
					# enum: check all values in cases
					set valuesIdx [::Semantic::getAttribute $type enumValues]
					set values {}
					foreach v $valuesIdx {
						lappend values [::Semantic::getAttribute $v name]
					}
					set defaultSeen 1
					foreach v $values {
						if { [lsearch $listCases $v] < 0 } {
							set defaultSeen 0
							break
						}
					}
				}
			}
		}
		if { !$defaultSeen } {
			::logiscope::addViolation $node
		}
	}
	return 1
}
