.NAME Constructor and base classes

.DESCRIPTION
	All constructors of a class should explicitly call a 
constructor for all of its immediate base classes and all 
virtual base classes. 

.COMMENT V7.0

.SEVERITY Advisory

.COMMENT
Please refer to the MISRA C++:2008 document for further details (www.misra-cpp.com)
LIMITATION: This rule checks that base class constructors are called in the initialization list, separated by colons.
It does not check that base class constructors are called within the constructor body.

.REQUIRED cpp_semantic

.COMMAND tcl

.CODE

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

proc compute {standardName tree} {

	# Check all ... nodes
	utilities::filterTree $tree [list [namespace current]::check]
}

# Build the list of base classes of a class
proc getBaseClasses {curClass} {
	set baseClasses ""
	# Does the class has at least one base class
	if { [::Semantic::exists $curClass ancestors] } {
		set classAncestors [::Semantic::getAttribute $curClass ancestors]
		if {[expr [llength $classAncestors] >= 1]} {
			foreach curUpClass $classAncestors {
				set curClass [lindex $curUpClass 1]
				set curClassName [::Semantic::getAttribute $curClass name]
				lappend baseClasses $curClassName
			}
		}
	}
	return $baseClasses
}


proc check {node} {
	# Look for function definitions
	if {[::utilities::isTreeOperator $node fndef]} {
		set declarator [::logiscope::treeGetSon $node DECLARATOR]
		set funcName [::utilities::getName $declarator]
		# Retrieve the semantic node
		set funcNode [::Semantic::getScopeOfNode $node]
		# If the function belongs to a class, process it if it's a constructor
		if {[::Semantic::exists $funcNode class]} {
			set funcClass [::Semantic::getAttribute $funcNode class]
			if {$funcClass != -1} {
				set funcClassName [::Semantic::getAttribute $funcClass name]
				set myRegexp "regexp \{$funcClassName\..*\} \"$funcName\""
				if {[expr [eval $myRegexp] == 1]} {
					set myRegsub "regsub \{$funcClassName\.\} $funcName \"\" funcName"
					eval $myRegsub
				}
				
				if {[string equal $funcClassName $funcName]} {
					# Retrieve the constructor initializers, if any
					::logiscope::forobj curChild $node treeChild {
						set initializers ""
						if {[string equal [::utilities::getName $curChild] ctor_initializer]} {
							set memberInitList [::logiscope::treeGetSon $curChild MEMBER_INIT_LIST]
							::logiscope::forobj memberInit $memberInitList treeChild {
								set curMemberName [::logiscope::treeGetSon $memberInit MEMBER_NAME]
								lappend initializers [::utilities::getName $curMemberName]
							}
						}
					}
					# Check if all base classes constructors are called
					set allClear 1
					foreach curBaseClass [getBaseClasses $funcClass] {
						if {[expr [lsearch $initializers $curBaseClass] == -1]} {
							set allClear 0
						}
					}
					
					if {[expr $allClear == 0]} {
						::logiscope::addViolation $node
					}
				}
			}		
		}
	}
	return 1
}