|
16 | 16 | import cpp |
17 | 17 | import codingstandards.cpp.autosar |
18 | 18 |
|
19 | | -newtype TTemplateElement = |
20 | | - TTemplateClass(TemplateClass c) or |
21 | | - TTemplateFunction(TemplateFunction f) or |
22 | | - TTemplateVariable(TemplateVariable v) |
23 | | - |
24 | | -/** |
25 | | - * A templated element. These are either templated classes, templated functions, |
26 | | - * or templated variables. |
27 | | - */ |
28 | | -class TemplateElement extends TTemplateElement { |
29 | | - TemplateClass asTemplateClass() { this = TTemplateClass(result) } |
30 | | - |
31 | | - TemplateFunction asTemplateFunction() { this = TTemplateFunction(result) } |
32 | | - |
33 | | - TemplateVariable asTemplateVariable() { this = TTemplateVariable(result) } |
34 | | - |
35 | | - string toString() { |
36 | | - result = this.asTemplateClass().toString() or |
37 | | - result = this.asTemplateFunction().toString() or |
38 | | - result = this.asTemplateVariable().toString() |
39 | | - } |
40 | | - |
41 | | - Location getLocation() { |
42 | | - result = this.asTemplateClass().getLocation() or |
43 | | - result = this.asTemplateFunction().getLocation() or |
44 | | - result = this.asTemplateVariable().getLocation() |
45 | | - } |
46 | | - |
47 | | - string getName() { |
48 | | - result = this.asTemplateClass().getName() or |
49 | | - result = this.asTemplateFunction().getName() or |
50 | | - result = this.asTemplateVariable().getName() |
51 | | - } |
52 | | -} |
53 | | - |
54 | | -newtype TTemplateInstantiation = |
55 | | - TClassTemplateInstantiation(ClassTemplateInstantiation c) or |
56 | | - TFunctionTemplateInstantiation(FunctionTemplateInstantiation f) or |
57 | | - TVariableTemplateInstantiation(VariableTemplateInstantiation v) |
58 | | - |
59 | | -/** |
60 | | - * An instantiation of a templated element, either a templated class, templated |
61 | | - * function, or templated variable. |
62 | | - */ |
63 | | -class TemplateInstantiation extends TTemplateInstantiation { |
64 | | - ClassTemplateInstantiation asClassTemplateInstantiation() { |
65 | | - this = TClassTemplateInstantiation(result) |
66 | | - } |
67 | | - |
68 | | - FunctionTemplateInstantiation asFunctionTemplateInstantiation() { |
69 | | - this = TFunctionTemplateInstantiation(result) |
70 | | - } |
71 | | - |
72 | | - VariableTemplateInstantiation asVariableTemplateInstantiation() { |
73 | | - this = TVariableTemplateInstantiation(result) |
74 | | - } |
75 | | - |
76 | | - string toString() { |
77 | | - result = this.asClassTemplateInstantiation().toString() or |
78 | | - result = this.asFunctionTemplateInstantiation().toString() or |
79 | | - result = this.asVariableTemplateInstantiation().toString() |
80 | | - } |
81 | | - |
82 | | - Location getLocation() { |
83 | | - result = this.asClassTemplateInstantiation().getLocation() or |
84 | | - result = this.asFunctionTemplateInstantiation().getLocation() or |
85 | | - result = this.asVariableTemplateInstantiation().getLocation() |
86 | | - } |
87 | | - |
88 | | - Element asElement() { |
89 | | - result = this.asClassTemplateInstantiation() or |
90 | | - result = this.asFunctionTemplateInstantiation() or |
91 | | - result = this.asVariableTemplateInstantiation() |
92 | | - } |
93 | | - |
94 | | - /** |
95 | | - * Gets the template this instantiation is from, depending on the kind of the element |
96 | | - * this instantiation is for. |
97 | | - */ |
98 | | - TemplateElement getTemplate() { |
99 | | - result.asTemplateClass() = this.asClassTemplateInstantiation().getTemplate() or |
100 | | - result.asTemplateFunction() = this.asFunctionTemplateInstantiation().getTemplate() or |
101 | | - result.asTemplateVariable() = this.asVariableTemplateInstantiation().getTemplate() |
102 | | - } |
103 | | - |
104 | | - /** |
105 | | - * Gets a use of an instantiation of this template. i.e. |
106 | | - * 1. For a class template, it's where the instantiated type is used by the name. |
107 | | - * 2. For a function template, it's where the instantiated function is called. |
108 | | - * 3. For a variable template, it's where the instantiated variable is initialized. |
109 | | - */ |
110 | | - Element getAUse() { |
111 | | - result = this.asClassTemplateInstantiation().getATypeNameUse() or |
112 | | - result = this.asFunctionTemplateInstantiation().getACallToThisFunction() or |
113 | | - result = this.asVariableTemplateInstantiation() |
114 | | - } |
115 | | -} |
116 | | - |
117 | | -/** |
118 | | - * An implicit conversion from a plain char type to an explicitly signed or unsigned char |
119 | | - * type. `std::uint8_t` and `std::int8_t` are also considered as these char types. |
120 | | - * |
121 | | - * Note that this class only includes implicit conversions and does not include explicit |
122 | | - * type conversions, i.e. casts. |
123 | | - */ |
124 | | -class ImplicitConversionFromPlainCharType extends Conversion { |
125 | | - ImplicitConversionFromPlainCharType() { |
126 | | - this.isImplicit() and |
127 | | - this.getExpr().getUnspecifiedType() instanceof PlainCharType and |
128 | | - ( |
129 | | - this.getUnspecifiedType() instanceof SignedCharType or |
130 | | - this.getUnspecifiedType() instanceof UnsignedCharType |
131 | | - ) |
132 | | - } |
133 | | -} |
134 | | - |
135 | | -newtype TImplicitConversionElement = |
136 | | - TImplicitConversionOutsideTemplate(ImplicitConversionFromPlainCharType implicitConversion) { |
137 | | - not exists(TemplateInstantiation instantiation | |
138 | | - implicitConversion.isFromTemplateInstantiation(instantiation.asElement()) |
139 | | - ) |
140 | | - } or |
141 | | - TInstantiationOfImplicitConversionTemplate( |
142 | | - TemplateInstantiation templateInstantiation, |
143 | | - ImplicitConversionFromPlainCharType implicitConversion |
144 | | - ) { |
145 | | - implicitConversion.getEnclosingElement+() = templateInstantiation.asElement() |
146 | | - } |
147 | | - |
148 | | -/** |
149 | | - * The locations where the implicit conversion from a plain char to an explicitly signed / unsigned |
150 | | - * char is taking place on a high level. It splits case on whether the conversion is caused by |
151 | | - * instantiating a template: |
152 | | - * |
153 | | - * - For conversions not due to template usage (i.e. outside a templated element), this refers to |
154 | | - * the same element as the one associated with the conversion. |
155 | | - * - For conversions due to template usage, this refers to the element that uses the instantiation |
156 | | - * of a template where an implicit char conversion happens. |
157 | | - */ |
158 | | -class ImplicitConversionLocation extends TImplicitConversionElement { |
159 | | - ImplicitConversionFromPlainCharType asImplicitConversionOutsideTemplate() { |
160 | | - this = TImplicitConversionOutsideTemplate(result) |
161 | | - } |
162 | | - |
163 | | - TemplateInstantiation asInstantiationOfImplicitConversionTemplate( |
164 | | - ImplicitConversionFromPlainCharType implicitConversion |
165 | | - ) { |
166 | | - this = TInstantiationOfImplicitConversionTemplate(result, implicitConversion) |
167 | | - } |
168 | | - |
169 | | - /** |
170 | | - * Holds if this is a location of a conversion happening outside of a template. |
171 | | - */ |
172 | | - predicate isImplicitConversionOutsideTemplate() { |
173 | | - exists(this.asImplicitConversionOutsideTemplate()) |
174 | | - } |
175 | | - |
176 | | - /** |
177 | | - * Holds if this is a location of a conversion happening due to instantiating a |
178 | | - * template. |
179 | | - */ |
180 | | - predicate isInstantiationOfImplicitConversionTemplate() { |
181 | | - exists( |
182 | | - TemplateInstantiation templateInstantiation, |
183 | | - ImplicitConversionFromPlainCharType implicitConversion |
184 | | - | |
185 | | - templateInstantiation = this.asInstantiationOfImplicitConversionTemplate(implicitConversion) |
186 | | - ) |
187 | | - } |
188 | | - |
189 | | - /** |
190 | | - * Gets the implicit conversion that this location is associated with. |
191 | | - * - In cases of conversions not involving a template, this is the same as the |
192 | | - * location associated with the conversion. |
193 | | - * - In cases of conversions due to using a template, this is the conversion that |
194 | | - * happens in the instantiated template. |
195 | | - */ |
196 | | - ImplicitConversionFromPlainCharType getImplicitConversion() { |
197 | | - result = this.asImplicitConversionOutsideTemplate() or |
198 | | - exists(TemplateInstantiation templateInstantiation | |
199 | | - this = TInstantiationOfImplicitConversionTemplate(templateInstantiation, result) |
200 | | - ) |
201 | | - } |
202 | | - |
203 | | - string toString() { |
204 | | - result = this.asImplicitConversionOutsideTemplate().toString() or |
205 | | - exists(ImplicitConversionFromPlainCharType implicitConversion | |
206 | | - result = this.asInstantiationOfImplicitConversionTemplate(implicitConversion).toString() |
207 | | - ) |
208 | | - } |
209 | | - |
210 | | - Location getLocation() { |
211 | | - result = this.asImplicitConversionOutsideTemplate().getLocation() or |
212 | | - exists(ImplicitConversionFromPlainCharType implicitConversion | |
213 | | - result = this.asInstantiationOfImplicitConversionTemplate(implicitConversion).getLocation() |
214 | | - ) |
215 | | - } |
216 | | - |
217 | | - Element asElement() { |
218 | | - result = this.asImplicitConversionOutsideTemplate() or |
219 | | - exists(ImplicitConversionFromPlainCharType implicitConversion | |
220 | | - result = this.asInstantiationOfImplicitConversionTemplate(implicitConversion).getAUse() |
221 | | - ) |
222 | | - } |
223 | | -} |
224 | | - |
225 | | -string getMessageTemplate(ImplicitConversionLocation implicitConversionLocation) { |
226 | | - exists(ImplicitConversionFromPlainCharType implicitConversion | |
227 | | - implicitConversion = implicitConversionLocation.getImplicitConversion() |
228 | | - | |
229 | | - implicitConversionLocation.isImplicitConversionOutsideTemplate() and |
230 | | - result = |
231 | | - "Implicit conversion of plain char $@ to '" + implicitConversion.getType().getName() + "'." |
232 | | - or |
233 | | - implicitConversionLocation.isInstantiationOfImplicitConversionTemplate() and |
234 | | - result = |
235 | | - "Implicit conversion of plain char $@ to '" + implicitConversion.getType().getName() + |
236 | | - "' from instantiating template '" + |
237 | | - implicitConversionLocation |
238 | | - .asInstantiationOfImplicitConversionTemplate(implicitConversion) |
239 | | - .getTemplate() |
240 | | - .getName() + "'." |
241 | | - ) |
242 | | -} |
243 | | - |
244 | | -from |
245 | | - ImplicitConversionLocation implicitConversionLocation, |
246 | | - ImplicitConversionFromPlainCharType implicitConversion |
| 19 | +from Conversion c |
247 | 20 | where |
248 | | - not isExcluded(implicitConversionLocation.asElement(), |
| 21 | + not isExcluded(c, |
249 | 22 | StringsPackage::signedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValuesQuery()) and |
250 | | - implicitConversion = implicitConversionLocation.getImplicitConversion() |
251 | | -select implicitConversionLocation.asElement(), getMessageTemplate(implicitConversionLocation), |
252 | | - implicitConversion.getExpr(), "expression" |
| 23 | + /* 1. Focus on implicit conversions only (explicit conversions are acceptable). */ |
| 24 | + c.isImplicit() and |
| 25 | + /* 2. The target type is explicitly signed or unsigned char. */ |
| 26 | + ( |
| 27 | + c.getUnspecifiedType() instanceof SignedCharType or |
| 28 | + c.getUnspecifiedType() instanceof UnsignedCharType |
| 29 | + ) and |
| 30 | + /* 3. Check if the source expression is a plain char type, i.e. not explicitly signed / unsigned. */ |
| 31 | + c.getExpr().getUnspecifiedType() instanceof PlainCharType |
| 32 | +select c, "Implicit conversion of plain char type to $@ with an explicitly signed char type", c, |
| 33 | + c.getUnspecifiedType().getName() |
0 commit comments