Skip to content

Commit 931aa12

Browse files
committed
EssentialTypes: Implement Rule 10.5
Adds a query that identifies explicit casts to an inappropriate essential type, according to the conditions set by MISRA C 2012.
1 parent 810a775 commit 931aa12

File tree

4 files changed

+172
-0
lines changed

4 files changed

+172
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* @id c/misra/inappropriate-essential-type-cast
3+
* @name RULE-10-5: The value of an expression should not be cast to an inappropriate essential type
4+
* @description
5+
* @kind problem
6+
* @precision very-high
7+
* @problem.severity error
8+
* @tags external/misra/id/rule-10-5
9+
* external/misra/obligation/advisory
10+
*/
11+
12+
import cpp
13+
import codingstandards.c.misra
14+
import codingstandards.c.misra.EssentialTypes
15+
import codingstandards.c.misra.MisraExpressions
16+
17+
predicate isIncompatibleEssentialTypeCast(EssentialTypeCategory fromCat, EssentialTypeCategory toCat) {
18+
fromCat = EssentiallyBooleanType() and
19+
toCat =
20+
[
21+
EssentiallyCharacterType(), EssentiallyEnumType(), EssentiallySignedType(),
22+
EssentiallyUnsignedType(), EssentiallyFloatingType().(TEssentialTypeCategory)
23+
]
24+
or
25+
fromCat = EssentiallyCharacterType() and
26+
toCat =
27+
[
28+
EssentiallyBooleanType(), EssentiallyEnumType(),
29+
EssentiallyFloatingType().(TEssentialTypeCategory)
30+
]
31+
or
32+
fromCat = EssentiallyEnumType() and
33+
toCat = [EssentiallyBooleanType(), EssentiallyEnumType().(TEssentialTypeCategory)] // NOTE only if different enum types
34+
or
35+
fromCat = EssentiallySignedType() and
36+
toCat = [EssentiallyBooleanType(), EssentiallyEnumType().(TEssentialTypeCategory)]
37+
or
38+
fromCat = EssentiallyUnsignedType() and
39+
toCat = [EssentiallyBooleanType(), EssentiallyEnumType().(TEssentialTypeCategory)]
40+
or
41+
fromCat = EssentiallyFloatingType() and
42+
toCat =
43+
[
44+
EssentiallyBooleanType(), EssentiallyCharacterType(),
45+
EssentiallyEnumType().(TEssentialTypeCategory)
46+
]
47+
}
48+
49+
from
50+
Cast c, Type essentialFromType, Type essentialToType, EssentialTypeCategory fromCategory,
51+
EssentialTypeCategory toCategory, string message
52+
where
53+
not isExcluded(c, EssentialTypesPackage::inappropriateEssentialTypeCastQuery()) and
54+
not c.isImplicit() and
55+
essentialFromType = getEssentialTypeBeforeConversions(c.getExpr()) and
56+
essentialToType = c.getType() and
57+
fromCategory = getEssentialTypeCategory(essentialFromType) and
58+
toCategory = getEssentialTypeCategory(essentialToType) and
59+
isIncompatibleEssentialTypeCast(fromCategory, toCategory) and
60+
(
61+
if fromCategory = EssentiallyEnumType() and toCategory = EssentiallyEnumType()
62+
then
63+
// If from/to enum types, then only report if the essential types are different
64+
not essentialToType = essentialFromType and
65+
message = "Incompatible cast from " + essentialFromType + " to " + essentialToType + "."
66+
else message = "Incompatible cast from " + fromCategory + " to " + toCategory + "."
67+
) and
68+
not (
69+
// Exception - casting from `0` or `1` to a boolean type is permitted
70+
(fromCategory = EssentiallySignedType() or fromCategory = EssentiallyUnsignedType()) and
71+
toCategory = EssentiallyBooleanType() and
72+
c.getExpr().getValue().toInt() = [0, 1]
73+
)
74+
select c, message
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
| test.c:9:3:9:9 | (char)... | Incompatible cast from essentially Boolean type to essentially Character type. |
2+
| test.c:10:3:10:13 | (E1)... | Incompatible cast from essentially Boolean type to essentially Enum Type. |
3+
| test.c:11:3:11:15 | (signed int)... | Incompatible cast from essentially Boolean type to essentially Signed type. |
4+
| test.c:12:3:12:17 | (unsigned int)... | Incompatible cast from essentially Boolean type to essentially Unsigned type. |
5+
| test.c:13:3:13:10 | (float)... | Incompatible cast from essentially Boolean type to essentially Floating type. |
6+
| test.c:16:3:16:11 | (bool)... | Incompatible cast from essentially Character type to essentially Boolean type. |
7+
| test.c:18:3:18:13 | (E1)... | Incompatible cast from essentially Character type to essentially Enum Type. |
8+
| test.c:21:3:21:10 | (float)... | Incompatible cast from essentially Character type to essentially Floating type. |
9+
| test.c:24:3:24:11 | (bool)... | Incompatible cast from essentially Enum Type to essentially Boolean type. |
10+
| test.c:26:3:26:13 | (E1)... | Incompatible cast from E2 to E1. |
11+
| test.c:33:3:33:11 | (bool)... | Incompatible cast from essentially Signed type to essentially Boolean type. |
12+
| test.c:35:3:35:13 | (E1)... | Incompatible cast from essentially Signed type to essentially Enum Type. |
13+
| test.c:41:3:41:11 | (bool)... | Incompatible cast from essentially Unsigned type to essentially Boolean type. |
14+
| test.c:43:3:43:13 | (E1)... | Incompatible cast from essentially Unsigned type to essentially Enum Type. |
15+
| test.c:49:3:49:11 | (bool)... | Incompatible cast from essentially Floating type to essentially Boolean type. |
16+
| test.c:50:3:50:9 | (char)... | Incompatible cast from essentially Floating type to essentially Character type. |
17+
| test.c:51:3:51:13 | (E1)... | Incompatible cast from essentially Floating type to essentially Enum Type. |
18+
| test.c:68:3:68:10 | (bool)... | Incompatible cast from essentially Signed type to essentially Boolean type. |
19+
| test.c:72:3:72:16 | (MyBool)... | Incompatible cast from essentially Signed type to essentially Boolean type. |
20+
| test.c:76:3:76:12 | (boolean)... | Incompatible cast from essentially Signed type to essentially Boolean type. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-10-5/InappropriateEssentialTypeCast.ql

