Fixed #9993 (false positive: misra-c2012-9.2) (#2908)

This commit is contained in:
Ivar Andreas Bonsaksen 2020-11-18 10:50:35 +01:00 committed by GitHub
parent e8c1c792a5
commit 9029fff59d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 16 deletions

View File

@ -1519,11 +1519,18 @@ class MisraChecker:
# returns [1,2], None # returns [1,2], None
def getArrayDimensionsAndValueType(token): def getArrayDimensionsAndValueType(token):
dimensions = [] dimensions = []
while token.str == '*':
if token.astOperand2 is not None:
token = token.astOperand2
else:
token = token.astOperand1
while token and token.str == '[': while token and token.str == '[':
if token.astOperand2 != None: if token.astOperand2 is not None:
dimensions.insert(0, token.astOperand2.getKnownIntValue()) dimensions.insert(0, token.astOperand2.getKnownIntValue())
token = token.astOperand1 token = token.astOperand1
elif token.astOperand1 != None: elif token.astOperand1 is not None:
dimensions.insert(0, token.astOperand1.getKnownIntValue()) dimensions.insert(0, token.astOperand1.getKnownIntValue())
break break
else: else:
@ -1578,14 +1585,13 @@ class MisraChecker:
effectiveLevel = sum(levelOffsets) + level effectiveLevel = sum(levelOffsets) + level
isStringInitializer = token.isString and effectiveLevel == len(dimensions) - 1 # Zero initializer is ok at any level
isZeroInitializer = (isFirstElement and token.str == '0') 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 effectiveLevel == len(dimensions) or isZeroInitializer or isStringInitializer:
if isZeroInitializer or isStringInitializer: if not isZeroInitializer and not isStringInitializer:
# Zero initializer is ok at any level
# String initializer is ok at one level below value level
pass
else:
isFirstElement = False isFirstElement = False
if valueType.type == 'record': if valueType.type == 'record':
if token.isName: if token.isName:
@ -1595,16 +1601,19 @@ class MisraChecker:
else: else:
if not checkObjectInitializer(token, elements): if not checkObjectInitializer(token, elements):
return False return False
elif token.str == '{' or token.isString: 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) self.reportError(token, 9, 2)
return False return False
# Done evaluating leaf node - go back up to find next astOperand2
while token: while token:
# Done checking once level is back to 0 # Done checking once level is back to 0 (or we run out of parents)
if level == 0: if level == 0 or not token.astParent:
return True
if not token.astParent:
return True return True
if token.astParent.astOperand1 == token and token.astParent.astOperand2: if token.astParent.astOperand1 == token and token.astParent.astOperand2:
@ -1662,7 +1671,7 @@ class MisraChecker:
if token.str == ',': if token.str == ',':
token = token.astOperand1 token = token.astOperand1
else: else:
if pos == None: if pos is None:
pos = 0 pos = 0
if token.isAssignmentOp: if token.isAssignmentOp:
@ -1727,7 +1736,7 @@ class MisraChecker:
if variable.isArray : if variable.isArray :
dimensions, valueType = getArrayDimensionsAndValueType(eq.astOperand1) dimensions, valueType = getArrayDimensionsAndValueType(eq.astOperand1)
if dimensions == None: if dimensions is None:
continue continue
checkArrayInitializer(eq.astOperand2, dimensions, valueType) checkArrayInitializer(eq.astOperand2, dimensions, valueType)

View File

@ -306,6 +306,12 @@ void misra_9_2() {
const char string_wrong_level_b[2][20] = "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_a[] = "Hello world";
const char string_correct_level_b[2][12] = { "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
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
int array_init_incorrect_levels_a[3][2] = { 1, 2, 3, 4, 5, 6 }; // 9.2 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_correct_levels_a[3][2] = { { 1, 2 }, { 3, 4 }, { 5, 6 } };