Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions change_notes/2026-02-12-unused-variable-reorganization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- `M0-1-3`, `RULE-2-8` - `UnusedLocalVariable.ql`, `UnusedMemberVariable.ql`, `UnusedGlobalOrNamespaceVariable.ql`, `UnusedObjectDefinition.ql`, `UnusedObjectDefinitionStrict.ql`:
- 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.
- 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.
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ import cpp
import codingstandards.cpp.autosar
import codingstandards.cpp.deadcode.UnusedVariables

from PotentiallyUnusedGlobalOrNamespaceVariable v
where
not isExcluded(v, DeadCodePackage::unusedGlobalOrNamespaceVariableQuery()) and
// No variable access
not exists(v.getAnAccess()) and
// Exclude members whose value is compile time and is potentially used to inintialize a template
not maybeACompileTimeTemplateArgument(v)
from ThirdPassUnused::UnusedGlobalOrNamespaceVariable v
where not isExcluded(v, DeadCodePackage::unusedGlobalOrNamespaceVariableQuery())
select v, "Variable '" + v.getQualifiedName() + "' is unused."
60 changes: 6 additions & 54 deletions cpp/autosar/src/rules/M0-1-3/UnusedLocalVariable.ql
Original file line number Diff line number Diff line change
Expand Up @@ -18,58 +18,10 @@ import cpp
import codingstandards.cpp.autosar
import codingstandards.cpp.deadcode.UnusedVariables

// Collect constant values that we should use to exclude otherwise unused constexpr variables.
//
// For constexpr variables used as template arguments or in static_asserts, we don't see accesses
// (just the appropriate literals). We therefore take a conservative approach and do not report
// constexpr variables whose values are used in such contexts.
//
// For performance reasons, these special values should be collected in a single pass.
predicate excludedConstantValue(string value) {
value = any(ClassTemplateInstantiation cti).getTemplateArgument(_).(Expr).getValue()
or
value = any(StaticAssert sa).getCondition().getAChild*().getValue()
}

/**
* Defines the local variables that should be excluded from the unused variable analysis based
* on their constant value.
*
* See `excludedConstantValue` for more details.
*/
predicate excludeVariableByValue(Variable variable) {
variable.isConstexpr() and
excludedConstantValue(getConstExprValue(variable))
}

// TODO: This predicate may be possible to merge with M0-1-4's getUseCount(). These two rules
// diverged to handle `excludeVariableByValue`, but may be possible to merge.
int getUseCountConservatively(Variable v) {
result =
count(VariableAccess access | access = v.getAnAccess()) +
count(UserProvidedConstructorFieldInit cfi | cfi.getTarget() = v) +
// In case an array type uses a constant in the same scope as the constexpr variable,
// consider it as used.
countUsesInLocalArraySize(v)
}

predicate isConservativelyUnused(Variable v) {
getUseCountConservatively(v) = 0 and
not excludeVariableByValue(v)
}

from PotentiallyUnusedLocalVariable v
where
not isExcluded(v, DeadCodePackage::unusedLocalVariableQuery()) and
// Local variable is never accessed
not exists(v.getAnAccess()) and
// Sometimes multiple objects representing the same entities are created in
// the AST. Check if those are not accessed as well. Refer issue #658
not exists(LocalScopeVariable another |
another.getDefinitionLocation() = v.getDefinitionLocation() and
another.hasName(v.getName()) and
exists(another.getAnAccess()) and
another != v
) and
isConservativelyUnused(v)
// 10.1, 41.0
// 10.9, 45.9
// 11.0, 52.3
// 13.1, 59.3
from ThirdPassUnused::UnusedLocalVariable v
where not isExcluded(v, DeadCodePackage::unusedLocalVariableQuery())
select v, "Local variable '" + v.getName() + "' in '" + v.getFunction().getName() + "' is not used."
11 changes: 2 additions & 9 deletions cpp/autosar/src/rules/M0-1-3/UnusedMemberVariable.ql
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,6 @@ import codingstandards.cpp.autosar
import codingstandards.cpp.FunctionEquivalence
import codingstandards.cpp.deadcode.UnusedVariables

from PotentiallyUnusedMemberVariable v
where
not isExcluded(v, DeadCodePackage::unusedMemberVariableQuery()) and
// No variable access
not exists(v.getAnAccess()) and
// No explicit initialization in a constructor
not exists(UserProvidedConstructorFieldInit cfi | cfi.getTarget() = v) and
// Exclude members whose value is compile time and is potentially used to inintialize a template
not maybeACompileTimeTemplateArgument(v)
from ThirdPassUnused::UnusedMemberVariable v
where not isExcluded(v, DeadCodePackage::unusedMemberVariableQuery())
select v, "Member variable '" + v.getName() + "' is unused."
9 changes: 3 additions & 6 deletions cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,15 @@ import codingstandards.cpp.alertreporting.DeduplicateMacroResults
class UnusedObjectDefinition extends VariableDeclarationEntry {
UnusedObjectDefinition() {
(
getVariable() instanceof BasePotentiallyUnusedLocalVariable
getVariable() instanceof FirstPassUnused::UnusedLocalVariable
or
getVariable() instanceof BasePotentiallyUnusedGlobalOrNamespaceVariable
getVariable() instanceof FirstPassUnused::UnusedGlobalOrNamespaceVariable
) and
not exists(VariableAccess access | access.getTarget() = getVariable()) and
getVariable().getDefinition() = this
}

/* Dead objects with these attributes are reported in the "strict" queries. */
predicate hasAttrUnused() {
getVariable().getAnAttribute().hasName(["unused", "used", "maybe_unused", "cleanup"])
}
predicate hasAttrUnused() { hasAttrUnused(getVariable()) }
}

/* Configuration to use the `DedupMacroResults` module to reduce alert noise */
Expand Down
Loading
Loading