diff --git a/addons/misra.py b/addons/misra.py index 88dd95af9..6e1f1f698 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -897,6 +897,14 @@ def isConstantExpression(expr): return False return True +def isUnknownConstantExpression(expr): + if expr.isName and not isEnumConstant(expr) and expr.variable is None: + return True + if expr.astOperand1 and isUnknownConstantExpression(expr.astOperand1): + return True + if expr.astOperand2 and isUnknownConstantExpression(expr.astOperand2): + return True + return False def isUnsignedInt(expr): return expr and expr.valueType and expr.valueType.type in ('short', 'int') and expr.valueType.sign == 'unsigned' @@ -3258,6 +3266,32 @@ class MisraChecker: tok = tok.next def misra_config(self, data): + for var in data.variables: + if not var.isArray or var.nameToken is None or not cppcheckdata.simpleMatch(var.nameToken.next, '['): + continue + tok = var.nameToken.next + while tok.str == '[': + sz = tok.astOperand2 + if sz and sz.getKnownIntValue() is None: + has_var = False + unknown_constant = False + tokens = [sz] + while len(tokens) > 0: + t = tokens[-1] + tokens = tokens[:-1] + if t: + if t.isName and t.getKnownIntValue() is None: + if t.varId or t.variable: + has_var = True + continue + unknown_constant = True + self.report_config_error(tok, 'Unknown constant {}, please review configuration'.format(t.str)) + if t.isArithmeticalOp: + tokens += [t.astOperand1, t.astOperand2] + if not unknown_constant and not has_var: + self.report_config_error(tok, 'Unknown array size, please review configuration') + tok = tok.link.next + for token in data.tokenlist: if token.str not in ("while", "if"): continue @@ -3367,7 +3401,7 @@ class MisraChecker: # Unknown define or syntax error if not typetok.astOperand2: continue - if not isConstantExpression(typetok.astOperand2): + if not isConstantExpression(typetok.astOperand2) and not isUnknownConstantExpression(typetok.astOperand2): self.reportError(var.nameToken, 18, 8) def misra_19_2(self, data): diff --git a/addons/misra_9.py b/addons/misra_9.py index 89002f30d..b84417066 100644 --- a/addons/misra_9.py +++ b/addons/misra_9.py @@ -396,38 +396,6 @@ class InitializerParser: break def misra_9_x(self, data, rule, rawTokens = None): - # If there are arrays with unknown size constants then we need to warn about missing configuration - # and bailout - has_config_errors = False - for var in data.variables: - if not var.isArray or var.nameToken is None or not cppcheckdata.simpleMatch(var.nameToken.next,'['): - continue - tok = var.nameToken.next - while tok.str == '[': - sz = tok.astOperand2 - if sz and sz.getKnownIntValue() is None: - has_var = False - unknown_constant = False - tokens = [sz] - while len(tokens) > 0: - t = tokens[-1] - tokens = tokens[:-1] - if t: - if t.isName and t.getKnownIntValue() is None: - if t.varId or t.variable: - has_var = True - continue - unknown_constant = True - cppcheckdata.reportError(sz, 'error', 'Unknown constant {}, please review configuration'.format(t.str), 'misra', 'config') - has_config_errors = True - if t.isArithmeticalOp: - tokens += [t.astOperand1, t.astOperand2] - if not unknown_constant and not has_var: - cppcheckdata.reportError(sz, 'error', 'Unknown array size, please review configuration', 'misra', 'config') - has_config_errors = True - tok = tok.link.next - if has_config_errors: - return parser = InitializerParser() diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c index 35291c45e..4c4ed1124 100644 --- a/addons/test/misra/misra-test.c +++ b/addons/test/misra/misra-test.c @@ -1783,6 +1783,8 @@ static void misra_18_8(int x) { int buf1[10]; int buf2[sizeof(int)]; int vla[x]; // 18.8 + // #9498 + int vlb[y]; // config static const unsigned char arr18_8_1[] = UNDEFINED_ID; static uint32_t enum_test_0[R18_8_ENUM_CONSTANT_0] = {0}; }