Skip to content

Commit 87a1780

Browse files
committed
DeadCode: Add MISRA C 2012 Rule 2.4
Add a query for finding unused tags. This query uses `TypeMention`s to identify tags that are never referenced. Note: this query tries to exclude tags generated from macros, but this is not currently working due to a bug in the CodeQL CLI 2.9.4.
1 parent 57e164c commit 87a1780

File tree

5 files changed

+127
-0
lines changed

5 files changed

+127
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* @id c/misra/unused-tag-declaration
3+
* @name RULE-2-4: A project should not contain unused tag declarations
4+
* @description Unused tag declarations are either redundant or indicate a possible mistake on the
5+
* part of the programmer.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity warning
9+
* @tags external/misra/id/rule-2-4
10+
* readability
11+
* maintainability
12+
* external/misra/obligation/advisory
13+
*/
14+
15+
import cpp
16+
import codingstandards.c.misra
17+
import codingstandards.cpp.TypeUses
18+
19+
from UserType s
20+
where
21+
not isExcluded(s, DeadCodePackage::unusedTagDeclarationQuery()) and
22+
// ignore structs without a tag name
23+
not s.getName() = "struct <unnamed>" and
24+
// typedefs do not have a "tag" name, so this rule does not apply to them
25+
not s instanceof TypedefType and
26+
// Not mentioned anywhere
27+
not exists(TypeMention tm | tm.getMentionedType() = s) and
28+
// Exclude any struct that is fully generated from a macro expansion, as it may be used in other
29+
// expansions of the same macro.
30+
// Note: due to a bug in the CodeQL CLI version 2.9.4, this will currently have no effect, because
31+
// `isInMacroExpansion` is broken for `UserType`s.
32+
not s.isInMacroExpansion()
33+
select s, "struct " + s.getName() + " has an unused tag."
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
| test.c:4:8:4:9 | S2 | struct S2 has an unused tag. |
2+
| test.c:7:16:7:17 | S3 | struct S3 has an unused tag. |
3+
| test.c:17:6:17:7 | E1 | struct E1 has an unused tag. |
4+
| test.c:31:10:31:11 | S7 | struct S7 has an unused tag. |
5+
| test.c:50:8:50:10 | S10 | struct S10 has an unused tag. |
6+
| test.c:66:3:66:14 | S13 | struct S13 has an unused tag. |
7+
| test.c:79:8:79:10 | s14 | struct s14 has an unused tag. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-2-4/UnusedTagDeclaration.ql

c/misra/test/rules/RULE-2-4/test.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
struct S1 { // COMPLIANT
2+
int x;
3+
};
4+
struct S2 { // NON_COMPLIANT
5+
int x;
6+
};
7+
typedef struct S3 { // NON_COMPLIANT
8+
int x;
9+
} T1;
10+
typedef struct S4 { // COMPLIANT
11+
int x;
12+
} T2;
13+
struct S5 { // COMPLIANT
14+
int x;
15+
};
16+
typedef struct S5 T3;
17+
enum E1 { state1, state2 }; // NON_COMPLIANT
18+
enum E2 { state3, state4 }; // COMPLIANT
19+
struct { // COMPLIANT - no tag
20+
int x;
21+
} s6;
22+
23+
void test() {
24+
struct S1 s1;
25+
T1 t1;
26+
t1.x = 0; // Field access on struct S3
27+
T2 t2;
28+
struct S4 s4;
29+
int x = state1; // enum access on E1
30+
enum E2 e2;
31+
struct S7 { // NON_COMPLIANT
32+
int x
33+
} s7;
34+
struct S8 { // COMPLIANT
35+
int x
36+
} s8;
37+
struct S8 s8_2;
38+
39+
struct S11 { // COMPLIANT
40+
int x;
41+
} foo(struct S11 s);
42+
}
43+
44+
struct S9 { // COMPLIANT
45+
int x;
46+
} test_2() {
47+
return (struct S9){0};
48+
}
49+
50+
struct S10 { // NON_COMPLIANT
51+
int x;
52+
} * test_3() {
53+
return 0;
54+
}
55+
56+
struct S12 { // COMPLIANT
57+
int x;
58+
} foo(struct S12 s);
59+
60+
#define STRUCT_MACRO \
61+
struct S13 { \
62+
int x; \
63+
};
64+
65+
void testMacroNameUsed() {
66+
STRUCT_MACRO // COMPLIANT[FALSE_POSITIVE] - although the struct generated by
67+
// the macro is never used in this expansion, it may be used in
68+
// other expansions, so we don't want to report it as unused
69+
}
70+
71+
void testMacroNameNotUsed() {
72+
STRUCT_MACRO // COMPLIANT - S13 is used in this expansion
73+
struct S13 s13_2;
74+
}
75+
76+
#define PARTIAL \
77+
{ int x; }
78+
79+
struct s14 PARTIAL; // NON_COMPLIANT - affected by macro, but not fully
80+
// generated, so fair to report as unused

c/misra/test/rules/RULE-2-4/test.ql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import cpp
2+
3+
// from UserType ut
4+
// where ut.isAffectedByMacro()
5+
// select ut
6+
select any(Location l).toString() as s, count(Location l | l.toString() = s)

0 commit comments

Comments
 (0)