|
| 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 |
0 commit comments