Skip to content

Commit 89ee1b7

Browse files
Limit results, support unions, filter std::array and va_args
1 parent 72383c2 commit 89ee1b7

File tree

3 files changed

+104
-29
lines changed

3 files changed

+104
-29
lines changed

cpp/misra/src/rules/RULE-15-1-4/NonStaticMemberNotInitBeforeUse.ql

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
import cpp
17+
import codingstandards.cpp.StdNamespace
1718
import codingstandards.cpp.misra
1819
import codingstandards.cpp.types.TrivialType
1920

@@ -39,7 +40,10 @@ class RelevantAggregate extends Class {
3940

4041
RelevantAggregate() {
4142
isAggregateClass(this) and
42-
f = getAField()
43+
f = getAField() and
44+
not getNamespace() instanceof StdNS and
45+
// Some aggregates, such as va_list, have no location
46+
exists(getLocation())
4347
}
4448

4549
CheckedField getField() { result = f }
@@ -100,6 +104,7 @@ class IncompleteConstructor extends Constructor, IncompleteInitialization {
100104
not ctorInitializesCheckedField(this, checkedField) and
101105
// aggregate classes are allowed and do not initialize members
102106
not isAggregateClass(getDeclaringType()) and
107+
not getDeclaringType() instanceof Union and
103108
this.getDeclaringType().hasDefinition() and
104109
not this.isDeleted() and
105110
// Delegating constructors do not need to initialize members
@@ -170,15 +175,13 @@ predicate typeContainsAggregate(Type t, RelevantAggregate aggregate) {
170175
* Note that `aggregate agg;` as a member of an aggregate class is compliant, and as a member of a
171176
* non-aggregate class will be checked at the outer class constructor definition.
172177
*/
173-
class IncompleteAggregateInit extends Variable, IncompleteInitialization {
178+
class IncompleteAggregateInit extends LocalVariable, IncompleteInitialization {
174179
RelevantAggregate aggregate;
175180

176181
IncompleteAggregateInit() {
177182
typeContainsAggregate(getType(), aggregate) and
178183
// agg{} is allowed, and agg; is not.
179-
not this.hasInitializer() and
180-
// Aggregate members may be initialized by constructor or belong to another aggregate.
181-
not this instanceof MemberVariable
184+
not this.hasInitializer()
182185
}
183186

184187
override CheckedField getField() { result = aggregate.getField() }
@@ -205,8 +208,25 @@ class IncompleteAggregateNew extends NewOrNewArrayExpr, IncompleteInitialization
205208
override string getKindStr() { result = "Aggregate new expression" }
206209
}
207210

208-
from IncompleteInitialization init, CheckedField f
211+
predicate test(IncompleteConstructor c, CheckedField f) {
212+
c.getField() = f and
213+
f.getName() = "num_polls" and
214+
not exists(f.getInitializer()) and
215+
not f.hasInitializer() and
216+
not exists(f.getAnAssignment())
217+
}
218+
219+
from IncompleteInitialization init, CheckedField f, int total, int ranked, string suffix
209220
where
210221
not isExcluded(init, Classes4Package::nonStaticMemberNotInitBeforeUseQuery()) and
211-
f = init.getField()
212-
select init, init.getKindStr() + " does not initialize non-static data member $@", f, f.getName()
222+
total = count(init.getField()) and
223+
f =
224+
rank[ranked](Field candidate |
225+
candidate = init.getField()
226+
|
227+
candidate order by candidate.getName()
228+
) and
229+
ranked <= 3 and
230+
if total > 1 then suffix = " (and " + (total - 1) + " more)" else suffix = ""
231+
select init, init.getKindStr() + " does not initialize non-static data member $@" + suffix + ".", f,
232+
f.getName()
Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
1-
| test.cpp:35:3:35:14 | MemberUninit | Constructor does not initialize non-static data member $@ | test.cpp:36:16:36:17 | m1 | m1 |
2-
| test.cpp:45:3:45:19 | MemberUninitArray | Constructor does not initialize non-static data member $@ | test.cpp:46:16:46:17 | m1 | m1 |
3-
| test.cpp:50:3:50:21 | MemberUninitPointer | Constructor does not initialize non-static data member $@ | test.cpp:51:17:51:18 | m1 | m1 |
4-
| test.cpp:55:3:55:21 | MemberUninitAndInit | Constructor does not initialize non-static data member $@ | test.cpp:56:16:56:17 | m1 | m1 |
5-
| test.cpp:62:3:62:15 | MultipleCtors | Constructor does not initialize non-static data member $@ | test.cpp:65:16:65:17 | m1 | m1 |
6-
| test.cpp:74:3:74:21 | DefaultedCtorUninit | Constructor does not initialize non-static data member $@ | test.cpp:75:16:75:17 | m2 | m2 |
7-
| test.cpp:85:3:85:16 | CopyMoveUninit | Constructor does not initialize non-static data member $@ | test.cpp:87:16:87:17 | m1 | m1 |
8-
| test.cpp:86:3:86:16 | CopyMoveUninit | Constructor does not initialize non-static data member $@ | test.cpp:87:16:87:17 | m1 | m1 |
9-
| test.cpp:104:3:104:37 | DelegatingCtorSameClassNonCompliant | Constructor does not initialize non-static data member $@ | test.cpp:109:16:109:17 | m1 | m1 |
10-
| test.cpp:120:3:120:32 | DelegatingCtorBaseNonCompliant | Constructor does not initialize non-static data member $@ | test.cpp:121:16:121:17 | m1 | m1 |
11-
| test.cpp:147:3:147:62 | using DelegateToNonCompliantBase | Using declaration with base constructor does not initialize non-static data member $@ | test.cpp:148:16:148:17 | m1 | m1 |
12-
| test.cpp:202:24:202:25 | l4 | Aggregate variable does not initialize non-static data member $@ | test.cpp:177:16:177:17 | m1 | m1 |
13-
| test.cpp:207:24:207:25 | l9 | Aggregate variable does not initialize non-static data member $@ | test.cpp:177:16:177:17 | m1 | m1 |
14-
| test.cpp:210:3:210:26 | new | Aggregate new expression does not initialize non-static data member $@ | test.cpp:177:16:177:17 | m1 | m1 |
15-
| test.cpp:213:3:213:29 | new[] | Aggregate new expression does not initialize non-static data member $@ | test.cpp:177:16:177:17 | m1 | m1 |
16-
| test.cpp:217:36:217:38 | l12 | Aggregate variable does not initialize non-static data member $@ | test.cpp:186:24:186:25 | m1 | m1 |
17-
| test.cpp:220:36:220:38 | l15 | Aggregate variable does not initialize non-static data member $@ | test.cpp:186:24:186:25 | m1 | m1 |
18-
| test.cpp:222:3:222:38 | new | Aggregate new expression does not initialize non-static data member $@ | test.cpp:186:24:186:25 | m1 | m1 |
19-
| test.cpp:241:3:241:32 | HasAggregateMemberNonCompliant | Constructor does not initialize non-static data member $@ | test.cpp:242:24:242:25 | m1 | m1 |
20-
| test.cpp:241:3:241:32 | HasAggregateMemberNonCompliant | Constructor does not initialize non-static data member $@ | test.cpp:243:36:243:37 | m2 | m2 |
21-
| test.cpp:253:3:253:43 | HasUninitArrayAggregateMemberNonCompliant | Constructor does not initialize non-static data member $@ | test.cpp:254:24:254:25 | m1 | m1 |
1+
| test.cpp:35:3:35:14 | MemberUninit | Constructor does not initialize non-static data member $@. | test.cpp:36:16:36:17 | m1 | m1 |
2+
| test.cpp:45:3:45:19 | MemberUninitArray | Constructor does not initialize non-static data member $@. | test.cpp:46:16:46:17 | m1 | m1 |
3+
| test.cpp:50:3:50:21 | MemberUninitPointer | Constructor does not initialize non-static data member $@. | test.cpp:51:17:51:18 | m1 | m1 |
4+
| test.cpp:55:3:55:21 | MemberUninitAndInit | Constructor does not initialize non-static data member $@. | test.cpp:56:16:56:17 | m1 | m1 |
5+
| test.cpp:62:3:62:15 | MultipleCtors | Constructor does not initialize non-static data member $@. | test.cpp:65:16:65:17 | m1 | m1 |
6+
| test.cpp:74:3:74:21 | DefaultedCtorUninit | Constructor does not initialize non-static data member $@. | test.cpp:75:16:75:17 | m2 | m2 |
7+
| test.cpp:85:3:85:16 | CopyMoveUninit | Constructor does not initialize non-static data member $@. | test.cpp:87:16:87:17 | m1 | m1 |
8+
| test.cpp:86:3:86:16 | CopyMoveUninit | Constructor does not initialize non-static data member $@. | test.cpp:87:16:87:17 | m1 | m1 |
9+
| test.cpp:104:3:104:37 | DelegatingCtorSameClassNonCompliant | Constructor does not initialize non-static data member $@. | test.cpp:109:16:109:17 | m1 | m1 |
10+
| test.cpp:120:3:120:32 | DelegatingCtorBaseNonCompliant | Constructor does not initialize non-static data member $@. | test.cpp:121:16:121:17 | m1 | m1 |
11+
| test.cpp:147:3:147:62 | using DelegateToNonCompliantBase | Using declaration with base constructor does not initialize non-static data member $@. | test.cpp:148:16:148:17 | m1 | m1 |
12+
| test.cpp:202:24:202:25 | l4 | Aggregate variable does not initialize non-static data member $@. | test.cpp:177:16:177:17 | m1 | m1 |
13+
| test.cpp:207:24:207:25 | l9 | Aggregate variable does not initialize non-static data member $@. | test.cpp:177:16:177:17 | m1 | m1 |
14+
| test.cpp:210:3:210:26 | new | Aggregate new expression does not initialize non-static data member $@. | test.cpp:177:16:177:17 | m1 | m1 |
15+
| test.cpp:213:3:213:29 | new[] | Aggregate new expression does not initialize non-static data member $@. | test.cpp:177:16:177:17 | m1 | m1 |
16+
| test.cpp:217:36:217:38 | l12 | Aggregate variable does not initialize non-static data member $@. | test.cpp:186:24:186:25 | m1 | m1 |
17+
| test.cpp:220:36:220:38 | l15 | Aggregate variable does not initialize non-static data member $@. | test.cpp:186:24:186:25 | m1 | m1 |
18+
| test.cpp:222:3:222:38 | new | Aggregate new expression does not initialize non-static data member $@. | test.cpp:186:24:186:25 | m1 | m1 |
19+
| test.cpp:245:3:245:32 | HasAggregateMemberNonCompliant | Constructor does not initialize non-static data member $@ (and 1 more). | test.cpp:246:24:246:25 | m1 | m1 |
20+
| test.cpp:245:3:245:32 | HasAggregateMemberNonCompliant | Constructor does not initialize non-static data member $@ (and 1 more). | test.cpp:247:36:247:37 | m2 | m2 |
21+
| test.cpp:257:3:257:43 | HasUninitArrayAggregateMemberNonCompliant | Constructor does not initialize non-static data member $@. | test.cpp:258:24:258:25 | m1 | m1 |
22+
| test.cpp:267:18:267:18 | a | Aggregate variable does not initialize non-static data member $@ (and 9 more). | test.cpp:262:7:262:8 | m1 | m1 |
23+
| test.cpp:267:18:267:18 | a | Aggregate variable does not initialize non-static data member $@ (and 9 more). | test.cpp:262:11:262:12 | m2 | m2 |
24+
| test.cpp:267:18:267:18 | a | Aggregate variable does not initialize non-static data member $@ (and 9 more). | test.cpp:262:43:262:45 | m10 | m10 |
25+
| test.cpp:290:18:290:18 | a | Aggregate variable does not initialize non-static data member $@ (and 1 more). | test.cpp:285:9:285:10 | m1 | m1 |
26+
| test.cpp:290:18:290:18 | a | Aggregate variable does not initialize non-static data member $@ (and 1 more). | test.cpp:286:11:286:12 | m2 | m2 |

cpp/misra/test/rules/RULE-15-1-4/test.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,10 @@ void test_aggregates() {
228228
new int *; // COMPLIANT
229229
}
230230

231+
// Static aggregates are zero-initialized even with the `x y;` syntax.
232+
AggregateFieldUninit g1; // COMPLIANT
233+
AggregateFieldUninit g2[2]; // COMPLIANT
234+
231235
class HasAggregateMemberCompliant {
232236
HasAggregateMemberCompliant() : m3{0}, m5{0} {}
233237
AggregateFieldCtor m1;
@@ -252,4 +256,50 @@ class HasAggregateMemberCompliantInit {
252256
class HasUninitArrayAggregateMemberNonCompliant {
253257
HasUninitArrayAggregateMemberNonCompliant() {} // NON_COMPLIANT
254258
AggregateFieldUninit m1[5];
259+
};
260+
261+
struct NoisyAggregate {
262+
int m1, m2, m3, m4, m5, m6, m7, m8, m9, m10;
263+
};
264+
265+
void useNoisyAggregate() {
266+
// This should not report 10 results, as that would be very noisy.
267+
NoisyAggregate a; // NON_COMPLIANT
268+
}
269+
270+
#include <array>
271+
namespace std {
272+
struct Aggregate {
273+
int m1;
274+
};
275+
} // namespace std
276+
void useStd() {
277+
// std::array is the only aggregate in the STL according to the spec, but
278+
// we should categorically exclude
279+
std::array<int, 5> a; // COMPLIANT
280+
std::Aggregate a2; // COMPLIANT
281+
}
282+
283+
void useUnionAggregate() {
284+
union UnionAggregate {
285+
int m1;
286+
float m2;
287+
};
288+
289+
// Unions are aggregates, but we should not report on them.
290+
UnionAggregate a; // NON_COMPLIANT
291+
UnionAggregate a2{}; // COMPLIANT
292+
UnionAggregate a3 = {}; // COMPLIANT
293+
UnionAggregate a4{.m1 = 0}; // COMPLIANT
294+
UnionAggregate a5{.m2 = 0.0}; // COMPLIANT
295+
}
296+
297+
union UnionWithConstructor {
298+
int m1;
299+
float m2;
300+
// Union constructors can only initialize a single member.
301+
UnionWithConstructor(int m1) : m1(m1) {} // COMPLIANT
302+
// Union constructors should still be required to initialize one member, but
303+
// this is not implemented.
304+
UnionWithConstructor() {} // NON_COMPLIANT[False negative]
255305
};

0 commit comments

Comments
 (0)