Product: SonarQube Community Build 26.5.0.122743
sonar-java version: sonar-java 8.29 (build 43460)
sonar-java SE version: sonar-java-symbolic-execution 8.16.4 (build 1912)
Java source level: 21 (javac 21, source/target 21)
Rule
java:S1481 — Unused local variables should be removed
Description
S1481 incorrectly reports a local variable as unused when its only update site is a compound assignment (+=) embedded in a while condition, even though the assignment’s result is what drives the loop. When the same code is rewritten with an explicit x = x + y assignment in the same position, S1481 correctly recognizes the variable as used. This is a false positive on the compound-assignment form: per JLS §15.26.2, x += y reads x, computes x + y, and writes the result back to x, so the variable is read on every iteration. The two forms are observationally indistinguishable but produce different verdicts.
Reproducer
public class S1481Reproducer {
// BEFORE — S1481 incorrectly reports `read` as unused.
public void compoundForm() {
int read = 0;
while ((read += step()) < 100) { // S1481 raised on `read`
doWork();
}
}
// AFTER — semantically identical, S1481 does NOT fire.
public void explicitForm() {
int read = 0;
while ((read = read + step()) < 100) {
doWork();
}
}
private int step() { return 7; }
private void doWork() { /* no-op */ }
}
Expected behavior
S1481 should treat read += step() exactly like read = read + step(). Both forms read the current value of read on the right-hand side (implicitly for +=), compute a new value, and assign it back; the new value then flows into the surrounding while condition, so read is unambiguously used. S1481 should NOT raise on either method.
Actual behavior
compoundForm():java:S1481(MINOR) raised on the declarationint read = 0;with message
“Remove this unused ‘read’ local variable.”explicitForm(): no S1481 violation, although the only structural difference is=++instead of+=.