Skip to content

Commit 3d2616a

Browse files
committed
Rule 7.0.4: Add support for shift-assignment operators
1 parent db58704 commit 3d2616a

File tree

3 files changed

+77
-9
lines changed

3 files changed

+77
-9
lines changed

cpp/misra/src/rules/RULE-7-0-4/InappropriateBitwiseOrShiftOperands.ql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ where
112112
message = "Shift operator '" + shift.getOperator() + "' requires unsigned left operand."
113113
)
114114
or
115+
// Compound assignment shift operators - left operand must be unsigned
116+
exists(AssignShiftOperation shift |
117+
shift = x and
118+
not isUnsignedType(shift.getLValue().getExplicitlyConverted().getType()) and
119+
message = "Shift operator '" + shift.getOperator() + "' requires unsigned left operand."
120+
)
121+
or
115122
// Shift operators - right operand must be unsigned or constant in valid range
116123
exists(BinaryShiftOperation shift, Expr right |
117124
shift = x and
@@ -122,5 +129,16 @@ where
122129
"Shift operator '" + shift.getOperator() +
123130
"' requires unsigned right operand or constant in valid range."
124131
)
132+
or
133+
// Compound assignment shift operators - right operand must be unsigned or constant in valid range
134+
exists(AssignShiftOperation shift, Expr right |
135+
shift = x and
136+
right = shift.getRValue() and
137+
not isUnsignedType(right.getExplicitlyConverted().getType()) and
138+
not isValidShiftConstantRange(right, shift.getLValue().getExplicitlyConverted().getType()) and
139+
message =
140+
"Shift operator '" + shift.getOperator() +
141+
"' requires unsigned right operand or constant in valid range."
142+
)
125143
)
126144
select x, message

cpp/misra/test/rules/RULE-7-0-4/InappropriateBitwiseOrShiftOperands.expected

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,25 @@
1919
| test.cpp:94:3:94:11 | ... << ... | Shift operator '<<' requires unsigned right operand or constant in valid range. |
2020
| test.cpp:95:3:95:11 | ... >> ... | Shift operator '>>' requires unsigned right operand or constant in valid range. |
2121
| test.cpp:96:3:96:11 | ... >> ... | Shift operator '>>' requires unsigned right operand or constant in valid range. |
22-
| test.cpp:106:3:106:9 | ... << ... | Shift operator '<<' requires unsigned left operand. |
23-
| test.cpp:107:3:107:9 | ... << ... | Shift operator '<<' requires unsigned left operand. |
24-
| test.cpp:108:3:108:9 | ... << ... | Shift operator '<<' requires unsigned left operand. |
25-
| test.cpp:109:3:109:9 | ... << ... | Shift operator '<<' requires unsigned left operand. |
26-
| test.cpp:113:3:113:11 | ... << ... | Shift operator '<<' requires unsigned left operand. |
27-
| test.cpp:117:3:117:30 | ... << ... | Shift operator '<<' requires unsigned left operand. |
28-
| test.cpp:119:3:119:17 | ... << ... | Shift operator '<<' requires unsigned left operand. |
29-
| test.cpp:125:3:125:10 | ... << ... | Shift operator '<<' requires unsigned left operand. |
30-
| test.cpp:133:3:133:11 | ... >> ... | Shift operator '>>' requires unsigned left operand. |
22+
| test.cpp:115:3:115:12 | ... <<= ... | Shift operator '<<=' requires unsigned left operand. |
23+
| test.cpp:116:3:116:12 | ... >>= ... | Shift operator '>>=' requires unsigned left operand. |
24+
| test.cpp:117:3:117:11 | ... <<= ... | Shift operator '<<=' requires unsigned left operand. |
25+
| test.cpp:118:3:118:11 | ... >>= ... | Shift operator '>>=' requires unsigned left operand. |
26+
| test.cpp:121:3:121:12 | ... <<= ... | Shift operator '<<=' requires unsigned right operand or constant in valid range. |
27+
| test.cpp:122:3:122:12 | ... >>= ... | Shift operator '>>=' requires unsigned right operand or constant in valid range. |
28+
| test.cpp:125:3:125:12 | ... <<= ... | Shift operator '<<=' requires unsigned right operand or constant in valid range. |
29+
| test.cpp:126:3:126:12 | ... <<= ... | Shift operator '<<=' requires unsigned right operand or constant in valid range. |
30+
| test.cpp:127:3:127:12 | ... >>= ... | Shift operator '>>=' requires unsigned right operand or constant in valid range. |
31+
| test.cpp:130:3:130:12 | ... <<= ... | Shift operator '<<=' requires unsigned right operand or constant in valid range. |
32+
| test.cpp:131:3:131:12 | ... <<= ... | Shift operator '<<=' requires unsigned right operand or constant in valid range. |
33+
| test.cpp:132:3:132:12 | ... >>= ... | Shift operator '>>=' requires unsigned right operand or constant in valid range. |
34+
| test.cpp:133:3:133:12 | ... >>= ... | Shift operator '>>=' requires unsigned right operand or constant in valid range. |
35+
| test.cpp:143:3:143:9 | ... << ... | Shift operator '<<' requires unsigned left operand. |
36+
| test.cpp:144:3:144:9 | ... << ... | Shift operator '<<' requires unsigned left operand. |
37+
| test.cpp:145:3:145:9 | ... << ... | Shift operator '<<' requires unsigned left operand. |
38+
| test.cpp:146:3:146:9 | ... << ... | Shift operator '<<' requires unsigned left operand. |
39+
| test.cpp:150:3:150:11 | ... << ... | Shift operator '<<' requires unsigned left operand. |
40+
| test.cpp:154:3:154:30 | ... << ... | Shift operator '<<' requires unsigned left operand. |
41+
| test.cpp:156:3:156:17 | ... << ... | Shift operator '<<' requires unsigned left operand. |
42+
| test.cpp:162:3:162:10 | ... << ... | Shift operator '<<' requires unsigned left operand. |
43+
| test.cpp:170:3:170:11 | ... >> ... | Shift operator '>>' requires unsigned left operand. |

