@@ -94,6 +94,97 @@ class IntegerPromotion extends RelevantRealConversion {
94
94
override string getKindOfConversion ( ) { result = "Integer promotion" }
95
95
}
96
96
97
+ class ImpliedUsualArithmeticConversion extends RelevantConversion {
98
+ NumericType fromType ;
99
+ NumericType toType ;
100
+
101
+ ImpliedUsualArithmeticConversion ( ) {
102
+ // The lvalue of an assignment operation does not have a `Conversion` in our model, but
103
+ // it is still subject to usual arithmetic conversions (excepting shifts).
104
+ //
105
+ // rvalues are handled separately in the `UsualArithmeticConversion` class.
106
+ exists ( AssignOperation aop |
107
+ not aop instanceof AssignLShiftExpr and
108
+ not aop instanceof AssignRShiftExpr and
109
+ // lvalue subject to usual arithmetic conversions
110
+ aop .getLValue ( ) = this and
111
+ // From type is the type of the lvalue, which should be a numeric type under the MISRA rule
112
+ fromType = this .getType ( ) and
113
+ // Under usual arithmetic conversions, the converted types of both arguments will be the same,
114
+ // so even though we don't have an explicit conversion, we can still deduce that the target
115
+ // type will be the same as the converted type of the rvalue.
116
+ toType = aop .getRValue ( ) .getFullyConverted ( ) .getType ( ) and
117
+ // Only consider cases where the conversion is not a no-op, for consistency with the `Conversion` class
118
+ not fromType .getRealType ( ) = toType .getRealType ( )
119
+ )
120
+ }
121
+
122
+ override Type getFromType ( ) { result = fromType }
123
+
124
+ override Type getToType ( ) { result = toType }
125
+
126
+ override Expr getConvertedExpr ( ) { result = this }
127
+
128
+ override string getKindOfConversion ( ) { result = "Usual arithmetic conversion" }
129
+ }
130
+
131
+ class ImpliedIntegerPromotion extends RelevantConversion {
132
+ NumericType fromType ;
133
+
134
+ ImpliedIntegerPromotion ( ) {
135
+ (
136
+ exists ( AssignLShiftExpr aop | aop .getLValue ( ) = this ) or
137
+ exists ( AssignRShiftExpr aop | aop .getLValue ( ) = this )
138
+ ) and
139
+ // Only consider integer promotions from MISRA C++ "numeric types" as per the rule
140
+ fromType = this .getType ( ) and
141
+ fromType .getTypeCategory ( ) = Integral ( ) and
142
+ // If the size is less than int, then it is an implied integer promotion
143
+ fromType .getRealSize ( ) < sizeOfInt ( )
144
+ }
145
+
146
+ override Type getFromType ( ) { result = fromType }
147
+
148
+ override IntegralType getToType ( ) {
149
+ // Only report the canonical type - e.g. `int` not `signed int`
150
+ result = result .getCanonicalArithmeticType ( ) and
151
+ if result instanceof Char16Type or result instanceof Char32Type or result instanceof Wchar_t
152
+ then
153
+ // Smallest type that can hold the value of the `fromType`
154
+ result =
155
+ min ( NumericType candidateType |
156
+ (
157
+ candidateType instanceof IntType or
158
+ candidateType instanceof LongType or
159
+ candidateType instanceof LongLongType
160
+ ) and
161
+ fromType .getIntegralUpperBound ( ) <= candidateType .getIntegralUpperBound ( )
162
+ |
163
+ candidateType order by candidateType .getIntegralUpperBound ( )
164
+ )
165
+ else (
166
+ // The result is always `int` or `unsigned int`
167
+ result instanceof IntType and
168
+ if
169
+ // If the `fromType` is signed, the result must be signed
170
+ fromType .getSignedness ( ) = Signed ( )
171
+ or
172
+ // If the `fromType` is unsigned, but the result can fit into the signed int type, then the
173
+ // result must be signed as well.
174
+ fromType .getIntegralUpperBound ( ) <=
175
+ any ( IntType t | t .isSigned ( ) ) .( NumericType ) .getIntegralUpperBound ( )
176
+ then result .isSigned ( )
177
+ else
178
+ // Otherwise an unsigned type is returned
179
+ result .isUnsigned ( )
180
+ )
181
+ }
182
+
183
+ override Expr getConvertedExpr ( ) { result = this }
184
+
185
+ override string getKindOfConversion ( ) { result = "Integer promotion" }
186
+ }
187
+
97
188
from Expr e , RelevantConversion c , NumericType fromType , NumericType toType , string changeType
98
189
where
99
190
not isExcluded ( e , ConversionsPackage:: noSignednessChangeFromPromotionQuery ( ) ) and
0 commit comments