Skip to content

Commit 810a775

Browse files
committed
EssentialTypes: Implement Rule 10.4
Adds a query that finds operands to operators with the usual arithmetic conversions that are incompatible.
1 parent fe01ab8 commit 810a775

File tree

4 files changed

+104
-0
lines changed

4 files changed

+104
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* @id c/misra/operands-with-mismatched-essential-type-category
3+
* @name RULE-10-4: Both operands of an operator in which the usual arithmetic conversions are performed shall have the
4+
* @description Both operands of an operator in which the usual arithmetic conversions are performed
5+
* shall have the same essential type category
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-10-4
10+
* external/misra/obligation/required
11+
*/
12+
13+
import cpp
14+
import codingstandards.c.misra
15+
import codingstandards.c.misra.EssentialTypes
16+
import codingstandards.c.misra.MisraExpressions
17+
18+
from
19+
OperationWithUsualArithmeticConversions op, Type leftOpEssentialType, Type rightOpEssentialType,
20+
EssentialTypeCategory leftOpTypeCategory, EssentialTypeCategory rightOpTypeCategory,
21+
string message
22+
where
23+
not isExcluded(op, EssentialTypesPackage::operandsWithMismatchedEssentialTypeCategoryQuery()) and
24+
leftOpEssentialType = getEssentialType(op.getLeftOperand()) and
25+
rightOpEssentialType = getEssentialType(op.getRightOperand()) and
26+
leftOpTypeCategory = getEssentialTypeCategory(leftOpEssentialType) and
27+
rightOpTypeCategory = getEssentialTypeCategory(rightOpEssentialType) and
28+
(
29+
not leftOpTypeCategory = rightOpTypeCategory and
30+
message =
31+
"The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: "
32+
+ leftOpTypeCategory + ", right operand: " + rightOpTypeCategory + ")."
33+
or
34+
// This is not technically covered by the rule, but the examples make it clear that this should
35+
// be reported as non-compliant.
36+
leftOpTypeCategory = EssentiallyEnumType() and
37+
rightOpTypeCategory = EssentiallyEnumType() and
38+
not leftOpEssentialType = rightOpEssentialType and
39+
message =
40+
"The operands of this operator with usual arithmetic conversions have mismatched essentially Enum types (left operand: "
41+
+ leftOpEssentialType + ", right operand: " + rightOpEssentialType + ")."
42+
) and
43+
not (
44+
// Mismatch is permitted if using "+" or "+=" with one character operand and one integer operand
45+
op.getOperator() = ["+", "+="] and
46+
[leftOpTypeCategory, rightOpTypeCategory] = EssentiallyCharacterType() and
47+
[leftOpTypeCategory, rightOpTypeCategory] =
48+
[EssentiallyUnsignedType().(TEssentialTypeCategory), EssentiallySignedType()]
49+
) and
50+
not (
51+
// Mismatch is permitted if using "+" or "+=" with one pointer operand and one integer operand
52+
op.getOperator() = ["-", "-="] and
53+
leftOpTypeCategory = EssentiallyCharacterType() and
54+
rightOpTypeCategory =
55+
[EssentiallyUnsignedType().(TEssentialTypeCategory), EssentiallySignedType()]
56+
)
57+
select op, message
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
| test.c:14:3:14:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Unsigned type, right operand: essentially Signed type). |
2+
| test.c:15:3:15:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Unsigned type). |
3+
| test.c:16:3:16:10 | ... += ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Unsigned type). |
4+
| test.c:17:3:17:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Floating type, right operand: essentially Signed type). |
5+
| test.c:18:3:18:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Floating type). |
6+
| test.c:19:3:19:10 | ... += ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Floating type). |
7+
| test.c:27:3:27:9 | ... - ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Character type). |
8+
| test.c:28:3:28:10 | ... -= ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Character type). |
9+
| test.c:34:3:34:11 | ... < ... | The operands of this operator with usual arithmetic conversions have mismatched essentially Enum types (left operand: E1, right operand: E2). |
10+
| test.c:35:3:35:7 | ... < ... | The operands of this operator with usual arithmetic conversions have mismatched essentially Enum types (left operand: E1, right operand: E2). |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.ql

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
void testOps() {
2+
signed int s32 = 100;
3+
signed long long s64 = 100;
4+
unsigned int u = 100;
5+
float f = 10.0f;
6+
char c = 'A';
7+
8+
s32 + s32; // COMPLIANT
9+
s64 + s64; // COMPLIANT
10+
s32 + s64; // COMPLIANT
11+
s64 + s32; // COMPLIANT
12+
s64 += s32; // COMPLIANT
13+
s32 += s64; // COMPLIANT
14+
u + s32; // NON_COMPLIANT
15+
s32 + u; // NON_COMPLIANT
16+
s32 += u; // NON_COMPLIANT
17+
f + s32; // NON_COMPLIANT
18+
s32 + f; // NON_COMPLIANT
19+
s32 += f; // NON_COMPLIANT
20+
21+
c + s32; // COMPLIANT - by exception
22+
c += s32; // COMPLIANT - by exception
23+
s32 + c; // COMPLIANT - by exception
24+
s32 += c; // COMPLIANT - by exception
25+
c - s32; // COMPLIANT - by exception
26+
c -= s32; // COMPLIANT - by exception
27+
s32 - c; // NON_COMPLIANT
28+
s32 -= c; // NON_COMPLIANT
29+
30+
enum E1 { A, B, C } e1a;
31+
enum E2 { D, E, F } e2a;
32+
e1a < e1a; // COMPLIANT
33+
A < A; // COMPLIANT
34+
e1a < e2a; // NON_COMPLIANT
35+
A < D; // NON_COMPLIANT
36+
}

0 commit comments

Comments
 (0)