cpp/misra/test/rules/RULE-7-0-4/test.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,43 @@ void test_shift_operators_negative_right_operand() {
9696
u32 >> -3; // NON_COMPLIANT
9797
}
9898

99+
void test_compound_assignment_shift_operators() {
100+
std::uint32_t u32 = 0x12345678U;
101+
std::uint8_t u8 = 2U;
102+
std::int32_t s32 = 0x12345678;
103+
std::int8_t s8 = 2;
104+
105+
// Unsigned left operand with unsigned right operand
106+
u32 <<= u8; // COMPLIANT
107+
u32 >>= u8; // COMPLIANT
108+
109+
// Unsigned left operand with constant right operand in valid range
110+
u32 <<= 0; // COMPLIANT
111+
u32 <<= 31; // COMPLIANT
112+
u32 >>= 15; // COMPLIANT
113+
114+
// Signed left operand
115+
s32 <<= u8; // NON_COMPLIANT
116+
s32 >>= u8; // NON_COMPLIANT
117+
s32 <<= 2; // NON_COMPLIANT
118+
s32 >>= 2; // NON_COMPLIANT
119+
120+
// Unsigned left operand with signed right operand
121+
u32 <<= s8; // NON_COMPLIANT
122+
u32 >>= s8; // NON_COMPLIANT
123+
124+
// Right operand out of range
125+
u32 <<= 32; // NON_COMPLIANT
126+
u32 <<= 64; // NON_COMPLIANT
127+
u32 >>= 32; // NON_COMPLIANT
128+
129+
// Negative right operand
130+
u32 <<= -1; // NON_COMPLIANT
131+
u32 <<= -5; // NON_COMPLIANT
132+
u32 >>= -1; // NON_COMPLIANT
133+
u32 >>= -3; // NON_COMPLIANT
134+
}
135+
99136
void test_exception_signed_constant_left_operand_exception() {
100137
// Exception cases for signed constant expressions
101138
1 << 30; // COMPLIANT

0 commit comments

Comments
 (0)