Skip to content

Commit 8bb9e8a

Browse files
authored
Merge pull request #4592 from geoffw0/varnotused
C++: Work around two false positive issues with the UnusedLocals.ql query
2 parents f7361ca + 498177c commit 8bb9e8a

File tree

4 files changed

+106
-8
lines changed

4 files changed

+106
-8
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Two issues causing the 'Unused local variable' query (`cpp/unused-local-variable`) to produce false positive results have been fixed.

cpp/ql/src/Best Practices/Unused Entities/UnusedLocals.ql

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,12 @@ where
5757
not declarationHasSideEffects(v) and
5858
not exists(AsmStmt s | f = s.getEnclosingFunction()) and
5959
not v.getAnAttribute().getName() = "unused" and
60-
not any(ErrorExpr e).getEnclosingFunction() = f // unextracted expr likely used `v`
60+
not any(ErrorExpr e).getEnclosingFunction() = f and // unextracted expr may use `v`
61+
not exists(
62+
Literal l // this case can be removed when the `myFunction2( [obj](){} );` test case doesn't depend on this exclusion
63+
|
64+
l.getEnclosingFunction() = f and
65+
not exists(l.getValue())
66+
) and
67+
not any(ConditionDeclExpr cde).getEnclosingFunction() = f // this case can be removed when the `if (a = b; a)` test case doesn't depend on this exclusion
6168
select v, "Variable " + v.getName() + " is not used"

cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedLocals/UnusedLocals.expected

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
| code2.cpp:4:6:4:7 | v1 | Variable v1 is not used |
2-
| code2.cpp:6:6:6:7 | v3 | Variable v3 is not used |
3-
| code2.cpp:10:16:10:17 | v7 | Variable v7 is not used |
4-
| code2.cpp:25:16:25:17 | v1 | Variable v1 is not used |
5-
| code2.cpp:26:16:26:17 | v2 | Variable v2 is not used |
6-
| code2.cpp:41:11:41:16 | myVar1 | Variable myVar1 is not used |
7-
| code2.cpp:63:7:63:8 | v3 | Variable v3 is not used |
1+
| code2.cpp:5:6:5:7 | v1 | Variable v1 is not used |
2+
| code2.cpp:7:6:7:7 | v3 | Variable v3 is not used |
3+
| code2.cpp:11:16:11:17 | v7 | Variable v7 is not used |
4+
| code2.cpp:26:16:26:17 | v1 | Variable v1 is not used |
5+
| code2.cpp:27:16:27:17 | v2 | Variable v2 is not used |
6+
| code2.cpp:42:11:42:16 | myVar1 | Variable myVar1 is not used |
7+
| code2.cpp:64:7:64:8 | v3 | Variable v3 is not used |
8+
| code2.cpp:108:11:108:12 | v2 | Variable v2 is not used |
9+
| code2.cpp:128:9:128:9 | b | Variable b is not used |
810
| code.c:10:18:10:18 | y | Variable y is not used |
911
| code.c:11:18:11:18 | z | Variable z is not used |
1012
| code.c:18:7:18:7 | x | Variable x is not used |

cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedLocals/code2.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// semmle-extractor-options: -std=c++17
12

23
int test_const_init()
34
{
@@ -76,3 +77,89 @@ void test_expect()
7677
}
7778
}
7879
}
80+
81+
// ---
82+
83+
template<class T>
84+
class MyContainer
85+
{
86+
public:
87+
struct Iterator {
88+
const T& operator*() const;
89+
bool operator!=(const Iterator &rhs) const;
90+
Iterator operator++();
91+
};
92+
93+
Iterator begin();
94+
Iterator end();
95+
};
96+
97+
void output(int value);
98+
99+
void test_range_based_for()
100+
{
101+
MyContainer<int> myContainer;
102+
103+
for (int v1 : myContainer) // GOOD: v1 is used
104+
{
105+
output(v1);
106+
}
107+
108+
for (int v2 : myContainer) // BAD: v2 is not used
109+
{
110+
}
111+
}
112+
113+
// ---
114+
115+
int test_lambdas1()
116+
{
117+
int a, b, c, d, e; // (b is not used, but is explicitly captured)
118+
auto myLambda = [a, b, &c](int x, int y) -> int // (y is not used, but is a parameter)
119+
{
120+
return a + c + x;
121+
};
122+
123+
return myLambda(d, e);
124+
}
125+
126+
int test_lambdas2()
127+
{
128+
int a, b; // BAD: b is not used
129+
auto myLambda = [=]() -> int // BAD: myLambda is not used [NOT DETECTED] (due to containing a Constructor)
130+
{
131+
return a;
132+
};
133+
134+
return 0;
135+
}
136+
137+
// ---
138+
139+
void test_if_initializer()
140+
{
141+
bool a = false, b = true; // GOOD: a, b are both used
142+
143+
if (a = b; a)
144+
{
145+
// ...
146+
}
147+
}
148+
149+
// ---
150+
151+
class MyObj
152+
{
153+
public:
154+
MyObj();
155+
};
156+
157+
template<class T>
158+
void myFunction2(T t);
159+
160+
void test_captured_contructor()
161+
{
162+
const auto &obj = MyObj(); // GOOD: obj is used
163+
164+
myFunction2( [obj](){} );
165+
}

0 commit comments

Comments
 (0)