Skip to content

Commit 187564b

Browse files
Merge pull request github#974 from github/michaelrfairhurst/performance-unused-local-vars-m0-1-3
Improve performance of m0-1-3, unused local vars.
2 parents cbc7d53 + 0e9fc04 commit 187564b

File tree

2 files changed

+34
-15
lines changed

2 files changed

+34
-15
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `M0-1-3` - `UnusedLocalVariable.ql`:
2+
- Improved performance of the unused local variable analysis by moving constant expression value extraction to a separate pass, eliminating certain expensive joins.

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

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,46 @@ import cpp
1818
import codingstandards.cpp.autosar
1919
import codingstandards.cpp.deadcode.UnusedVariables
2020

21-
// This predicate is similar to getUseCount for M0-1-4 except that it also
22-
// considers static_asserts. This was created to cater for M0-1-3 specifically
23-
// and hence, doesn't attempt to reuse the M0-1-4 specific predicate
24-
// - getUseCount()
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.
2547
int getUseCountConservatively(Variable v) {
2648
result =
2749
count(VariableAccess access | access = v.getAnAccess()) +
2850
count(UserProvidedConstructorFieldInit cfi | cfi.getTarget() = v) +
29-
// For constexpr variables used as template arguments, we don't see accesses (just the
30-
// appropriate literals). We therefore take a conservative approach and count the number of
31-
// template instantiations that use the given constant, and consider each one to be a use
32-
// of the variable
33-
count(ClassTemplateInstantiation cti |
34-
cti.getTemplateArgument(_).(Expr).getValue() = getConstExprValue(v)
35-
) +
36-
// For static asserts too, check if there is a child which has the same value
37-
// as the constexpr variable.
38-
count(StaticAssert s | s.getCondition().getAChild*().getValue() = getConstExprValue(v)) +
3951
// In case an array type uses a constant in the same scope as the constexpr variable,
4052
// consider it as used.
4153
countUsesInLocalArraySize(v)
4254
}
4355

56+
predicate isConservativelyUnused(Variable v) {
57+
getUseCountConservatively(v) = 0 and
58+
not excludeVariableByValue(v)
59+
}
60+
4461
from PotentiallyUnusedLocalVariable v
4562
where
4663
not isExcluded(v, DeadCodePackage::unusedLocalVariableQuery()) and
@@ -54,5 +71,5 @@ where
5471
exists(another.getAnAccess()) and
5572
another != v
5673
) and
57-
getUseCountConservatively(v) = 0
74+
isConservativelyUnused(v)
5875
select v, "Local variable '" + v.getName() + "' in '" + v.getFunction().getName() + "' is not used."

0 commit comments

Comments
 (0)