c/misra/test/rules/RULE-10-5/test.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#include <stdbool.h>
2+
3+
void testIncompatibleCasts() {
4+
enum E1 { A, B };
5+
6+
_Bool b = true;
7+
8+
(_Bool) b; // COMPLIANT
9+
(char)b; // NON_COMPLIANT
10+
(enum E1) b; // NON_COMPLIANT
11+
(signed int)b; // NON_COMPLIANT
12+
(unsigned int)b; // NON_COMPLIANT
13+
(float)b; // NON_COMPLIANT
14+
15+
char c = 100;
16+
(_Bool) c; // NON_COMPLIANT
17+
(char)c; // COMPLIANT
18+
(enum E1) c; // NON_COMPLIANT
19+
(signed int)c; // COMPLIANT
20+
(unsigned int)c; // COMPLIANT
21+
(float)c; // NON_COMPLIANT
22+
23+
enum E2 { C, D } e = C;
24+
(_Bool) e; // NON_COMPLIANT
25+
(char)e; // COMPLIANT
26+
(enum E1) e; // NON_COMPLIANT
27+
(enum E2) e; // COMPLIANT
28+
(signed int)e; // COMPLIANT
29+
(unsigned int)e; // COMPLIANT
30+
(float)e; // COMPLIANT
31+
32+
signed int i = 100;
33+
(_Bool) i; // NON_COMPLIANT
34+
(char)i; // COMPLIANT
35+
(enum E1) i; // NON_COMPLIANT
36+
(signed int)i; // COMPLIANT
37+
(unsigned int)i; // COMPLIANT
38+
(float)i; // COMPLIANT
39+
40+
unsigned int u = 100;
41+
(_Bool) u; // NON_COMPLIANT
42+
(char)u; // COMPLIANT
43+
(enum E1) u; // NON_COMPLIANT
44+
(signed int)u; // COMPLIANT
45+
(unsigned int)u; // COMPLIANT
46+
(float)u; // COMPLIANT
47+
48+
float f = 100.0;
49+
(_Bool) f; // NON_COMPLIANT
50+
(char)f; // NON_COMPLIANT
51+
(enum E1) f; // NON_COMPLIANT
52+
(signed int)f; // COMPLIANT
53+
(unsigned int)f; // COMPLIANT
54+
(float)f; // COMPLIANT
55+
}
56+
57+
void testImplicit() {
58+
// Implicit conversions are not checked by this rule.
59+
char c = true; // Not covered by rule
60+
_Bool b = 100; // Not covered by rule
61+
unsigned int u = 100;
62+
_Bool b2 = u; // Not covered by rule
63+
}
64+
65+
void testIntegerConstantBool() {
66+
(_Bool)0; // COMPLIANT
67+
(_Bool)1; // COMPLIANT
68+
(_Bool)2; // NON_COMPLIANT
69+
enum MyBool { f, t };
70+
(enum MyBool)0; // COMPLIANT
71+
(enum MyBool)1; // COMPLIANT
72+
(enum MyBool)2; // NON_COMPLIANT
73+
typedef int boolean;
74+
(boolean)0; // COMPLIANT
75+
(boolean)1; // COMPLIANT
76+
(boolean)2; // NON_COMPLIANT
77+
}

0 commit comments

Comments
 (0)