Skip to content

Commit a1398a4

Browse files
authored
Merge pull request #535 from rvermeulen/rvermeulen/fix-384
Fix FP reported in 384
2 parents 65fba17 + c702ee5 commit a1398a4

10 files changed

+82
-21
lines changed
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- `M0-1-3` - `UnusedMemberVariable.ql`, `UnusedGlobalOrNamespaceVariable.ql`:
2+
- Address FP reported in #384. Exclude variables with compile time values that may have been used as a template argument.
3+
- Exclude uninstantiated template members.
4+
- Reformat the alert message to adhere to the style-guide.

cpp/autosar/src/rules/M0-1-3/UnusedGlobalOrNamespaceVariable.ql

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,7 @@ from PotentiallyUnusedGlobalOrNamespaceVariable v
2222
where
2323
not isExcluded(v, DeadCodePackage::unusedGlobalOrNamespaceVariableQuery()) and
2424
// No variable access
25-
not exists(v.getAnAccess())
26-
select v, "Variable " + v.getQualifiedName() + " is unused."
25+
not exists(v.getAnAccess()) and
26+
// Exclude members whose value is compile time and is potentially used to inintialize a template
27+
not maybeACompileTimeTemplateArgument(v)
28+
select v, "Variable '" + v.getQualifiedName() + "' is unused."

cpp/autosar/src/rules/M0-1-3/UnusedLocalVariable.ql

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ where
5050
// Local variable is never accessed
5151
not exists(v.getAnAccess()) and
5252
getUseCountConservatively(v) = 0
53-
select v, "Local variable " + v.getName() + " in " + v.getFunction().getName() + " is not used."
53+
select v, "Local variable '" + v.getName() + "' in '" + v.getFunction().getName() + "' is not used."

cpp/autosar/src/rules/M0-1-3/UnusedMemberVariable.ql

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,7 @@ where
2525
// No variable access
2626
not exists(v.getAnAccess()) and
2727
// No explicit initialization in a constructor
28-
not exists(UserProvidedConstructorFieldInit cfi | cfi.getTarget() = v)
29-
select v, "Member variable " + v.getName() + " is unused."
28+
not exists(UserProvidedConstructorFieldInit cfi | cfi.getTarget() = v) and
29+
// Exclude members whose value is compile time and is potentially used to inintialize a template
30+
not maybeACompileTimeTemplateArgument(v)
31+
select v, "Member variable '" + v.getName() + "' is unused."
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
| test_global_or_namespace.cpp:3:5:3:6 | g3 | Variable g3 is unused. |
2-
| test_global_or_namespace.cpp:18:4:18:4 | a | Variable a is unused. |
3-
| test_global_or_namespace.cpp:26:5:26:6 | x3 | Variable N1::x3 is unused. |
4-
| test_global_or_namespace.cpp:36:5:36:5 | a | Variable N1::a is unused. |
1+
| test_global_or_namespace.cpp:3:5:3:6 | g3 | Variable 'g3' is unused. |
2+
| test_global_or_namespace.cpp:18:4:18:4 | a | Variable 'a' is unused. |
3+
| test_global_or_namespace.cpp:26:5:26:6 | x3 | Variable 'N1::x3' is unused. |
4+
| test_global_or_namespace.cpp:36:5:36:5 | a | Variable 'N1::a' is unused. |
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
| test.cpp:7:7:7:7 | y | Local variable y in test_simple is not used. |
2-
| test.cpp:14:13:14:13 | y | Local variable y in test_const is not used. |
3-
| test.cpp:17:7:17:7 | z | Local variable z in test_const is not used. |
4-
| test.cpp:23:5:23:5 | t | Local variable t in f1 is not used. |
5-
| test.cpp:23:5:23:5 | t | Local variable t in f1 is not used. |
6-
| test.cpp:44:6:44:6 | a | Local variable a in test_side_effect_init is not used. |
1+
| test.cpp:7:7:7:7 | y | Local variable 'y' in 'test_simple' is not used. |
2+
| test.cpp:14:13:14:13 | y | Local variable 'y' in 'test_const' is not used. |
3+
| test.cpp:17:7:17:7 | z | Local variable 'z' in 'test_const' is not used. |
4+
| test.cpp:23:5:23:5 | t | Local variable 't' in 'f1' is not used. |
5+
| test.cpp:23:5:23:5 | t | Local variable 't' in 'f1' is not used. |
6+
| test.cpp:44:6:44:6 | a | Local variable 'a' in 'test_side_effect_init' is not used. |
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
| test_member.cpp:4:7:4:8 | m1 | Member variable m1 is unused. |
2-
| test_member.cpp:17:9:17:11 | pad | Member variable pad is unused. |
3-
| test_member.cpp:19:9:19:11 | sm2 | Member variable sm2 is unused. |
4-
| test_member.cpp:31:7:31:8 | m1 | Member variable m1 is unused. |
1+
| test_member.cpp:4:7:4:8 | m1 | Member variable 'm1' is unused. |
2+
| test_member.cpp:17:9:17:11 | pad | Member variable 'pad' is unused. |
3+
| test_member.cpp:19:9:19:11 | sm2 | Member variable 'sm2' is unused. |
4+
| test_member.cpp:31:7:31:8 | m1 | Member variable 'm1' is unused. |

