MISRA 9.2 to 9.5 (#2954)

This commit is contained in:
kskjerve 2020-12-16 17:28:54 +01:00 committed by GitHub
parent c9d2e55ea9
commit d4860f500a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 648 additions and 299 deletions

View File

@ -30,6 +30,7 @@ try:
except ImportError:
pass
import misra_9
def grouped(iterable, n):
"""s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."""
@ -1496,263 +1497,19 @@ class MisraChecker:
self.reportError(token, 8, 14)
def misra_9_2(self, data):
# Holds information about a struct or union's element definition.
class ElementDef:
def __init__(self, elementType, name, valueType = None, dimensions = None):
self.elementType = elementType
self.name = name
self.valueType = valueType
self.dimensions = dimensions
misra_9.misra_9_x(self, data, 902)
# Return an array containing the size of each dimension of an array declaration,
# or coordinates of a designator in an array initializer,
# and the name token's valueType, if it exist.
#
# In the examples below, the ^ indicates the initial token passed to the function.
#
# Ex: int arr[1][2][3] = .....
# ^
# returns: [1,2,3], valueType
#
# Ex: int arr[3][4] = { [1][2] = 5 }
# ^
# returns [1,2], None
def getArrayDimensionsAndValueType(token):
dimensions = []
def misra_9_3(self, data):
misra_9.misra_9_x(self, data, 903)
while token.str == '*':
if token.astOperand2 is not None:
token = token.astOperand2
else:
token = token.astOperand1
def misra_9_4(self, data):
misra_9.misra_9_x(self, data, 904)
while token and token.str == '[':
if token.astOperand2 is not None:
dimensions.insert(0, token.astOperand2.getKnownIntValue())
token = token.astOperand1
elif token.astOperand1 is not None:
dimensions.insert(0, token.astOperand1.getKnownIntValue())
break
else:
dimensions = None
break
valueType = token.valueType if token else None
return dimensions, valueType
# Returns a list of the struct elements as StructElementDef in the order they are declared.
def getRecordElements(valueType):
if not valueType or not valueType.typeScope:
return []
elements = []
for variable in valueType.typeScope.varlist:
if variable.isArray:
dimensions, arrayValueType = getArrayDimensionsAndValueType(variable.nameToken.astParent)
elements.append(ElementDef('array', variable.nameToken.str, arrayValueType, dimensions))
elif variable.isClass:
elements.append(ElementDef('class', variable.nameToken.str, variable.nameToken.valueType))
else:
elements.append(ElementDef('element', variable.nameToken.str))
return elements
# Checks if the initializer conforms to the dimensions of the array declaration
# at a given level.
# Parameters:
# token: root node of the initializer tree
# dimensions: dimension sizes of the array declaration
# valueType: the array type
def checkArrayInitializer(token, dimensions, valueType):
level = 0
levelOffsets = [] # Calculated when designators in initializers are used
elements = getRecordElements(valueType) if valueType.type == 'record' else None
isFirstElement = False
while token:
if token.str == ',':
token = token.astOperand1
isFirstElement = False
continue
if token.isAssignmentOp and not token.valueType:
designator, _ = getArrayDimensionsAndValueType(token.astOperand1)
# Calculate level offset based on designator in initializer
levelOffsets[-1] = len(designator) - 1
token = token.astOperand2
isFirstElement = False
effectiveLevel = sum(levelOffsets) + level
# Zero initializer is ok at any level
isZeroInitializer = (isFirstElement and token.str == '0')
# String initializer is ok at one level below value level unless array to pointers
isStringInitializer = token.isString and effectiveLevel == len(dimensions) - 1 and valueType.pointer == len(dimensions)
if effectiveLevel == len(dimensions) or isZeroInitializer or isStringInitializer:
if not isZeroInitializer and not isStringInitializer:
isFirstElement = False
if valueType.type == 'record':
if token.isName:
if not token.valueType.typeScope == valueType.typeScope:
self.reportError(token, 9, 2)
return False
else:
if not checkObjectInitializer(token, elements):
return False
elif token.str == '{':
self.reportError(token, 9, 2)
return False
# String initializer is not ok at this level, unless array to pointers
# (should be pointer to const-qualified char, but that check is out of scope for 9.2)
elif token.isString and valueType.pointer == len(dimensions):
self.reportError(token, 9, 2)
return False
# Done evaluating leaf node - go back up to find next astOperand2
while token:
# Done checking once level is back to 0 (or we run out of parents)
if level == 0 or not token.astParent:
return True
if token.astParent.astOperand1 == token and token.astParent.astOperand2:
token = token.astParent.astOperand2
break
else:
token = token.astParent
if token.str == '{':
level = level - 1
levelOffsets.pop()
effectiveLevel = sum(levelOffsets) + level
elif token.str == '{' :
if not token.astOperand1:
# Empty initializer
self.reportError(token, 9, 2)
return False
token = token.astOperand1
level = level + 1
levelOffsets.append(0)
isFirstElement = True
else:
self.reportError(token, 9, 2)
return False
return True
# Checks if the initializer conforms to the elements of the struct or union
# Parameters:
# token: root node of the initializer tree
# elements: the elements as specified in the declaration
def checkObjectInitializer(token, elements):
if not token:
return True
# Initializer must start with a curly bracket
if not token.str == '{':
self.reportError(token, 9, 2)
return False
# Empty initializer is not ok { }
if not token.astOperand1:
self.reportError(token, 9, 2)
return False
token = token.astOperand1
# Zero initializer is ok { 0 }
if token.str == '0' :
return True
pos = None
while(token):
if token.str == ',':
token = token.astOperand1
else:
if pos is None:
pos = 0
if token.isAssignmentOp:
if token.astOperand1.str == '.':
elementName = token.astOperand1.astOperand1.str
pos = next((i for i, element in enumerate(elements) if element.name == elementName), len(elements))
token = token.astOperand2
if pos >= len(elements):
self.reportError(token, 9, 2)
return False
element = elements[pos]
if element.elementType == 'class':
if token.isName:
if not token.valueType.typeScope == element.valueType.typeScope:
self.reportError(token, 9, 2)
return False
else:
subElements = getRecordElements(element.valueType)
if not checkObjectInitializer(token, subElements):
return False
elif element.elementType == 'array':
if not checkArrayInitializer(token, element.dimensions, element.valueType):
return False
elif token.str == '{':
self.reportError(token, 9, 2)
return False
# The assignment represents the astOperand
if token.astParent.isAssignmentOp:
token = token.astParent
if not token == token.astParent.astOperand2:
pos = pos + 1
token = token.astParent.astOperand2
else:
token = None
return True
# ------
for variable in data.variables:
if not variable.nameToken:
continue
nameToken = variable.nameToken
# Check if declaration and initialization is
# split into two separate statements in ast.
if nameToken.next and nameToken.next.isSplittedVarDeclEq:
nameToken = nameToken.next.next
# Find declarations with initializer assignment
eq = nameToken
while not eq.isAssignmentOp and eq.astParent:
eq = eq.astParent
# We are only looking for initializers
if not eq.isAssignmentOp or eq.astOperand2.isName:
continue
if variable.isArray :
dimensions, valueType = getArrayDimensionsAndValueType(eq.astOperand1)
if dimensions is None:
continue
checkArrayInitializer(eq.astOperand2, dimensions, valueType)
elif variable.isClass:
if not nameToken.valueType:
continue
valueType = nameToken.valueType
if valueType.type == 'record':
elements = getRecordElements(valueType)
checkObjectInitializer(eq.astOperand2, elements)
def misra_9_5(self, rawTokens):
for token in rawTokens:
if simpleMatch(token, '[ ] = { ['):
self.reportError(token, 9, 5)
def misra_9_5(self, data, rawTokens):
misra_9.misra_9_x(self, data, 905, rawTokens)
#for token in rawTokens:
# if simpleMatch(token, '[ ] = { ['):
# self.reportError(token, 9, 5)
def misra_10_1(self, data):
for token in data.tokenlist:
@ -3365,8 +3122,10 @@ class MisraChecker:
if cfgNumber == 0:
self.executeCheck(814, self.misra_8_14, data.rawTokens)
self.executeCheck(902, self.misra_9_2, cfg)
self.executeCheck(903, self.misra_9_3, cfg)
self.executeCheck(904, self.misra_9_4, cfg)
if cfgNumber == 0:
self.executeCheck(905, self.misra_9_5, data.rawTokens)
self.executeCheck(905, self.misra_9_5, cfg, data.rawTokens)
self.executeCheck(1001, self.misra_10_1, cfg)
self.executeCheck(1002, self.misra_10_2, cfg)
self.executeCheck(1004, self.misra_10_4, cfg)

492
addons/misra_9.py Normal file
View File

@ -0,0 +1,492 @@
# Holds information about an array, struct or union's element definition.
class ElementDef:
def __init__(self, elementType, name, valueType, dimensions = None):
self.elementType = elementType # 'array', 'record' or 'value'
self.name = str(name)
self.valueType = valueType
self.children = []
self.dimensions = dimensions
self.parent = None
self.isDesignated = False
self.isPositional = False
self.numInits = 0
self.childIndex = -1
self.isFlexible = False
self.structureViolationToken = None
def __repr__(self):
inits = ""
if self.isPositional:
inits += 'P'
if self.isDesignated:
inits += 'D'
if not (self.isPositional or self.isDesignated) and self.numInits == 0:
inits += '_'
if (self.numInits > 1):
inits += str(self.numInits)
attrs = ["childIndex", "elementType", "valueType"]
return "{}({}, {}, {})".format(
"ED",
self.getLongName(),
inits,
", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs))
)
@property
def isArray(self):
return self.elementType == 'array'
@property
def isRecord(self):
return self.elementType == 'record'
@property
def isValue(self):
return self.elementType == 'value'
def getLongName(self):
return self.parent.getLongName() + "." + self.name if self.parent else self.name
def getInitDump(self):
t = []
if self.isPositional:
t.append('P')
if self.isDesignated:
t.append('D')
if self.numInits == 0:
t.append('_')
if (self.numInits > 1):
t.append(str(self.numInits))
myDump = "".join(t)
if len(self.children):
childDumps = []
for c in self.children:
childDumps.append(c.getInitDump())
if self.structureViolationToken is not None:
myDump += "!"
myDump += "{ " + ", ".join(childDumps) + " }"
return myDump
def addChild(self, child):
self.children.append(child)
child.parent = self
def getNextChild(self):
self.childIndex += 1
return self.getChildByIndex(self.childIndex)
def getChildByIndex(self, index):
if self.isFlexible:
while len(self.children) <= index:
createChild(self, self.flexibleToken, len(self.children))
return self.children[index] if index >= 0 and len(self.children) > index else None
def getChildByName(self, name):
for c in self.children:
if c.name == name:
return c
return None
def getNextValueElement(self, root):
current = self
while current != root:
# Get next index of parent
i = current.parent.children.index(current) + 1
# Next index of parent exists
if i < len(current.parent.children):
current = current.parent.children[i]
return current.getFirstValueElement()
# Next index of parent doesn't exist. Move up
current = current.parent
return None
def getFirstValueElement(self):
current = self
# Move to first child as long as children exists
next_child = current.getChildByIndex(0)
while next_child:
current = next_child
next_child = current.getChildByIndex(0)
return current
def getLastValueElement(self):
current = self
# Move to last child as long as children exists
while len(current.children) > 0:
current = current.children[-1]
return current
def getChildByValueElement(self, ed):
potentialChild = ed
while potentialChild and not potentialChild in self.children:
potentialChild = potentialChild.parent
return self.children[self.children.index(potentialChild)] if potentialChild else None
def getEffectiveLevel(self):
if self.parent and self.parent.elementType == "array":
return self.parent.getEffectiveLevel() + 1
else:
return 0
def setInitialized(self, designated=False, positional=False):
if designated:
self.isDesignated = True
if positional or not designated:
self.isPositional = True
self.numInits += 1
def initializeChildren(self):
for child in self.children:
child.setInitialized(positional=True)
child.initializeChildren()
def unset(self):
self.isDesignated = False
self.isPositional = False
# Unset is always recursive
for child in self.children:
child.unset()
def markStuctureViolation(self, token):
if self.name == '->':
self.children[0].markStuctureViolation(token)
elif not self.structureViolationToken:
self.structureViolationToken = token
def markAsFlexibleArray(self, token):
self.flexibleToken = token;
self.isFlexible = True
def markAsCurrent(self):
if self.parent:
if self.name == '<-':
self.parent.childIndex = self.parent.children.index(self.children[0])
else:
self.parent.childIndex = self.parent.children.index(self)
self.parent.markAsCurrent()
def isAllChildrenSet(self):
myself = len(self.children) == 0 and (self.isDesignated or self.isPositional)
mychildren = len(self.children) > 0 and all([child.isAllChildrenSet() for child in self.children])
return myself or mychildren
def isAllSet(self):
return all([child.isPositional or child.isDesignated for child in self.children])
def isOnlyDesignated(self):
return all([not child.isPositional for child in self.children])
def isMisra92Compliant(self):
return self.structureViolationToken is None and all([child.isMisra92Compliant() for child in self.children])
def isMisra93Compliant(self):
if self.elementType == 'array':
result = self.isAllChildrenSet() or \
((self.isAllSet() or \
self.isOnlyDesignated()) and \
all([not (child.isDesignated or child.isPositional) or child.isMisra93Compliant() for child in self.children]))
return result
elif self.elementType == 'record':
result = all([child.isMisra93Compliant() for child in self.children])
return result
else:
return True
def isMisra94Compliant(self):
return self.numInits <= 1 and all([child.isMisra94Compliant() for child in self.children])
def isMisra95Compliant(self):
return not self.isFlexible or all([not child.isDesignated for child in self.children])
# Parses the initializers and uodate the ElementDefs status accordingly
class InitializerParser:
def __init__(self):
self.token = None
self.root = None
self.ed = None
self.rootStack = []
def parseInitializer(self, root, token):
self.root = root
self.token = token
dummyRoot = ElementDef('array', '->', self.root.valueType)
dummyRoot.children = [self.root]
self.rootStack = []
self.root = dummyRoot
self.ed = self.root.getFirstValueElement()
isFirstElement = False
isDesignated = False
while self.token:
if self.token.str == ',':
self.token = self.token.astOperand1
isFirstElement = False
# Designated initializer ( [2]=... or .name=... )
elif self.token.isAssignmentOp and not self.token.valueType:
self.popFromStackIfExitElement()
self.ed = getElementByDesignator(self.root, self.token.astOperand1)
if self.ed:
# Update root
self.pushToRootStackAndMarkAsDesignated()
# Make sure ed points to valueElement
self.ed = self.ed.getFirstValueElement()
self.token = self.token.astOperand2
isFirstElement = False
isDesignated = True
elif self.token.str == '{':
nextChild = self.root.getNextChild()
if nextChild:
if nextChild.isArray or nextChild.isRecord:
nextChild.unset()
nextChild.setInitialized(isDesignated)
self.ed = nextChild.getFirstValueElement()
isDesignated = False
elif nextChild.valueType is None:
# No type information available - unable to check structure - assume correct initialization
nextChild.setInitialized(isDesignated)
self.unwindAndContinue()
continue
elif self.token.astOperand1:
# Create dummy nextChild to represent excess levels in initializer
dummyRoot = ElementDef('array', '<-', self.root.valueType)
dummyRoot.parent = self.root
dummyRoot.childIndex = 0
dummyRoot.children = [nextChild]
nextChild.parent = dummyRoot
self.root.markStuctureViolation(self.token)
# Fake dummy as nextChild (of current root)
nextChild = dummyRoot
if self.token.astOperand1:
self.root = nextChild
self.token = self.token.astOperand1
isFirstElement = True
else:
# {}
if self.root.name == '<-':
self.root.parent.markStuctureViolation(self.token)
else:
self.root.markStuctureViolation(self.token)
self.ed = None
self.unwindAndContinue()
else:
if self.ed and self.ed.isValue:
if not isDesignated and len(self.rootStack) > 0 and self.rootStack[-1][1] == self.root:
self.rootStack[-1][0].markStuctureViolation(self.token)
if isFirstElement and self.token.str == '0' and self.token.next.str == '}':
# Zero initializer causes recursive initialization
self.root.initializeChildren()
elif self.token.isString and self.ed.valueType.pointer > 0:
if self.ed.valueType.pointer - self.ed.getEffectiveLevel() == 1:
if self.ed.parent != self.root:
self.root.markStuctureViolation(self.token)
self.ed.setInitialized(isDesignated)
elif self.ed.valueType.pointer == self.ed.getEffectiveLevel():
if(self.root.name != '->' and self.ed.parent.parent != self.root) or (self.root.name == '->' and self.root.children[0] != self.ed.parent):
self.root.markStuctureViolation(self.token)
else:
self.ed.parent.setInitialized(isDesignated)
self.ed.parent.initializeChildren()
else:
if self.ed.parent != self.root:
# Check if token is correct value type for self.root.children[?]
child = self.root.getChildByValueElement(self.ed)
if child.elementType != 'record' or self.token.valueType.type != 'record' or child.valueType.typeScope != self.token.valueType.typeScope:
self.root.markStuctureViolation(self.token)
self.ed.setInitialized(isDesignated)
# Mark all elements up to root with positional or designated
# (for complex designators, or missing structure)
parent = self.ed.parent
while parent and parent != self.root:
parent.isDesignated = isDesignated if isDesignated and not parent.isPositional else parent.isDesignated
parent.isPositional = not isDesignated if not isDesignated and not parent.isDesignated else parent.isPositional
parent = parent.parent
isDesignated = False
self.unwindAndContinue()
def pushToRootStackAndMarkAsDesignated(self):
new = self.ed.parent
if new != self.root:
# Mark all elements up to self.root root as designated
parent = new
while parent != self.root:
parent.isDesignated = True
parent = parent.parent
self.rootStack.append((self.root, new))
new.markAsCurrent()
new.childIndex = new.children.index(self.ed) - 1
self.root = new
def popFromStackIfExitElement(self):
if len(self.rootStack) > 0 and self.rootStack[-1][1] == self.root:
old = self.rootStack.pop()[0]
old.markAsCurrent()
self.root = old
def unwindAndContinue(self):
while self.token:
if self.token.astParent.astOperand1 == self.token and self.token.astParent.astOperand2:
if self.ed:
self.ed.markAsCurrent()
self.ed = self.ed.getNextValueElement(self.root)
self.token = self.token.astParent.astOperand2
break
else:
self.token = self.token.astParent
if self.token.str == '{':
self.ed = self.root.getLastValueElement()
self.ed.markAsCurrent()
# Cleanup if root is dummy node representing excess levels in initializer
if self.root and self.root.name == '<-':
self.root.children[0].parent = self.root.parent
self.root = self.root.parent
if self.token.astParent == None:
self.token = None
break
def misra_9_x(self, data, rule, rawTokens = None):
parser = InitializerParser()
for variable in data.variables:
if not variable.nameToken:
continue
nameToken = variable.nameToken
# Check if declaration and initialization is
# split into two separate statements in ast.
if nameToken.next and nameToken.next.isSplittedVarDeclEq:
nameToken = nameToken.next.next
# Find declarations with initializer assignment
eq = nameToken
while not eq.isAssignmentOp and eq.astParent:
eq = eq.astParent
# We are only looking for initializers
if not eq.isAssignmentOp or eq.astOperand2.isName:
continue
if variable.isArray or variable.isClass:
ed = getElementDef(nameToken, rawTokens)
parser.parseInitializer(ed, eq.astOperand2)
# print(rule, nameToken.str + '=', ed.getInitDump())
if rule == 902 and not ed.isMisra92Compliant():
self.reportError(nameToken, 9, 2)
if rule == 903 and not ed.isMisra93Compliant():
self.reportError(nameToken, 9, 3)
if rule == 904 and not ed.isMisra94Compliant():
self.reportError(nameToken, 9, 4)
if rule == 905 and not ed.isMisra95Compliant():
self.reportError(nameToken, 9, 5)
def getElementDef(nameToken, rawTokens = None):
if nameToken.variable.isArray:
ed = ElementDef("array", nameToken.str, nameToken.valueType)
createArrayChildrenDefs(ed, nameToken.astParent, rawTokens)
elif nameToken.variable.isClass:
ed = ElementDef("record", nameToken.str, nameToken.valueType)
createRecordChildrenDefs(ed)
else:
ed = ElementDef("value", nameToken.str, nameToken.valueType)
return ed
def createArrayChildrenDefs(ed, token, rawTokens = None):
if token.str == '[':
if rawTokens is not None:
foundToken = next(rawToken for rawToken in rawTokens if rawToken.file == token.file and rawToken.linenr == token.linenr and rawToken.column == token.column)
if foundToken and foundToken.next and foundToken.next.str == ']':
ed.markAsFlexibleArray(token)
if token.astOperand2 is not None:
for i in range(token.astOperand2.getKnownIntValue()):
createChild(ed, token, i)
else:
ed.markAsFlexibleArray(token)
def createChild(ed, token, name):
if token.astParent and token.astParent.str == '[':
child = ElementDef("array", name, ed.valueType)
createArrayChildrenDefs(child, token.astParent)
else:
if ed.valueType and ed.valueType.type == "record":
child = ElementDef("record", name, ed.valueType)
createRecordChildrenDefs(child)
else:
child = ElementDef("value", name, ed.valueType)
ed.addChild(child)
def createRecordChildrenDefs(ed):
valueType = ed.valueType
if not valueType or not valueType.typeScope:
return
for variable in valueType.typeScope.varlist:
child = getElementDef(variable.nameToken)
ed.addChild(child)
def getElementByDesignator(ed, token):
while token.str in [ '.', '[' ]:
token = token.astOperand1
while ed and not token.isAssignmentOp:
token = token.astParent
if token.str == '[':
chIndex = -1
if token.astOperand2 is not None:
chIndex = token.astOperand2.getKnownIntValue()
elif token.astOperand1 is not None:
chIndex = token.astOperand1.getKnownIntValue()
if not ed.isArray:
ed.markStuctureViolation(token)
ed = ed.getChildByIndex(chIndex)
elif token.str == '.':
name = ""
if token.astOperand2 is not None:
name = token.astOperand2.str
elif token.astOperand1 is not None:
name = token.astOperand1.str
if not ed.isRecord:
ed.markStuctureViolation(token)
ed = ed.getChildByName(name)
return ed

View File

@ -295,38 +295,90 @@ enum misra_8_12_e { misra_e1 = sizeof(int), misra_e2}; // no-crash
void misra_8_14(char * restrict str) {(void)str;} // 8.14
void misra_9_2() {
int empty_init[2][2] = { }; // 9.2
int empty_nested_init[2][2] = { { } }; // 9.2
int zero_init_a[5] = { 0 };
int zero_init_b[5][2] = { 0 };
int zero_init_c[2][2] = { { 1, 2 }, { 0 } };
void misra_9_empty_or_zero_initializers() {
int a[2] = {}; // 9.2
int b[2][2] = {}; // 9.2
int c[2][2] = { {} }; // 9.2 9.3
int d[2][2] = { {}, {} }; // 9.2
int e[2][2] = { { 1 , 2 }, {} }; // 9.2
const char string_wrong_level_a[12] = { "Hello world" }; // 9.2
const char string_wrong_level_b[2][20] = "Hello world"; // 9.2
const char string_correct_level_a[] = "Hello world";
const char string_correct_level_b[2][12] = { "Hello world" };
const char *char_p_correct_level[2] = { "Hello", [1] = "world" };
const char *char_p_incorrect_level[1] = "Hello world"; // 9.2
int f[5] = { 0 };
int g[5][2] = { 0 };
int h[2][2] = { { 0 } }; // 9.3
int i[2][2] = { { 0 }, { 0 } };
int j[2][2] = { { 1, 2 }, { 0 } };
int k[2][2] = { [0] = { 1 , 2 }, { 0 } };
int l[1][2] = { { 0 }, [0] = { 1 } }; // 9.3 9.4
char **str_p = &char_p_correct_level[0];
char **str_p_array_correct_level[1] = { str_p };
char **str_p_array_incorrect_level[1] = { { str_p } }; // 9.2
typedef struct {
int a;
int b;
} struct1;
int array_init_incorrect_levels_a[3][2] = { 1, 2, 3, 4, 5, 6 }; // 9.2
int array_init_correct_levels_a[3][2] = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
int array_init_incorrect_levels_b[6] = { { 1, 2 }, { 3, 4 }, { 5, 6 } }; // 9.2
int array_init_correct_levels_b[6] = { 1, 2, 3, 4, 5, 6 };
struct1 m = { }; // 9.2
struct1 n = { 0 };
}
int array_incorrect_designator_a[1] = { [0][1] = 1 }; // 9.2
int array_incorrect_designator_b[1] = { [0] = { 1, 2 } }; // 9.2
int array_incorrect_designator_c[1][2] = { [0] = 1 }; // 9.2
int array_incorrect_designator_d[2][2] = { { 1, 2 }, [1][0] = {3, 4} }; // 9.2
int array_correct_designator_a[2] = { [0] = 1, 2 };
int array_correct_designator_b[2] = { [1] = 2, [0] = 1 };
int array_correct_designator_c[2][2] = { { 1, 2 }, [1] = {3, 4} };
int array_correct_designator_d[2][2] = { { 1, 2 }, [1][0] = 3, 4};
void misra_9_string_initializers() {
const char a[12] = { "Hello world" }; // 9.2
const char b[2][20] = "Hello world"; // 9.2 9.3
const char c[] = "Hello world";
const char d[15] = "Hello world";
const char e[1][12] = { "Hello world" };
const char *f[2] = { "Hello", [1] = "world" };
const char *g[1] = "Hello world"; // 9.2
const char h[2][15] = { { 0 }, "Hello world" };
char **str_p = &f[0];
char **i[1] = { str_p };
char **j[1] = { { str_p } }; // 9.2
}
void misra_9_array_initializers() {
char a[4] = { 1, 2, 3, 4 };
char b[2][2] = { {1, 2}, {3, 4} };
char c[2][2] = { 1, 2, 3, 4 }; // 9.2
char d[6] = { { 1, 2 }, { 3, 4 }, { 5, 6 } }; // 9.2 9.3
char e[2][2] = { {1, 2}, {4} }; // 9.3
char f[2][2] = { 1, 2, 3 }; // 9.2 9.3
char g[2][2] = { {1, 2, 3, 4} }; // 9.3
char h[2][2] = { { 1, { 2 } }, { 3, { 5 } } }; // 9.2
char i[2][2] = { { 1, { 2 } }, { 3 } }; // 9.2 9.3
char j[2][3] = { { 1, { 2 }, 3 }, { 4, { 5 }, 6 } }; // 9.2
char k[2][3] = { { 1, { 2 }, 3 }, { 4, { 5 } } }; // 9.2 9.3
char l[3] = { 1, { 2, 3 } }; // 9.2 9.3
}
void misra_9_array_initializers_with_designators() {
char a[1] = { [0][1] = 1 }; // 9.2
char b[1] = { [0] = { 1, 2 } }; // 9.2
char c[2][2] = { [0] = {1, 2, 3} };
char d[1][2] = { [0] = 1 }; // 9.2
char e[2][2] = { { 1, 2 }, [1][0] = {3, 4} }; // 9.2
char f[2] = { [0] = 1, 2 };
char g[2] = { [1] = 2, [0] = 1 };
char h[2][2] = { { 1, 2 }, [1] = { 3 } }; // 9.3
char i[2][2] = { { 1, 2 }, [1] = { 3, 4 } };
char j[2][2] = { { 1, 2 }, [1] = { [0] = 3 } };
char k[2][2] = { { 1, 2 }, [1][0] = 3 };
char l[2][2] = { { 1, 2 }, [1][0] = 3, 4}; // 9.2
char m[2][2] = { [0] = { [2] = 2 }, [1][5] = 4 };
char n[2][2] = { [0] = { 1 } }; // 9.3
char o[2][2] = { { 1 }, [1][0] = 3 }; // 9.3
char p[2][2] = { { 1, 2 }, { 3, 4 }, [1] = { 3 } }; // 9.3 9.4
char q[2][2] = { { 1, 2 }, { 1 }, [1] = { [1] = 3 } }; // 9.4
char r[2][2][2] = { [0][0] = { 1, 2 }, [1] = { [0] = {5, 6} } };
char s[2][2][2] = { [0][0] = { 1, 2 }, [1] = {5, 6, 7, 8}}; // 9.2
char t[2][2][2] = { [0][0] = { 1, 2 }, {3, 4}, [1] = {5, 6}}; // 9.2 9.3
char u[2][2][2] = { [0] = { 1, 2, {3, 4} } }; // 9.2
char v[2][2][2] = { [0] = { 1, 2, [1] = {3, 4} }}; // 9.2
}
void misra_9_struct_initializers() {
typedef struct {
int i1;
int i2;
@ -338,31 +390,77 @@ void misra_9_2() {
char c2[4];
} struct2;
typedef struct {
struct1 s[2][2];
} struct3;
struct3 sa[2] = { [1].s[1][0].i1 = 3, 4 }; // 9.2
struct1 sa = 1; // 9.2
struct1 sb = { 1, 2 };
struct2 sc = { 1, { 2 }, {4, 5, 6, 7} };
struct2 sd = { 1, { 2, 3 }, {4, 5, 6} }; // 9.3
struct2 se = { 1, 2, 3, 4, 5, 6, 7 }; // 9.2
struct2 sf = { 1, { 2, 3 }, 4, 5, 6, 7 }; // 9.2
struct2 sg = { 1, { 2 }, 4, 5, 6, 7 }; // 9.2
struct2 sh = { 1, { 2, 3 }, 4, 5, 6 }; // 9.2 9.3
struct2 si = { 1, 2, 3, {4,5,6,7} }; // 9.2
int a;
struct1 sj = { a = 1, 2 }; // 13.1
struct2 struct_empty_init = { }; // 9.2
struct2 struct_zero_init = { 0 };
struct1 struct_missing_brackets = 1; // 9.2
struct2 struct_correct_init = { 1, {2, 3}, {0} };
struct1 struct_array_incorrect_levels[2] = { 1, 2, 3, 4 }; // 9.2
struct1 struct_array_correct_levels[2] = { {1, 2}, {3, 4} };
struct1 struct_correct_designator_a = { .i2 = 2, .i1 = 1 };
struct2 struct_correct_designator_b = { .is1 = {2, 3}, { 4 } };
struct1 struct_correct_designator_c = { a = 1, 2 }; // 13.1
struct2 struct_incorrect_type = { .is1 = struct_correct_designator_b }; // 9.2
struct2 struct_correct_type = { .is1 = struct_correct_designator_a };
// Struct types
struct2 sta = { .is1 = sc }; // 9.2
struct2 stb = { .is1 = sb };
struct1 stc[1] = { sc }; // 9.2
struct1 std[1] = { sb };
struct1 struct_array_incorrect_type[1] = { struct_correct_designator_b }; // 9.2
struct1 struct_array_correct_type[1] = { struct_correct_designator_a };
// Struct designators
struct1 sda = { 1, .i2 = 2 };
struct2 sdb = { 1, { 2, .i2=3 }, .c2[1]=5 };
struct2 sdc = { 1, { 2, .i2=3 }, .c2 = { 5 } }; // 9.3
struct2 sdd = { 1, { 2, .i2=3 }, .c2 = 5 }; // 9.2
struct2 sde = { .is1 = { 2, 3 }, { 4, 5, 6, 7 } };
union misra_9_2_union { // 19.2
// Struct arrays
struct1 asa[2] = { {1,2}, {3,4} };
struct1 asb[2] = { {1}, {3,4} };
struct1 asc[2] = { {1,2} }; // 9.3
struct1 asd[2] = { 1,2, 3,4 }; // 9.2
struct1 ase[2] = { 1,2, 3 }; // 9.2
struct1 asf[2] = { 1,2 }; // 9.2 9.3
struct1 asg[2] = { [1].i1 = 3 };
struct3 ash[2] = { [1].s[1][0].i1 = 3 };
struct3 asi[2] = { [0] = { .s[0] = { { 1, 2 } }}}; // 9.3
struct3 asj[2] = { [0] = { .s[0] = { 1, 2 }}}; // 9.2 9.3
// Missing type information
dummy_struct dsa = { 1, .a = 2 };
dummy_struct dsb[2] = { {1,2}, {3,4} };
dummy_struct dsc[2][2] = { {1,2}, {3,4} };
dummy_struct dsd[2][2] = { 1, 2, 3, 4 }; // 9.2
dummy_struct dse[3] = { {1,2}, {3,4}, [1] = {5,6} }; // 9.3 9.4
dummy_struct dsd[] = { [0] = 1 }; // 9.5
}
void misra_9_2() {
union misra_9_2_union { // 19.2
char c;
struct1 i;
} u = { 3 }; // 19.2
} u = { 3 }; // 19.2
}
void misra_9_5() {
int x[] = {[0]=23}; // 9.5
char a[] = { 1, 2, 3 };
char b[] = { [2] = 5 }; // 9.5
char c[] = { 1, [1] = 5 }; // 9.5
char d[] = { [1] = 2, [0] = 1 }; // 9.5
char e[][2] = { { 1, 2 }, { 3, 4 } };
char f[][2] = { [1] = { 3, 4 } }; // 9.5
char g[][2] = { { 1, 2 }, [1] = { 3, 4 } }; // 9.5
char h[][2] = { [1] = { 1, 2 }, [0] = { 3, 4 } }; // 9.5
}
typedef char misra_10_1_char_t;
@ -658,7 +756,7 @@ void misra_13_1(int *p) {
int a4[2] = { [0]=0, [1]=(v+=1) }; // 13.1
int a5[2] = { [0]=0, [1]=(v+1) };
int a6[2] = { v, 1 };
int a6[2] = { v >>= 3 }; // 13.1
int a6[2] = { v >>= 3 }; // 13.1 9.3
int a7[2] = { v, ++v }; // 13.1
int a8[1] = { vv }; // TODO: 13.1 Trac #9504