.NAME Header file in multiple translation units

.DESCRIPTION
It shall be possible to include any header file in multiple 
translation units without violating the One Definition Rule. 

.COMMENT V7.0

.SEVERITY Required

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

.COMMAND tcl

.CODE

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

proc compute {standardName tree} {
  variable CurrentParameterList

  set suffix [file extension [::logiscope::fileName]]
  # check only headers
  if { "$suffix" == ".h" || "$suffix" == ".hh" || "$suffix" == ".hxx" || "$suffix" == ".hpp" } {
	# Check all fndef and extdecl nodes
	utilities::filterTree $tree [list [namespace current]::check]
  }
}

# check if declaration initializes a variable
proc withInitdecls { node } {
	set cla 0
	::logiscope::forobj decl $node treeChild {
		if { "[utilities::isTreeOperator $decl initdecls]" } {
			set cla 1
		}
	}
	return $cla
}
proc isStorageClass { node kindList } {
	set inline 0
	set ds [::logiscope::treeDown $node 0]
	::logiscope::forobj decl $ds treeChild {
		if { [::utilities::isTreeOperator $decl storage_class] } {
			if  { [lsearch -exact $kindList [::utilities::treeAtomString $decl]] >= 0 } {
				set inline 1
			}
		}
	}
	return $inline
}

proc isFunction { node } {
	set func 0
	set ini [::logiscope::treeDown $node 1]
	if { "$ini" != "NULL" } {
		set dcltr [::logiscope::treeDown $ini 0]
		if { "$dcltr" != "NULL" } {
			if { [::utilities::isTreeOperator [::logiscope::treeDown $dcltr 0] func_dcltr] } {
				set func 1
			}
		}
	}
	return $func
}

proc check { node } {
	switch -- [::utilities::treeOperatorName $node] {
		extdecl {
			if { ![isStorageClass $node {extern typedef}] && [withInitdecls $node] && ![isFunction $node] } {
				::logiscope::addViolation $node
			}
			return 0
		}
		fndef {
			if { ![isStorageClass $node inline] } {
				::logiscope::addViolation $node
			}
			return 0
		}
		template_def {
			return 0
		}
	}
	return 1
}