cpp/autosar/test/rules/M0-1-3/test_global_or_namespace.cpp

+19-1
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,22 @@ void test_ns() { x2 = 1; }
4141
m1(); // ignore dead code in macros
4242
} // namespace N1
4343

44-
int test_access_variable() { return N1::x5; }
44+
int test_access_variable() { return N1::x5; }
45+
46+
template <int t> struct C1 {
47+
int array[t]; // COMPLIANT
48+
};
49+
50+
constexpr int g5 = 1; // COMPLIANT - used as template parameter
51+
52+
namespace ns1 {
53+
constexpr int m1 = 1; // COMPLIANT - used a template parameter
54+
}
55+
56+
void test_fp_reported_in_384() {
57+
struct C1<g5> l1;
58+
struct C1<ns1::m1> l2;
59+
60+
l1.array[0] = 1;
61+
l2.array[0] = 1;
62+
}

cpp/autosar/test/rules/M0-1-3/test_member.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,18 @@ void test_d() {
4747
d.getT();
4848
}
4949

50+
template <int t> struct C1 {
51+
int array[t]; // COMPLIANT
52+
};
53+
54+
struct C2 {
55+
static constexpr int m1 = 1; // COMPLIANT - used as template parameter
56+
};
57+
58+
void test_fp_reported_in_384() {
59+
struct C1<C2::m1> l1;
60+
61+
l1.array[0] = 1;
62+
}
63+
5064
} // namespace test

cpp/common/src/codingstandards/cpp/deadcode/UnusedVariables.qll

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import cpp
22
import codingstandards.cpp.FunctionEquivalence
3+
import codingstandards.cpp.Scope
34

45
/**
56
* A type that contains a template parameter type (doesn't count pointers or references).
@@ -92,7 +93,9 @@ class PotentiallyUnusedMemberVariable extends MemberVariable {
9293
// Must be in a fully defined class, otherwise one of the undefined functions may use the variable
9394
getDeclaringType() instanceof FullyDefinedClass and
9495
// Lambda captures are not "real" member variables - it's an implementation detail that they are represented that way
95-
not this = any(LambdaCapture lc).getField()
96+
not this = any(LambdaCapture lc).getField() and
97+
// exclude uninstantiated template members
98+
not this.isFromUninstantiatedTemplate(_)
9699
}
97100
}
98101

@@ -119,3 +122,21 @@ class UserProvidedConstructorFieldInit extends ConstructorFieldInit {
119122
not getEnclosingFunction().isCompilerGenerated()
120123
}
121124
}
125+
126+
/**
127+
* Holds if `v` may hold a compile time value and is accessible to a template instantiation that
128+
* receives a constant value as an argument equal to the value of `v`.
129+
*/
130+
predicate maybeACompileTimeTemplateArgument(Variable v) {
131+
v.isConstexpr() and
132+
exists(ClassTemplateInstantiation cti, TranslationUnit tu |
133+
cti.getATemplateArgument().(Expr).getValue() = v.getInitializer().getExpr().getValue() and
134+
(
135+
cti.getFile() = tu and
136+
(
137+
v.getADeclarationEntry().getFile() = tu or
138+
tu.getATransitivelyIncludedFile() = v.getADeclarationEntry().getFile()
139+
)
140+
)
141+
)
142+
}

0 commit comments

Comments
 (0)