@@ -2,49 +2,98 @@ import cpp
22import codingstandards.cpp.misra
33
44/**
5- * The signedness of a numeric type.
5+ * A MISRA C++ 2023 type category .
66 */
7- newtype Signedness =
8- Signed ( ) or
9- Unsigned ( )
7+ newtype TypeCategory =
8+ Integral ( ) or
9+ FloatingPoint ( ) or
10+ Character ( ) or
11+ Other ( )
1012
1113/**
12- * The type category of a numeric type - either integral or floating-point.
14+ * Gets the type category of a built-in type.
15+ *
16+ * This does not apply the rules related to stripping specifiers or typedefs, or references.
1317 */
14- newtype TypeCategory =
15- Integral ( ) or
16- FloatingPoint ( )
18+ TypeCategory getTypeCategory ( BuiltInType t ) {
19+ (
20+ t instanceof CharType or
21+ t instanceof WideCharType or
22+ t instanceof Char16Type or
23+ t instanceof Char32Type or
24+ t instanceof Char8Type
25+ ) and
26+ result = Character ( )
27+ or
28+ (
29+ // The 5 standard integral types, covering both signed/unsigned variants
30+ // Explicitly list the signed/unsigned `char` to avoid capturing plain `char`, which is of character type category
31+ t instanceof SignedCharType or
32+ t instanceof UnsignedCharType or
33+ t instanceof ShortType or
34+ t instanceof IntType or
35+ t instanceof LongType or
36+ t instanceof LongLongType
37+ ) and
38+ result = Integral ( )
39+ or
40+ (
41+ t instanceof FloatType or
42+ t instanceof DoubleType or
43+ t instanceof LongDoubleType
44+ ) and
45+ result = FloatingPoint ( )
46+ or
47+ (
48+ t instanceof BoolType or
49+ t instanceof VoidType or
50+ t instanceof NullPointerType
51+ ) and
52+ result = Other ( )
53+ }
1754
1855/**
19- * A numeric type is a type that represents a number, either an integral or a floating-point.
56+ * The signedness of a MISRA C++ 2023 numeric type
57+ */
58+ newtype Signedness =
59+ Signed ( ) or
60+ Unsigned ( )
61+
62+ /**
63+ * A MISRA C++ 2023 numeric type is a type that represents a number, either an integral or a floating-point.
2064 *
2165 * In addition to the basic integral and floating-point types, it includes:
2266 * - Enum types with an explicit underlying type that is a numeric type.
2367 * - Typedef'd types that are numeric types.
2468 * - Numeric types with specifiers (e.g., `const`, `volatile`, `restrict`).
2569 */
2670class NumericType extends Type {
71+ // The actual numeric type, which is either an integral or a floating-point type.
2772 Type realType ;
2873
2974 NumericType ( ) {
30- realType = this .getUnspecifiedType ( ) .( ReferenceType ) .getBaseType ( ) .( NumericType ) .getRealType ( ) or
31- realType = this .getUnspecifiedType ( ) .( IntegralType ) or
32- realType = this .getUnspecifiedType ( ) .( FloatingPointType ) or
33- realType = this .getUnspecifiedType ( ) .( Enum ) .getExplicitUnderlyingType ( ) .getUnspecifiedType ( )
75+ // A type which is either an integral or a floating-point type category
76+ getTypeCategory ( this ) = [ Integral ( ) .( TypeCategory ) , FloatingPoint ( ) ] and
77+ realType = this
78+ or
79+ // Any type which, after stripping specifiers and typedefs, is a numeric type
80+ realType = this .getUnspecifiedType ( ) .( NumericType ) .getRealType ( )
81+ or
82+ // Any reference type where the base type is a numeric type
83+ realType = this .( ReferenceType ) .getBaseType ( ) .( NumericType ) .getRealType ( )
84+ or
85+ // Any Enum type with an explicit underlying type that is a numeric type
86+ realType = this .( Enum ) .getExplicitUnderlyingType ( ) .( NumericType ) .getRealType ( )
3487 }
3588
3689 Signedness getSignedness ( ) {
3790 if realType .( IntegralType ) .isUnsigned ( ) then result = Unsigned ( ) else result = Signed ( )
3891 }
3992
40- /** Gets the size of the actual numeric type */
93+ /** Gets the size of the actual numeric type. */
4194 int getRealSize ( ) { result = realType .getSize ( ) }
4295
43- TypeCategory getTypeCategory ( ) {
44- realType instanceof IntegralType and result = Integral ( )
45- or
46- realType instanceof FloatingPointType and result = FloatingPoint ( )
47- }
96+ TypeCategory getTypeCategory ( ) { result = getTypeCategory ( realType ) }
4897
4998 float getUpperBound ( ) { result = typeUpperBound ( realType ) }
5099
@@ -53,6 +102,13 @@ class NumericType extends Type {
53102 Type getRealType ( ) { result = realType }
54103}
55104
105+ /**
106+ * One of the 10 canonical integer types, which are the standard integer types.
107+ */
108+ class CanonicalIntegerTypes extends NumericType , IntegralType {
109+ CanonicalIntegerTypes ( ) { this = this .getCanonicalArithmeticType ( ) }
110+ }
111+
56112predicate isAssignment ( Expr source , NumericType targetType , string context ) {
57113 // Assignment expression (which excludes compound assignments)
58114 exists ( AssignExpr assign |
@@ -119,18 +175,24 @@ predicate isAssignment(Expr source, NumericType targetType, string context) {
119175 *
120176 * The type is determined by the signedness of the bit field and the number of bits.
121177 */
122- NumericType getBitFieldType ( BitField bf ) {
178+ CanonicalIntegerTypes getBitFieldType ( BitField bf ) {
123179 exists ( NumericType bitfieldActualType |
124180 bitfieldActualType = bf .getType ( ) and
125181 // Integral type with the same signedness as the bit field, and big enough to hold the bit field value
126- result instanceof IntegralType and
127182 result .getSignedness ( ) = bitfieldActualType .getSignedness ( ) and
128183 result .getSize ( ) * 8 >= bf .getNumBits ( ) and
129184 // No smaller integral type can hold the bit field value
130- not exists ( IntegralType other |
185+ not exists ( CanonicalIntegerTypes other |
131186 other .getSize ( ) * 8 >= bf .getNumBits ( ) and
132- other .( NumericType ) .getSignedness ( ) = result .getSignedness ( ) and
187+ other .getSignedness ( ) = result .getSignedness ( )
188+ |
133189 other .getSize ( ) < result .getRealSize ( )
190+ or
191+ // Where multiple types exist with the same size and signedness, prefer shorter names - mainly
192+ // to disambiguate between `unsigned long` and `unsigned long long` on platforms where they
193+ // are the same size
194+ other .getSize ( ) = result .getRealSize ( ) and
195+ other .getName ( ) .length ( ) < result .getName ( ) .length ( )
134196 )
135197 )
136198}
0 commit comments