misra.py: Handle stdint.h essential types (#2555)
Add stdint.h essential types to misra.py checks. This will fix false negatives for rules 10.6 and 10.8.
This commit is contained in:
parent
baa4cee70c
commit
4e5a8fac4a
|
@ -36,6 +36,14 @@ def grouped(iterable, n):
|
|||
return zip(*[iter(iterable)] * n)
|
||||
|
||||
|
||||
INT_TYPES = ['bool', 'char', 'short', 'int', 'long', 'long long']
|
||||
|
||||
|
||||
STDINT_TYPES = ['%s%d_t' % (n, v) for n, v in itertools.product(
|
||||
['int', 'uint', 'int_least', 'uint_least', 'int_fast', 'uint_fast'],
|
||||
[8, 16, 32, 64])]
|
||||
|
||||
|
||||
typeBits = {
|
||||
'CHAR': None,
|
||||
'SHORT': None,
|
||||
|
@ -46,6 +54,10 @@ typeBits = {
|
|||
}
|
||||
|
||||
|
||||
def isUnsignedType(ty):
|
||||
return ty == 'unsigned' or ty.startswith('uint')
|
||||
|
||||
|
||||
def simpleMatch(token, pattern):
|
||||
for p in pattern.split(' '):
|
||||
if not token or token.str != p:
|
||||
|
@ -274,9 +286,7 @@ C99_STDLIB_IDENTIFIERS = {
|
|||
'UINTMAX_MAX', 'PTRDIFF_MIN', 'PTRDIFF_MAX', 'SIG_ATOMIC_MIN',
|
||||
'SIG_ATOMIC_MAX', 'SIZE_MAX', 'WCHAR_MIN', 'WCHAR_MAX', 'WINT_MIN',
|
||||
'WINT_MAX', 'INTN_C', 'UINTN_C', 'INTMAX_C', 'UINTMAX_C',
|
||||
] + ['%s%d_t' % (n, v) for n,v in itertools.product(
|
||||
['int', 'uint', 'int_least', 'uint_least', 'int_fast', 'uint_fast'],
|
||||
[8, 16,32,64])],
|
||||
] + STDINT_TYPES,
|
||||
# B.18 Input/output
|
||||
'stdio.h': C90_STDLIB_IDENTIFIERS['stdio.h'] + [
|
||||
'mode', 'restrict', 'snprintf', 'vfscanf', 'vscanf',
|
||||
|
@ -417,7 +427,7 @@ def getEssentialType(expr):
|
|||
if expr.variable:
|
||||
typeToken = expr.variable.typeStartToken
|
||||
while typeToken and typeToken.isName:
|
||||
if typeToken.str in ('char', 'short', 'int', 'long', 'float', 'double'):
|
||||
if typeToken.str in INT_TYPES + STDINT_TYPES + ['float', 'double']:
|
||||
return typeToken.str
|
||||
typeToken = typeToken.next
|
||||
|
||||
|
@ -431,15 +441,10 @@ def getEssentialType(expr):
|
|||
e2 = getEssentialType(expr.astOperand2)
|
||||
if not e1 or not e2:
|
||||
return None
|
||||
types = ['bool', 'char', 'short', 'int', 'long', 'long long']
|
||||
try:
|
||||
i1 = types.index(e1)
|
||||
i2 = types.index(e2)
|
||||
if i2 >= i1:
|
||||
return types[i2]
|
||||
return types[i1]
|
||||
except ValueError:
|
||||
return None
|
||||
if bitsOfEssentialType(e2) >= bitsOfEssentialType(e1):
|
||||
return e2
|
||||
else:
|
||||
return e1
|
||||
elif expr.str == "~":
|
||||
e1 = getEssentialType(expr.astOperand1)
|
||||
return e1
|
||||
|
@ -447,20 +452,22 @@ def getEssentialType(expr):
|
|||
return None
|
||||
|
||||
|
||||
def bitsOfEssentialType(expr):
|
||||
type = getEssentialType(expr)
|
||||
if type is None:
|
||||
def bitsOfEssentialType(ty):
|
||||
if ty is None:
|
||||
return 0
|
||||
if type == 'char':
|
||||
if ty == 'char':
|
||||
return typeBits['CHAR']
|
||||
if type == 'short':
|
||||
if ty == 'short':
|
||||
return typeBits['SHORT']
|
||||
if type == 'int':
|
||||
if ty == 'int':
|
||||
return typeBits['INT']
|
||||
if type == 'long':
|
||||
if ty == 'long':
|
||||
return typeBits['LONG']
|
||||
if type == 'long long':
|
||||
if ty == 'long long':
|
||||
return typeBits['LONG_LONG']
|
||||
for sty in STDINT_TYPES:
|
||||
if ty == sty:
|
||||
return int(''.join(filter(str.isdigit, sty)))
|
||||
return 0
|
||||
|
||||
|
||||
|
@ -1335,9 +1342,9 @@ class MisraChecker:
|
|||
if not e1 or not e2:
|
||||
continue
|
||||
if token.str in ('<<', '>>'):
|
||||
if e1 != 'unsigned':
|
||||
if not isUnsignedType(e1):
|
||||
self.reportError(token, 10, 1)
|
||||
elif e2 != 'unsigned' and not token.astOperand2.isNumber:
|
||||
elif not isUnsignedType(e2) and not token.astOperand2.isNumber:
|
||||
self.reportError(token, 10, 1)
|
||||
elif token.str in ('~', '&', '|', '^'):
|
||||
e1_et = getEssentialType(token.astOperand1)
|
||||
|
@ -1392,16 +1399,13 @@ class MisraChecker:
|
|||
if not vt2 or vt2.pointer > 0:
|
||||
continue
|
||||
try:
|
||||
intTypes = ['char', 'short', 'int', 'long', 'long long']
|
||||
index1 = intTypes.index(vt1.type)
|
||||
if isCast(token.astOperand2):
|
||||
e = vt2.type
|
||||
else:
|
||||
e = getEssentialType(token.astOperand2)
|
||||
if not e:
|
||||
continue
|
||||
index2 = intTypes.index(e)
|
||||
if index1 > index2:
|
||||
if bitsOfEssentialType(vt1.type) > bitsOfEssentialType(e):
|
||||
self.reportError(token, 10, 6)
|
||||
except ValueError:
|
||||
pass
|
||||
|
@ -1431,13 +1435,10 @@ class MisraChecker:
|
|||
self.reportError(token, 10, 8)
|
||||
else:
|
||||
try:
|
||||
intTypes = ['char', 'short', 'int', 'long', 'long long']
|
||||
index1 = intTypes.index(token.valueType.type)
|
||||
e = getEssentialType(token.astOperand1)
|
||||
if not e:
|
||||
continue
|
||||
index2 = intTypes.index(e)
|
||||
if index1 > index2:
|
||||
if bitsOfEssentialType(token.valueType.type) > bitsOfEssentialType(e):
|
||||
self.reportError(token, 10, 8)
|
||||
except ValueError:
|
||||
pass
|
||||
|
@ -1625,7 +1626,7 @@ class MisraChecker:
|
|||
maxval = val.intvalue
|
||||
if maxval == 0:
|
||||
continue
|
||||
sz = bitsOfEssentialType(token.astOperand1)
|
||||
sz = bitsOfEssentialType(getEssentialType(token.astOperand1))
|
||||
if sz <= 0:
|
||||
continue
|
||||
if maxval >= sz:
|
||||
|
|
|
@ -267,7 +267,7 @@ void misra_10_1_ternary()
|
|||
int8_t i8;
|
||||
int16_t i16;
|
||||
|
||||
a = ui16 << ui16;
|
||||
a = ui16 << ui16; // 10.6
|
||||
a = ui16 << (get_bool(42) ? ui16 : ui16);
|
||||
a = ui16 << (get_bool(42) ? ui16 : (get_bool(34) ? ui16 : ui16)); // 10.4
|
||||
a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : ui16) : ui16); // 10.4
|
||||
|
@ -305,6 +305,10 @@ void misra_10_6(u8 x, u32 a, u32 b, char c1, char c2) {
|
|||
u32 c = ( u16) ( u32 a + u32 b ); //10.6
|
||||
s32 i = c1 - c2; // FIXME: False positive for 10.6 (this is compliant). Trac #9488
|
||||
}
|
||||
void misra_10_6_1(uint32_t *a, uint16_t b, uint16_t c)
|
||||
{
|
||||
*a = b + c ; // 10.6
|
||||
}
|
||||
|
||||
void misra_10_8(u8 x, s32 a, s32 b) {
|
||||
y = (u16)x;
|
||||
|
|
Loading…
Reference in New Issue