@@ -94,6 +94,97 @@ class IntegerPromotion extends RelevantRealConversion {
9494 override string getKindOfConversion ( ) { result = "Integer promotion" }
9595}
9696
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+
97188from Expr e , RelevantConversion c , NumericType fromType , NumericType toType , string changeType
98189where
99190 not isExcluded ( e , ConversionsPackage:: noSignednessChangeFromPromotionQuery ( ) ) and
0 commit comments