Skip to content

Commit 0083f2e

Browse files
First pass implementing RULE-0-2-1, unused variables.
Implementation relies on shared code with autosar that was previously declared in the ql files. This behavior has been moved into UnusedObjects.qll. The previous code seemed like a very disorganized set of exceptional cases, which was going to be worse with the new code. I made a minimal attempt to better organize it by organizing it into modules containing individual filter passes. Filtering out `.getAnAccess()` was always the last step. From a performance perspective, this is a bad order. We start with all variables, and for each one we join it against some set of rare exceptional cases, like functions with assembly, that only minimally reduce the set of variables we want to query. Changed to use a better order, where we begin with the set of variables that have no accesses, which should be a very small set relatively speaking, and then perform the odds-and-ends filters on top of that set. Small performance improvements have been measured across the queries.
1 parent e140430 commit 0083f2e

File tree

17 files changed

+611
-178
lines changed

17 files changed

+611
-178
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- `M0-1-3`, `RULE-2-8` - `UnusedLocalVariable.ql`, `UnusedMemberVariable.ql`, `UnusedGlobalOrNamespaceVariable.ql`, `UnusedObjectDefinition.ql`, `UnusedObjectDefinitionStrict.ql`:
2+
- The organization of unused variable analysis has been reorganized to be usable in MISRA C++ rule 0.2.1, with no expected noticeable change in results.
3+
- New filtering passes begin by filtering out variables that have an existing access (`.getAnAccess()`), which should improve performance in later filtering passes and overall query performance.

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ import cpp
1818
import codingstandards.cpp.autosar
1919
import codingstandards.cpp.deadcode.UnusedVariables
2020

21-
from PotentiallyUnusedGlobalOrNamespaceVariable v
22-
where
23-
not isExcluded(v, DeadCodePackage::unusedGlobalOrNamespaceVariableQuery()) and
24-
// No variable access
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)
21+
from ThirdPassUnused::UnusedGlobalOrNamespaceVariable v
22+
where not isExcluded(v, DeadCodePackage::unusedGlobalOrNamespaceVariableQuery())
2823
select v, "Variable '" + v.getQualifiedName() + "' is unused."

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

Lines changed: 6 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -18,58 +18,10 @@ import cpp
1818
import codingstandards.cpp.autosar
1919
import codingstandards.cpp.deadcode.UnusedVariables
2020

21-
// Collect constant values that we should use to exclude otherwise unused constexpr variables.
22-
//
23-
// For constexpr variables used as template arguments or in static_asserts, we don't see accesses
24-
// (just the appropriate literals). We therefore take a conservative approach and do not report
25-
// constexpr variables whose values are used in such contexts.
26-
//
27-
// For performance reasons, these special values should be collected in a single pass.
28-
predicate excludedConstantValue(string value) {
29-
value = any(ClassTemplateInstantiation cti).getTemplateArgument(_).(Expr).getValue()
30-
or
31-
value = any(StaticAssert sa).getCondition().getAChild*().getValue()
32-
}
33-
34-
/**
35-
* Defines the local variables that should be excluded from the unused variable analysis based
36-
* on their constant value.
37-
*
38-
* See `excludedConstantValue` for more details.
39-
*/
40-
predicate excludeVariableByValue(Variable variable) {
41-
variable.isConstexpr() and
42-
excludedConstantValue(getConstExprValue(variable))
43-
}
44-
45-
// TODO: This predicate may be possible to merge with M0-1-4's getUseCount(). These two rules
46-
// diverged to handle `excludeVariableByValue`, but may be possible to merge.
47-
int getUseCountConservatively(Variable v) {
48-
result =
49-
count(VariableAccess access | access = v.getAnAccess()) +
50-
count(UserProvidedConstructorFieldInit cfi | cfi.getTarget() = v) +
51-
// In case an array type uses a constant in the same scope as the constexpr variable,
52-
// consider it as used.
53-
countUsesInLocalArraySize(v)
54-
}
55-
56-
predicate isConservativelyUnused(Variable v) {
57-
getUseCountConservatively(v) = 0 and
58-
not excludeVariableByValue(v)
59-
}
60-
61-
from PotentiallyUnusedLocalVariable v
62-
where
63-
not isExcluded(v, DeadCodePackage::unusedLocalVariableQuery()) and
64-
// Local variable is never accessed
65-
not exists(v.getAnAccess()) and
66-
// Sometimes multiple objects representing the same entities are created in
67-
// the AST. Check if those are not accessed as well. Refer issue #658
68-
not exists(LocalScopeVariable another |
69-
another.getDefinitionLocation() = v.getDefinitionLocation() and
70-
another.hasName(v.getName()) and
71-
exists(another.getAnAccess()) and
72-
another != v
73-
) and
74-
isConservativelyUnused(v)
21+
// 10.1, 41.0
22+
// 10.9, 45.9
23+
// 11.0, 52.3
24+
// 13.1, 59.3
25+
from ThirdPassUnused::UnusedLocalVariable v
26+
where not isExcluded(v, DeadCodePackage::unusedLocalVariableQuery())
7527
select v, "Local variable '" + v.getName() + "' in '" + v.getFunction().getName() + "' is not used."

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

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,6 @@ import codingstandards.cpp.autosar
1919
import codingstandards.cpp.FunctionEquivalence
2020
import codingstandards.cpp.deadcode.UnusedVariables
2121

22-
from PotentiallyUnusedMemberVariable v
23-
where
24-
not isExcluded(v, DeadCodePackage::unusedMemberVariableQuery()) and
25-
// No variable access
26-
not exists(v.getAnAccess()) and
27-
// No explicit initialization in a constructor
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)
22+
from ThirdPassUnused::UnusedMemberVariable v
23+
where not isExcluded(v, DeadCodePackage::unusedMemberVariableQuery())
3124
select v, "Member variable '" + v.getName() + "' is unused."

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,15 @@ import codingstandards.cpp.alertreporting.DeduplicateMacroResults
1717
class UnusedObjectDefinition extends VariableDeclarationEntry {
1818
UnusedObjectDefinition() {
1919
(
20-
getVariable() instanceof BasePotentiallyUnusedLocalVariable
20+
getVariable() instanceof FirstPassUnused::UnusedLocalVariable
2121
or
22-
getVariable() instanceof BasePotentiallyUnusedGlobalOrNamespaceVariable
22+
getVariable() instanceof FirstPassUnused::UnusedGlobalOrNamespaceVariable
2323
) and
24-
not exists(VariableAccess access | access.getTarget() = getVariable()) and
2524
getVariable().getDefinition() = this
2625
}
2726

2827
/* Dead objects with these attributes are reported in the "strict" queries. */
29-
predicate hasAttrUnused() {
30-
getVariable().getAnAttribute().hasName(["unused", "used", "maybe_unused", "cleanup"])
31-
}
28+
predicate hasAttrUnused() { hasAttrUnused(getVariable()) }
3229
}
3330

3431
/* Configuration to use the `DedupMacroResults` module to reduce alert noise */

0 commit comments

Comments
 (0)