Skip to content

Commit 3cf9eac

Browse files
committed
Improve detection of integer promotions and usual arithmetic conversions
1 parent 3a8dab1 commit 3cf9eac

File tree

2 files changed

+74
-52
lines changed

2 files changed

+74
-52
lines changed

cpp/misra/src/rules/RULE-7-0-5/NoSignednessChangeFromPromotion.ql

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,22 @@ abstract class RelevantRealConversion extends RelevantConversion, Conversion {
5050
class UsualArithmeticConversion extends RelevantRealConversion {
5151
UsualArithmeticConversion() {
5252
(
53-
exists(BinaryOperation op | op.getAnOperand().getFullyConverted() = this) or
54-
exists(UnaryOperation uao | uao.getOperand().getFullyConverted() = this) or
55-
exists(AssignArithmeticOperation ao | ao.getAnOperand().getFullyConverted() = this)
53+
// Most binary operations from and to numeric types participate in usual arithmetic conversions
54+
exists(BinaryOperation op |
55+
// Shifts do not participate in usual arithmetic conversions
56+
not op instanceof LShiftExpr and
57+
not op instanceof RShiftExpr and
58+
op.getAnOperand().getFullyConverted() = this
59+
)
60+
or
61+
// Most binary assignment operations from and to numeric types participate in usual arithmetic
62+
// conversions
63+
exists(AssignOperation ao |
64+
// Shifts do not participate in usual arithmetic conversions
65+
not ao instanceof AssignLShiftExpr and
66+
not ao instanceof AssignRShiftExpr and
67+
ao.getRValue().getFullyConverted() = this
68+
)
5669
)
5770
}
5871

@@ -61,15 +74,24 @@ class UsualArithmeticConversion extends RelevantRealConversion {
6174

6275
class IntegerPromotion extends RelevantRealConversion {
6376
IntegerPromotion() {
77+
// Exclude integer promotions combined with usual arithmetic conversions, which are handled separately
78+
not this instanceof UsualArithmeticConversion and
6479
// Only consider cases where the integer promotion is the last conversion applied
6580
exists(Expr e | e.getFullyConverted() = this) and
6681
// Integer promotion occurs where the from type is smaller than int
67-
fromType.getRealSize() < any(IntType i).(NumericType).getRealSize() and
82+
fromType.getRealSize() < sizeOfInt() and
6883
// To type is bigger than or equal to int
69-
toType.getRealSize() >= any(IntType i).(NumericType).getRealSize() and
84+
toType.getRealSize() >= sizeOfInt() and
85+
// An integer promotion is a conversion from an integral type to an integral type
86+
//
87+
// This deliberately excludes integer promotions from `bool` and unscoped enums which do not
88+
// have a fixed underlying type, because neither of these are considered integral types in the
89+
// MISRA C++ rules.
7090
fromType.getTypeCategory() = Integral() and
7191
toType.getTypeCategory() = Integral()
7292
}
93+
94+
override string getKindOfConversion() { result = "Integer promotion" }
7395
}
7496

7597
from Expr e, RelevantConversion c, NumericType fromType, NumericType toType, string changeType
Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,47 @@
1-
| test.cpp:24:5:24:6 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
2-
| test.cpp:24:10:24:11 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
3-
| test.cpp:25:5:25:6 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
4-
| test.cpp:25:10:25:11 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
5-
| test.cpp:26:5:26:6 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
6-
| test.cpp:26:10:26:11 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
7-
| test.cpp:27:5:27:6 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
8-
| test.cpp:27:10:27:11 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
9-
| test.cpp:28:5:28:6 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
10-
| test.cpp:28:10:28:11 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
11-
| test.cpp:29:5:29:6 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
12-
| test.cpp:29:10:29:11 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
13-
| test.cpp:30:5:30:6 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
14-
| test.cpp:30:10:30:11 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
15-
| test.cpp:31:5:31:6 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
16-
| test.cpp:31:10:31:11 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
17-
| test.cpp:45:11:45:12 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
18-
| test.cpp:46:11:46:12 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
19-
| test.cpp:47:11:47:12 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
20-
| test.cpp:48:11:48:12 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
21-
| test.cpp:49:11:49:12 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
22-
| test.cpp:50:11:50:12 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
23-
| test.cpp:51:11:51:12 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
24-
| test.cpp:52:11:52:12 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
25-
| test.cpp:64:5:64:6 | l1 | Conversion from 'signed int' to 'unsigned int' changes signedness. |
26-
| test.cpp:65:5:65:6 | l1 | Conversion from 'signed int' to 'unsigned int' changes signedness. |
27-
| test.cpp:66:5:66:6 | l1 | Conversion from 'signed int' to 'unsigned int' changes signedness. |
28-
| test.cpp:67:5:67:6 | l1 | Conversion from 'signed int' to 'unsigned int' changes signedness. |
29-
| test.cpp:68:5:68:6 | l1 | Conversion from 'signed int' to 'unsigned int' changes signedness. |
30-
| test.cpp:69:5:69:6 | l1 | Conversion from 'signed int' to 'unsigned int' changes signedness. |
31-
| test.cpp:71:5:71:6 | l3 | Conversion from 'unsigned char' to 'int' changes signedness. |
32-
| test.cpp:71:10:71:11 | l4 | Conversion from 'unsigned short' to 'int' changes signedness. |
33-
| test.cpp:72:5:72:6 | l3 | Conversion from 'unsigned char' to 'int' changes signedness. |
34-
| test.cpp:72:10:72:11 | l4 | Conversion from 'unsigned short' to 'int' changes signedness. |
35-
| test.cpp:82:10:82:11 | l2 | Conversion from 'unsigned char' to 'int' changes signedness. |
36-
| test.cpp:82:15:82:16 | l4 | Conversion from 'unsigned short' to 'int' changes signedness. |
37-
| test.cpp:89:5:89:6 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
38-
| test.cpp:90:5:90:6 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
39-
| test.cpp:100:6:100:7 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
40-
| test.cpp:102:6:102:7 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
41-
| test.cpp:104:6:104:7 | l1 | Conversion from 'unsigned char' to 'int' changes signedness. |
42-
| test.cpp:143:11:143:12 | l2 | Conversion from 'unsigned int' to 'float' changes signedness. |
43-
| test.cpp:143:11:143:12 | l2 | Conversion from 'unsigned int' to 'float' changes type category. |
44-
| test.cpp:144:11:144:12 | l2 | Conversion from 'unsigned int' to 'float' changes signedness. |
45-
| test.cpp:144:11:144:12 | l2 | Conversion from 'unsigned int' to 'float' changes type category. |
46-
| test.cpp:145:11:145:12 | l2 | Conversion from 'unsigned int' to 'float' changes signedness. |
47-
| test.cpp:145:11:145:12 | l2 | Conversion from 'unsigned int' to 'float' changes type category. |
1+
| test.cpp:24:5:24:6 | l1 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
2+
| test.cpp:24:10:24:11 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
3+
| test.cpp:25:5:25:6 | l1 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
4+
| test.cpp:25:10:25:11 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
5+
| test.cpp:26:5:26:6 | l1 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
6+
| test.cpp:26:10:26:11 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
7+
| test.cpp:27:5:27:6 | l1 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
8+
| test.cpp:27:10:27:11 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
9+
| test.cpp:28:5:28:6 | l1 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
10+
| test.cpp:28:10:28:11 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
11+
| test.cpp:29:5:29:6 | l1 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
12+
| test.cpp:29:10:29:11 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
13+
| test.cpp:30:5:30:6 | l1 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
14+
| test.cpp:30:10:30:11 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
15+
| test.cpp:31:5:31:6 | l1 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
16+
| test.cpp:31:10:31:11 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
17+
| test.cpp:45:11:45:12 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
18+
| test.cpp:46:11:46:12 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
19+
| test.cpp:47:11:47:12 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
20+
| test.cpp:48:11:48:12 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
21+
| test.cpp:49:11:49:12 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
22+
| test.cpp:50:11:50:12 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
23+
| test.cpp:51:11:51:12 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
24+
| test.cpp:52:11:52:12 | l2 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
25+
| test.cpp:64:5:64:6 | l1 | Usual arithmetic conversion from 'int32_t' to 'unsigned int' changes signedness. |
26+
| test.cpp:65:5:65:6 | l1 | Usual arithmetic conversion from 'int32_t' to 'unsigned int' changes signedness. |
27+
| test.cpp:66:5:66:6 | l1 | Usual arithmetic conversion from 'int32_t' to 'unsigned int' changes signedness. |
28+
| test.cpp:67:5:67:6 | l1 | Usual arithmetic conversion from 'int32_t' to 'unsigned int' changes signedness. |
29+
| test.cpp:68:5:68:6 | l1 | Usual arithmetic conversion from 'int32_t' to 'unsigned int' changes signedness. |
30+
| test.cpp:69:5:69:6 | l1 | Usual arithmetic conversion from 'int32_t' to 'unsigned int' changes signedness. |
31+
| test.cpp:71:5:71:6 | l3 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
32+
| test.cpp:71:10:71:11 | l4 | Usual arithmetic conversion from 'uint16_t' to 'int' changes signedness. |
33+
| test.cpp:72:5:72:6 | l3 | Usual arithmetic conversion from 'uint8_t' to 'int' changes signedness. |
34+
| test.cpp:72:10:72:11 | l4 | Usual arithmetic conversion from 'uint16_t' to 'int' changes signedness. |
35+
| test.cpp:82:10:82:11 | l2 | Integer promotion from 'uint8_t' to 'int' changes signedness. |
36+
| test.cpp:82:15:82:16 | l4 | Integer promotion from 'uint16_t' to 'int' changes signedness. |
37+
| test.cpp:89:5:89:6 | l1 | Integer promotion from 'uint8_t' to 'int' changes signedness. |
38+
| test.cpp:90:5:90:6 | l1 | Integer promotion from 'uint8_t' to 'int' changes signedness. |
39+
| test.cpp:100:6:100:7 | l1 | Integer promotion from 'uint8_t' to 'int' changes signedness. |
40+
| test.cpp:102:6:102:7 | l1 | Integer promotion from 'uint8_t' to 'int' changes signedness. |
41+
| test.cpp:104:6:104:7 | l1 | Integer promotion from 'uint8_t' to 'int' changes signedness. |
42+
| test.cpp:143:11:143:12 | l2 | Usual arithmetic conversion from 'uint32_t' to 'float' changes signedness. |
43+
| test.cpp:143:11:143:12 | l2 | Usual arithmetic conversion from 'uint32_t' to 'float' changes type category. |
44+
| test.cpp:144:11:144:12 | l2 | Usual arithmetic conversion from 'uint32_t' to 'float' changes signedness. |
45+
| test.cpp:144:11:144:12 | l2 | Usual arithmetic conversion from 'uint32_t' to 'float' changes type category. |
46+
| test.cpp:145:11:145:12 | l2 | Usual arithmetic conversion from 'uint32_t' to 'float' changes signedness. |
47+
| test.cpp:145:11:145:12 | l2 | Usual arithmetic conversion from 'uint32_t' to 'float' changes type category. |

0 commit comments

Comments
 (0)