Skip to content

Commit a1f17d3

Browse files
committed
Finalize 10.2.3 and update expected results
1 parent cfc6de7 commit a1f17d3

File tree

2 files changed

+158
-57
lines changed

2 files changed

+158
-57
lines changed

cpp/misra/src/rules/RULE-10-2-3/UnscopedEnumWithoutFixedUnderlyingTypeUsed.ql

Lines changed: 73 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class ArithmeticBitwiseLogicalBinaryOperation extends BinaryOperation {
4040
* `binOp.getLeftOperand().getExplicitlyConverted()` gives `int`.
4141
*/
4242
predicate arithmeticBitwiseLogicalOperationUsesUnscopedUnfixedEnum(
43-
ArithmeticBitwiseLogicalBinaryOperation binOp
43+
ArithmeticBitwiseLogicalBinaryOperation binOp, Enum enum
4444
) {
4545
/*
4646
* We want to strip explicit casts and not implicit ones. Without the
@@ -52,14 +52,11 @@ predicate arithmeticBitwiseLogicalOperationUsesUnscopedUnfixedEnum(
5252
* ```
5353
*/
5454

55-
isUnscopedEnumWithoutFixedUnderlyingType(binOp
56-
.getLeftOperand()
57-
.getExplicitlyConverted()
58-
.getUnderlyingType()) or
59-
isUnscopedEnumWithoutFixedUnderlyingType(binOp
60-
.getRightOperand()
61-
.getExplicitlyConverted()
62-
.getUnderlyingType())
55+
isUnscopedEnumWithoutFixedUnderlyingType(enum) and
56+
(
57+
enum = binOp.getLeftOperand().getExplicitlyConverted().getUnderlyingType() or
58+
enum = binOp.getRightOperand().getExplicitlyConverted().getUnderlyingType()
59+
)
6360
}
6461

6562
class RelationalEqualityBinaryOperation extends BinaryOperation {
@@ -69,7 +66,9 @@ class RelationalEqualityBinaryOperation extends BinaryOperation {
6966
}
7067
}
7168

72-
predicate relationalEqualityOperationUsesUnscopedUnfixedEnum(RelationalEqualityBinaryOperation binOp) {
69+
predicate relationalEqualityOperationUsesUnscopedUnfixedEnum(
70+
RelationalEqualityBinaryOperation binOp, Enum enum
71+
) {
7372
exists(Type leftOperandType, Type rightOperandType |
7473
/*
7574
* We want to strip explicit casts and not implicit ones. Without the
@@ -84,10 +83,10 @@ predicate relationalEqualityOperationUsesUnscopedUnfixedEnum(RelationalEqualityB
8483
leftOperandType = binOp.getLeftOperand().getExplicitlyConverted().getUnderlyingType() and
8584
rightOperandType = binOp.getRightOperand().getExplicitlyConverted().getUnderlyingType()
8685
|
86+
isUnscopedEnumWithoutFixedUnderlyingType(enum) and
8787
(
88-
isUnscopedEnumWithoutFixedUnderlyingType(leftOperandType)
89-
or
90-
isUnscopedEnumWithoutFixedUnderlyingType(rightOperandType)
88+
enum = leftOperandType or
89+
enum = rightOperandType
9190
) and
9291
leftOperandType != rightOperandType
9392
)
@@ -101,9 +100,10 @@ class ArithmeticBitwiseCompoundAssignment extends AssignOperation {
101100
}
102101

103102
predicate compoundAssignmentUsesUnscopedUnfixedEnum(
104-
ArithmeticBitwiseCompoundAssignment compoundAssignment
103+
ArithmeticBitwiseCompoundAssignment compoundAssignment, Enum enum
105104
) {
106-
isUnscopedEnumWithoutFixedUnderlyingType(compoundAssignment.getAnOperand().getUnderlyingType())
105+
isUnscopedEnumWithoutFixedUnderlyingType(enum) and
106+
enum = compoundAssignment.getAnOperand().getUnderlyingType()
107107
}
108108

109109
/**
@@ -164,58 +164,75 @@ predicate enumFitsInType(Enum e, IntegralType type) {
164164
)
165165
}
166166

167-
predicate assignmentSourceIsUnscopedUnfixedEnum(AssignExpr assign) {
168-
isUnscopedEnumWithoutFixedUnderlyingType(assign.getRValue().getUnderlyingType()) and
169-
(
170-
not enumFitsInType(assign.getRValue().getUnderlyingType(),
171-
assign.getLValue().getUnderlyingType()) and
172-
/* Exclude cases where the assignment's target type is the same enum. */
173-
not assign.getRValue().getUnderlyingType() = assign.getLValue().getUnderlyingType()
174-
)
167+
predicate assignmentSourceIsUnscopedUnfixedEnum(AssignExpr assign, Enum enum, Type targetType) {
168+
isUnscopedEnumWithoutFixedUnderlyingType(enum) and
169+
enum = assign.getRValue().getUnderlyingType() and
170+
targetType = assign.getLValue().getUnderlyingType() and
171+
not enumFitsInType(enum, targetType) and
172+
not enum = targetType
175173
}
176174

177-
predicate staticCastSourceIsUnscopedUnfixedEnumVariant(StaticCast cast) {
178-
isUnscopedEnumWithoutFixedUnderlyingType(cast.getExpr().getUnderlyingType()) and
179-
(
180-
not enumFitsInType(cast.getExpr().getUnderlyingType(), cast.getUnderlyingType()) and
181-
/* Exclude cases where the assignment's target type is the same enum. */
182-
not cast.getExpr().getUnderlyingType() = cast.getUnderlyingType()
183-
)
175+
predicate staticCastSourceIsUnscopedUnfixedEnumVariant(StaticCast cast, Enum enum, Type targetType) {
176+
isUnscopedEnumWithoutFixedUnderlyingType(enum) and
177+
enum = cast.getExpr().getUnderlyingType() and
178+
targetType = cast.getUnderlyingType() and
179+
not enumFitsInType(enum, targetType) and
180+
not enum = targetType
184181
}
185182

186-
predicate switchConditionIsAnUnfixedEnumVariant(SwitchStmt switch) {
187-
exists(Enum e |
188-
isUnscopedEnumWithoutFixedUnderlyingType(e) and
189-
e = switch.getExpr().getType() and
190-
exists(SwitchCase case | case = switch.getASwitchCase() |
191-
not case.getExpr().getUnderlyingType() = e
192-
)
193-
)
183+
predicate switchConditionIsAnUnfixedEnumVariant(SwitchStmt switch, Enum enum, SwitchCase invalidCase) {
184+
isUnscopedEnumWithoutFixedUnderlyingType(enum) and
185+
enum = switch.getExpr().getType() and
186+
invalidCase = switch.getASwitchCase() and
187+
not invalidCase.getExpr().getUnderlyingType() = enum
194188
}
195189

196190
/**
197-
* Holds if a `static_cast` expression has an enum with fixed underlying type but
198-
* the target type is not an unscoped enum.
191+
* Holds if a `static_cast` expression has an unscoped enum without fixed
192+
* underlying type as the target type.
199193
*/
200-
predicate staticCastTargetIsUnscopedUnfixedEnumVariant(StaticCast cast) {
201-
exists(Enum e |
202-
e = cast.getType() and
203-
isUnscopedEnumWithoutFixedUnderlyingType(e) and
204-
/* Exclude cases where the assignment's target type is the same enum. */
205-
not cast.getExpr().getType() = e
206-
)
194+
predicate staticCastTargetIsUnscopedUnfixedEnumVariant(StaticCast cast, Enum enum) {
195+
isUnscopedEnumWithoutFixedUnderlyingType(enum) and
196+
enum = cast.getType() and
197+
not cast.getExpr().getType() = enum
207198
}
208199

209-
from Element x
200+
from Element x, Enum enum, string message
210201
where
211202
not isExcluded(x, Banned3Package::unscopedEnumWithoutFixedUnderlyingTypeUsedQuery()) and
212203
(
213-
arithmeticBitwiseLogicalOperationUsesUnscopedUnfixedEnum(x) or
214-
relationalEqualityOperationUsesUnscopedUnfixedEnum(x) or
215-
compoundAssignmentUsesUnscopedUnfixedEnum(x) or
216-
assignmentSourceIsUnscopedUnfixedEnum(x) or
217-
staticCastSourceIsUnscopedUnfixedEnumVariant(x) or
218-
switchConditionIsAnUnfixedEnumVariant(x) or
219-
staticCastTargetIsUnscopedUnfixedEnumVariant(x)
204+
arithmeticBitwiseLogicalOperationUsesUnscopedUnfixedEnum(x, enum) and
205+
message =
206+
"Arithmetic, bitwise, or logical operation uses unscoped enum $@ without fixed underlying type."
207+
or
208+
relationalEqualityOperationUsesUnscopedUnfixedEnum(x, enum) and
209+
message =
210+
"Relational or equality operation compares unscoped enum $@ without fixed underlying type to a different type."
211+
or
212+
compoundAssignmentUsesUnscopedUnfixedEnum(x, enum) and
213+
message = "Compound assignment uses unscoped enum $@ without fixed underlying type."
214+
or
215+
exists(Type targetType |
216+
assignmentSourceIsUnscopedUnfixedEnum(x, enum, targetType) and
217+
message =
218+
"Assignment from unscoped enum $@ without fixed underlying type to '" + targetType.getName()
219+
+ "' which may not be large enough."
220+
)
221+
or
222+
exists(Type targetType |
223+
staticCastSourceIsUnscopedUnfixedEnumVariant(x, enum, targetType) and
224+
message =
225+
"Static cast from unscoped enum $@ without fixed underlying type to '" +
226+
targetType.getName() + "' which may not be large enough."
227+
)
228+
or
229+
exists(SwitchStmt switch |
230+
switchConditionIsAnUnfixedEnumVariant(switch, enum, x) and
231+
message =
232+
"Switch on unscoped enum $@ without fixed underlying type has case not of the same enum type."
233+
)
234+
or
235+
staticCastTargetIsUnscopedUnfixedEnumVariant(x, enum) and
236+
message = "Static cast to unscoped enum $@ without fixed underlying type."
220237
)
221-
select x, "TODO"
238+
select x, message, enum, enum.getName()

0 commit comments

Comments
 (0)