Add MISRA checks for rules 21.1 and 21.12 (#2284)
* Add MISRA 21.1 check This also required add static field for functions in symboldatabase. * Add MISRA R21.12 * Use newer ASSERT macroses in tests
This commit is contained in:
parent
37bb19f02c
commit
72f07c8a33
|
@ -341,6 +341,7 @@ class Function:
|
|||
tokenDef Token in function definition
|
||||
isVirtual Is this function is virtual
|
||||
isImplicitlyVirtual Is this function is virtual this in the base classes
|
||||
isStatic Is this function is static
|
||||
"""
|
||||
|
||||
Id = None
|
||||
|
@ -352,6 +353,7 @@ class Function:
|
|||
type = None
|
||||
isVirtual = None
|
||||
isImplicitlyVirtual = None
|
||||
isStatic = None
|
||||
|
||||
def __init__(self, element):
|
||||
self.Id = element.get('id')
|
||||
|
@ -362,6 +364,8 @@ class Function:
|
|||
self.isVirtual = (isVirtual and isVirtual == 'true')
|
||||
isImplicitlyVirtual = element.get('isImplicitlyVirtual')
|
||||
self.isImplicitlyVirtual = (isImplicitlyVirtual and isImplicitlyVirtual == 'true')
|
||||
isStatic = element.get('isStatic')
|
||||
self.isStatic = (isStatic and isStatic == 'true')
|
||||
|
||||
self.argument = {}
|
||||
self.argumentId = {}
|
||||
|
|
|
@ -1937,6 +1937,38 @@ class MisraChecker:
|
|||
ifStack.pop()
|
||||
|
||||
|
||||
def misra_21_1(self, data):
|
||||
# Reference: n1570 7.1.3 - Reserved identifiers
|
||||
re_forbidden_macro = re.compile(r'#define (errno|_[_A-Z]+)')
|
||||
|
||||
# Search for forbidden identifiers in macro names
|
||||
for directive in data.directives:
|
||||
res = re.search(re_forbidden_macro, directive.str)
|
||||
if res:
|
||||
self.reportError(directive, 21, 1)
|
||||
|
||||
# Search for forbidden identifiers
|
||||
for token in data.tokenlist:
|
||||
if not token.isName:
|
||||
continue
|
||||
if len(token.str) < 2:
|
||||
continue
|
||||
if token.str == 'errno':
|
||||
self.reportError(token, 21, 1)
|
||||
if token.str[0] == '_':
|
||||
if (token.str[1] in string.ascii_uppercase) or (token.str[1] == '_'):
|
||||
self.reportError(token, 21, 1)
|
||||
|
||||
# Allow identifiers with file scope visibility (static)
|
||||
if token.scope.type == 'Global':
|
||||
if token.variable and token.variable.isStatic:
|
||||
continue
|
||||
if token.function and token.function.isStatic:
|
||||
continue
|
||||
|
||||
self.reportError(token, 21, 1)
|
||||
|
||||
|
||||
def misra_21_3(self, data):
|
||||
for token in data.tokenlist:
|
||||
if isFunctionCall(token) and (token.astOperand1.str in ('malloc', 'calloc', 'realloc', 'free')):
|
||||
|
@ -1998,6 +2030,20 @@ class MisraChecker:
|
|||
self.reportError(directive, 21, 11)
|
||||
|
||||
|
||||
def misra_21_12(self, data):
|
||||
if findInclude(data.directives, '<fenv.h>'):
|
||||
for token in data.tokenlist:
|
||||
if token.str == 'fexcept_t' and token.isName:
|
||||
self.reportError(token, 21, 12)
|
||||
if isFunctionCall(token) and (token.astOperand1.str in (
|
||||
'feclearexcept',
|
||||
'fegetexceptflag',
|
||||
'feraiseexcept',
|
||||
'fesetexceptflag',
|
||||
'fetestexcept')):
|
||||
self.reportError(token, 21, 12)
|
||||
|
||||
|
||||
def get_verify_expected(self):
|
||||
"""Return the list of expected violations in the verify test"""
|
||||
return self.verify_expected
|
||||
|
@ -2495,6 +2541,7 @@ class MisraChecker:
|
|||
self.misra_20_10(cfg)
|
||||
self.misra_20_13(cfg)
|
||||
self.misra_20_14(cfg)
|
||||
self.misra_21_1(cfg)
|
||||
self.misra_21_3(cfg)
|
||||
self.misra_21_4(cfg)
|
||||
self.misra_21_5(cfg)
|
||||
|
@ -2504,6 +2551,7 @@ class MisraChecker:
|
|||
self.misra_21_9(cfg)
|
||||
self.misra_21_10(cfg)
|
||||
self.misra_21_11(cfg)
|
||||
self.misra_21_12(cfg)
|
||||
# 22.4 is already covered by Cppcheck writeReadOnlyFile
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <wchar.h> //21.6
|
||||
#include <time.h> // 21.10
|
||||
#include <tgmath.h> // 21.11
|
||||
#include <fenv.h>
|
||||
|
||||
|
||||
typedef unsigned char u8;
|
||||
|
@ -395,7 +396,7 @@ void misra_14_2() {
|
|||
struct {
|
||||
unsigned int x:1;
|
||||
unsigned int y:1;
|
||||
} _14_4_struct;
|
||||
} r14_4_struct;
|
||||
void misra_14_4(bool b) {
|
||||
if (x+4){} // 14.4
|
||||
else {}
|
||||
|
@ -403,7 +404,7 @@ void misra_14_4(bool b) {
|
|||
if (b) {}
|
||||
else {}
|
||||
|
||||
if (_14_4_struct.x) {}
|
||||
if (r14_4_struct.x) {}
|
||||
}
|
||||
|
||||
void misra_15_1() {
|
||||
|
@ -652,12 +653,12 @@ struct {
|
|||
} nested_2;
|
||||
uint8_t data_3[]; // 18.7
|
||||
} nested_3;
|
||||
} _18_7_struct;
|
||||
} r18_7_struct;
|
||||
struct {
|
||||
uint16_t len;
|
||||
uint8_t data_1[ 19 ];
|
||||
uint8_t data_2[ ]; // 18.7
|
||||
} _18_7_struct;
|
||||
} r18_7_struct;
|
||||
|
||||
void misra_18_8(int x) {
|
||||
int buf1[10];
|
||||
|
@ -688,6 +689,58 @@ union misra_19_2 { }; // 19.2
|
|||
# def fun_2013(v) () // 20.13
|
||||
#endif
|
||||
|
||||
#define _Incompatible 0xdeadbeef // 21.1
|
||||
#define __Incompatible 0xdeadbeef // 21.1
|
||||
#define __starts_with_lower 0xdeadbeef // 21.1
|
||||
#define __MY_HEADER_ // 21.1
|
||||
#define _starts_with_lower 1 // no warning
|
||||
static int _file_scope_id_21_1 = 42; // no warning
|
||||
static int _file_scope_id_21_1_fn() { return 42; } // no warning
|
||||
static int __file_scope_id_21_1 = 42; // 21.1
|
||||
static int __file_scope_id_21_1_fn() { return 42; } // 21.1
|
||||
static int _File_scope_id_21_1 = 42; // 21.1
|
||||
static int _File_scope_id_21_1_fn() { return 42; } // 21.1
|
||||
int _external_scope_id_21_1 = 42; // 21.1
|
||||
int _external_scope_id_21_1_fn() { return 42; } // 21.1
|
||||
int __external_scope_id_21_1 = 42; // 21.1
|
||||
int __external_scope_id_21_1_fn() { return 42; } // 21.1
|
||||
int _External_scope_id_21_1 = 42; // 21.1
|
||||
int _External_scope_id_21_1_fn() { return 42; } // 21.1
|
||||
int errno = 42; // 21.1
|
||||
int errno() { // 21.1
|
||||
// TODO: 15.5 false positive
|
||||
return 42; // 15.5
|
||||
}
|
||||
|
||||
struct _struct_21_1 { int a; }; // 21.1
|
||||
struct _Struct_21_1 { int a; }; // 21.1
|
||||
struct __struct_21_1 { int a; }; // 21.1
|
||||
typedef struct { int a; } _struct_21_1_t; // 21.1
|
||||
typedef struct { int a; } _Struct_21_1_t; // 21.1
|
||||
typedef struct { int a; } __struct_21_1_t; // 21.1
|
||||
|
||||
enum _enum_21_1 { ENUM211_1 }; // 21.1
|
||||
enum _Enum_21_1 { ENUM211_2 }; // 21.1
|
||||
enum __enum_21_1 { ENUM211_3 }; // 21.1
|
||||
enum __enum_21_1 { ENUM211_3 }; // 21.1
|
||||
typedef enum { ENUM211_4 } _enum_21_1_t; // 21.1
|
||||
typedef enum { ENUM211_5 } _Enum_21_1_t; // 21.1
|
||||
typedef enum { ENUM211_6 } __enum_21_1_t; // 21.1
|
||||
enum enum_21_1_valid_id {
|
||||
ENUM211_7,
|
||||
_ENUM211_8, // 21.1
|
||||
__ENUM211_9, // 21.1
|
||||
_eNUM211_10, // 21.1
|
||||
enum211_11
|
||||
};
|
||||
|
||||
union _union_21_1 { int a; }; // 21.1 19.2
|
||||
union _Union_21_1 { int a; }; // 21.1 19.2
|
||||
union __union_21_1 { int a; }; // 21.1 19.2
|
||||
typedef union { int a; } _union_21_1_t; // 21.1 19.2
|
||||
typedef union { int a; } _Union_21_1_t; // 21.1 19.2
|
||||
typedef union { int a; } __union_21_1_t; // 21.1 19.2
|
||||
|
||||
void misra_21_3() {
|
||||
p1=malloc(10); // 21.3
|
||||
p2=calloc(10); // 21.3
|
||||
|
@ -713,3 +766,14 @@ void misra_21_9() {
|
|||
(void)bsearch(key,base,num,size,cmp); // 21.9
|
||||
qsort(base,num,size,cmp); // 21.9
|
||||
}
|
||||
|
||||
void misra_21_12() {
|
||||
int rc;
|
||||
fexcept_t f; // 21.12
|
||||
rc = feclearexcept(1); // 21.12
|
||||
rc = fegetexceptflag(&f, 1); // 21.12
|
||||
rc = feraiseexcept(1); // 21.12
|
||||
rc = fesetexceptflag(&f, 1); // 21.12
|
||||
rc = fetestexcept(1); // 21.12
|
||||
}
|
||||
|
||||
|
|
|
@ -3225,6 +3225,8 @@ void SymbolDatabase::printXml(std::ostream &out) const
|
|||
else if (function->isImplicitlyVirtual())
|
||||
out << " isImplicitlyVirtual=\"true\"";
|
||||
}
|
||||
if (function->isStatic())
|
||||
out << " isStatic=\"true\"";
|
||||
if (function->argCount() == 0U)
|
||||
out << "/>" << std::endl;
|
||||
else {
|
||||
|
|
|
@ -221,6 +221,8 @@ private:
|
|||
|
||||
TEST_CASE(functionImplicitlyVirtual);
|
||||
|
||||
TEST_CASE(functionStatic);
|
||||
|
||||
TEST_CASE(namespaces1);
|
||||
TEST_CASE(namespaces2);
|
||||
TEST_CASE(namespaces3); // #3854 - unknown macro
|
||||
|
@ -2287,6 +2289,14 @@ private:
|
|||
ASSERT_EQUALS(true, function && function->isImplicitlyVirtual(false));
|
||||
}
|
||||
|
||||
void functionStatic() {
|
||||
GET_SYMBOL_DB("static void fs() { }");
|
||||
(void)db;
|
||||
const Function *func = db->scopeList.back().function;
|
||||
ASSERT(func);
|
||||
ASSERT(func->isStatic());
|
||||
}
|
||||
|
||||
void namespaces1() {
|
||||
GET_SYMBOL_DB("namespace fred {\n"
|
||||
" namespace barney {\n"
|
||||
|
|
Loading…
Reference in New Issue