Rust: Fix unused value FPs due to unexpanded macro calls as well.

This commit is contained in:
Geoffrey White
2025-03-07 14:31:53 +00:00
parent e0839a369c
commit cc902a6ad1
5 changed files with 21 additions and 19 deletions

View File

@@ -21,5 +21,6 @@ where
// avoid overlap with the unused variable query
not isUnused(v) and
not v instanceof DiscardVariable and
not write.isInMacroExpansion()
not write.isInMacroExpansion() and
not isAllowableUnused(v)
select write, "Variable $@ is assigned a value that is never used.", v, v.getText()

View File

@@ -11,24 +11,9 @@
import rust
import UnusedVariable
/**
* A callable for which we have incomplete information, for example because an unexpanded
* macro call is present. These callables are prone to false positive results from unused
* entities queries, unless they are excluded from results.
*/
class IncompleteCallable extends Callable {
IncompleteCallable() {
exists(MacroExpr me |
me.getEnclosingCallable() = this and
not me.getMacroCall().hasExpanded()
)
}
}
from Variable v
where
isUnused(v) and
not isAllowableUnused(v) and
not v instanceof DiscardVariable and
not v.getEnclosingCfgScope() instanceof IncompleteCallable
not v instanceof DiscardVariable
select v, "Variable '" + v + "' is not used."

View File

@@ -16,6 +16,20 @@ predicate isUnused(Variable v) {
not exists(v.getInitializer())
}
/**
* A callable for which we have incomplete information, for example because an unexpanded
* macro call is present. These callables are prone to false positive results from unused
* entities queries, unless they are excluded from results.
*/
class IncompleteCallable extends Callable {
IncompleteCallable() {
exists(MacroExpr me |
me.getEnclosingCallable() = this and
not me.getMacroCall().hasExpanded()
)
}
}
/**
* Holds if variable `v` is in a context where we may not find a use for it,
* but that's expected and should not be considered a problem.
@@ -24,6 +38,9 @@ predicate isAllowableUnused(Variable v) {
// in a macro expansion
v.getPat().isInMacroExpansion()
or
// declared in an incomplete callable
v.getEnclosingCfgScope() instanceof IncompleteCallable
or
// a 'self' variable
v.getText() = "self"
}

View File

@@ -14,7 +14,6 @@
| main.rs:284:13:284:17 | total | Variable $@ is assigned a value that is never used. | main.rs:252:13:252:17 | total | total |
| main.rs:377:9:377:9 | x | Variable $@ is assigned a value that is never used. | main.rs:377:9:377:9 | x | x |
| main.rs:385:17:385:17 | x | Variable $@ is assigned a value that is never used. | main.rs:385:17:385:17 | x | x |
| main.rs:510:9:510:9 | d | Variable $@ is assigned a value that is never used. | main.rs:510:9:510:9 | d | d |
| main.rs:550:9:550:20 | var_in_macro | Variable $@ is assigned a value that is never used. | main.rs:550:9:550:20 | var_in_macro | var_in_macro |
| main.rs:559:9:559:9 | c | Variable $@ is assigned a value that is never used. | main.rs:559:9:559:9 | c | c |
| more.rs:44:9:44:14 | a_ptr4 | Variable $@ is assigned a value that is never used. | more.rs:44:9:44:14 | a_ptr4 | a_ptr4 |

View File

@@ -507,7 +507,7 @@ fn macros2() {
}
fn macros3() {
let d: u16 = 4; // $ SPURIOUS: Alert[rust/unused-value]
let d: u16 = 4;
undefined_macro_call!(d);
}