Skip to content

M0-1-3: Consider local variable usages in array size and template function arguments #660

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions change_notes/2024-08-06-fix-fp-658-M0-1-3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- `M0-1-3` - `UnusedLocalVariable.ql`:
- Fixes #658. Considers usage of const/constexpr variables in array size and function parameters that are used in arguments of template functions.
21 changes: 18 additions & 3 deletions cpp/autosar/src/rules/M0-1-3/UnusedLocalVariable.ql
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import cpp
import codingstandards.cpp.autosar
import codingstandards.cpp.deadcode.UnusedVariables

/** Gets the constant value of a constexpr variable. */
/** Gets the constant value of a constexpr/const variable. */
private string getConstExprValue(Variable v) {
result = v.getInitializer().getExpr().getValue() and
v.isConstexpr()
(v.isConst() or v.isConstexpr())
}

// This predicate is similar to getUseCount for M0-1-4 except that it also
Expand All @@ -41,13 +41,28 @@ int getUseCountConservatively(Variable v) {
) +
// For static asserts too, check if there is a child which has the same value
// as the constexpr variable.
count(StaticAssert s | s.getCondition().getAChild*().getValue() = getConstExprValue(v))
count(StaticAssert s | s.getCondition().getAChild*().getValue() = getConstExprValue(v)) +
// In case an array type uses a constant in the same scope as the constexpr variable,
// consider it as used.
count(ArrayType at, LocalVariable arrayVariable |
arrayVariable.getType().resolveTypedefs() = at and
v.(PotentiallyUnusedLocalVariable).getFunction() = arrayVariable.getFunction() and
at.getArraySize().toString() = getConstExprValue(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
getUseCountConservatively(v) = 0
select v, "Local variable '" + v.getName() + "' in '" + v.getFunction().getName() + "' is not used."
11 changes: 5 additions & 6 deletions cpp/autosar/test/rules/M0-1-3/UnusedLocalVariable.expected
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
| test.cpp:7:7:7:7 | y | Local variable 'y' in 'test_simple' is not used. |
| test.cpp:14:13:14:13 | y | Local variable 'y' in 'test_const' is not used. |
| test.cpp:17:7:17:7 | z | Local variable 'z' in 'test_const' is not used. |
| test.cpp:23:5:23:5 | t | Local variable 't' in 'f1' is not used. |
| test.cpp:23:5:23:5 | t | Local variable 't' in 'f1' is not used. |
| test.cpp:44:6:44:6 | a | Local variable 'a' in 'test_side_effect_init' is not used. |
| test.cpp:91:5:91:5 | t | Local variable 't' in 'template_function' is not used. |
| test.cpp:15:7:15:7 | z | Local variable 'z' in 'test_const' is not used. |
| test.cpp:21:5:21:5 | t | Local variable 't' in 'f1' is not used. |
| test.cpp:21:5:21:5 | t | Local variable 't' in 'f1' is not used. |
| test.cpp:42:6:42:6 | a | Local variable 'a' in 'test_side_effect_init' is not used. |
| test.cpp:89:5:89:5 | t | Local variable 't' in 'template_function' is not used. |
22 changes: 18 additions & 4 deletions cpp/autosar/test/rules/M0-1-3/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ int test_simple() {

int test_const() {
const int x = 1; // COMPLIANT - used below
const int y = 2; // COMPLIANT[FALSE_POSITIVE] - used in array initialization,
// but the database does not contain sufficient information
// for this case
const int y = 2; // COMPLIANT - used in array initialization,
int z[y]; // NON_COMPLIANT - never used
return x;
}
Expand Down Expand Up @@ -98,4 +96,20 @@ class ClassT {
void test() {}
};

void test_template_function() { template_function<ClassT>(); }
void test_template_function() { template_function<ClassT>(); }

int foo() {
constexpr int arrayDim = 10; // COMPLIANT - used in array size below
static int array[arrayDim]{};
return array[4];
}

template <typename T> static T another_templ_function() { return T(); }

template <typename T, typename First, typename... Rest>
static T another_templ_function(const First &first, const Rest &...rest) {
return first +
another_templ_function<T>(rest...); // COMPLIANT - 'rest' is used here
}

static int templ_fnc2() { return another_templ_function<int>(1, 2, 3, 4, 5); }
Loading