misra.py: Handle essential type categories for ternary operations (#2455)
This commit will add feature to detect essential type categories for operators of ternary operation. This fixes issues with rule 10.1 and close the following ticket: https://trac.cppcheck.net/ticket/9543
This commit is contained in:
parent
fe23d017f3
commit
730ea4163b
|
@ -531,6 +531,28 @@ def isSimpleEscapeSequence(symbols):
|
|||
return symbols[1] in ("'", '"', '?', '\\', 'a', 'b', 'f', 'n', 'r', 't', 'v')
|
||||
|
||||
|
||||
def isTernaryOperator(token):
|
||||
if not token:
|
||||
return False
|
||||
if not token.astOperand2:
|
||||
return False
|
||||
return token.str == '?' and token.astOperand2.str == ':'
|
||||
|
||||
|
||||
def getTernaryOperandsRecursive(token):
|
||||
"""Returns list of ternary operands including nested onces."""
|
||||
if not isTernaryOperator(token):
|
||||
return []
|
||||
result = []
|
||||
result += getTernaryOperandsRecursive(token.astOperand2.astOperand1)
|
||||
if token.astOperand2.astOperand1 and not isTernaryOperator(token.astOperand2.astOperand1):
|
||||
result += [token.astOperand2.astOperand1]
|
||||
result += getTernaryOperandsRecursive(token.astOperand2.astOperand2)
|
||||
if token.astOperand2.astOperand2 and not isTernaryOperator(token.astOperand2.astOperand2):
|
||||
result += [token.astOperand2.astOperand2]
|
||||
return result
|
||||
|
||||
|
||||
def hasNumericEscapeSequence(symbols):
|
||||
"""Check that given string contains octal or hexadecimal escape sequences."""
|
||||
if '\\' not in symbols:
|
||||
|
@ -1049,20 +1071,25 @@ class MisraChecker:
|
|||
for token in data.tokenlist:
|
||||
if not token.isOp:
|
||||
continue
|
||||
e1 = getEssentialTypeCategory(token.astOperand1)
|
||||
e2 = getEssentialTypeCategory(token.astOperand2)
|
||||
if not e1 or not e2:
|
||||
continue
|
||||
if token.str in ('<<', '>>'):
|
||||
if e1 != 'unsigned':
|
||||
self.reportError(token, 10, 1)
|
||||
elif e2 != 'unsigned' and not token.astOperand2.isNumber:
|
||||
self.reportError(token, 10, 1)
|
||||
elif token.str in ('~', '&', '|', '^'):
|
||||
e1_et = getEssentialType(token.astOperand1)
|
||||
e2_et = getEssentialType(token.astOperand2)
|
||||
if e1_et == 'char' and e2_et == 'char':
|
||||
self.reportError(token, 10, 1)
|
||||
|
||||
for t1, t2 in itertools.product(
|
||||
list(getTernaryOperandsRecursive(token.astOperand1) or [token.astOperand1]),
|
||||
list(getTernaryOperandsRecursive(token.astOperand2) or [token.astOperand2]),
|
||||
):
|
||||
e1 = getEssentialTypeCategory(t1)
|
||||
e2 = getEssentialTypeCategory(t2)
|
||||
if not e1 or not e2:
|
||||
continue
|
||||
if token.str in ('<<', '>>'):
|
||||
if e1 != 'unsigned':
|
||||
self.reportError(token, 10, 1)
|
||||
elif e2 != 'unsigned' and not token.astOperand2.isNumber:
|
||||
self.reportError(token, 10, 1)
|
||||
elif token.str in ('~', '&', '|', '^'):
|
||||
e1_et = getEssentialType(token.astOperand1)
|
||||
e2_et = getEssentialType(token.astOperand2)
|
||||
if e1_et == 'char' and e2_et == 'char':
|
||||
self.reportError(token, 10, 1)
|
||||
|
||||
def misra_10_4(self, data):
|
||||
op = {'+', '-', '*', '/', '%', '&', '|', '^', '+=', '-=', ':'}
|
||||
|
|
|
@ -234,6 +234,32 @@ void misra_10_1(uint8_t u, char c1, char c2) {
|
|||
MISRA_10_1_CHAR cd3;
|
||||
cd3 = cd1 & cd2; // 10.1
|
||||
}
|
||||
void misra_10_1_ternary()
|
||||
{
|
||||
int a;
|
||||
uint8_t ui8;
|
||||
uint16_t ui16;
|
||||
int8_t i8;
|
||||
int16_t i16;
|
||||
|
||||
a = ui16 << ui16;
|
||||
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
|
||||
a = ui16 << (get_bool(42) ? i16 : (get_bool(34) ? ui16 : ui16)); // 10.1
|
||||
a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : i16) : ui16); // 10.1 10.4
|
||||
a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : ui16) : i16); // 10.1
|
||||
a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : ui8); // 10.4
|
||||
a = ui16 << (get_bool(42) ? (get_bool(34) ? i16 : ui8) : ui8); // 10.1 10.4
|
||||
a = (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : ui8) << ui16; // 10.4
|
||||
a = (get_bool(42) ? (get_bool(34) ? i16 : ui8) : ui8) << ui16; // 10.1 10.4
|
||||
a = (get_bool(42) ? (get_bool(34) ? ui16 : i8) : ui8) << ui16; // 10.1 10.4
|
||||
a = (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : i8) << ui16; // 10.1
|
||||
a = (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : ui8) << (get_bool(19) ? ui16 : ui8); // 10.4
|
||||
a = (get_bool(42) ? (get_bool(34) ? i16 : ui8) : ui8) << (get_bool(19) ? ui16 : ui8); // 10.1 10.4
|
||||
a = (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : ui8) << (get_bool(19) ? i16 : ui8); // 10.1 10.4
|
||||
|
||||
}
|
||||
|
||||
void misra_10_4(u32 x, s32 y) {
|
||||
z = x + 3; // 10.4
|
||||
|
|
Loading…
Reference in New Issue