void f (void) { int i; i = 0; i++; } seems like something a natural generalization of -Wunused-but-set-variable should warn for; the value of i is only used as part of an increment of i, so the definition and all uses of this variable could be safely removed. For a real example of this, see the variable lang_n_infiles in gcc.c:process_command (I'm testing a patch that removes that variable along with other changes).
Confirmed.
*** Bug 69723 has been marked as a duplicate of this bug. ***
*** Bug 70092 has been marked as a duplicate of this bug. ***
*** Bug 78964 has been marked as a duplicate of this bug. ***
As soon as consider more complicated testcases than just pre/post increment, this is going to be very hard to define and especially implement. The way the warning works right now is that all rvalue uses of a variable are marked as "read" and the warning then warns about variables that don't have the "read" bit set, but have the "used" bit set (i.e. they aren't fully unused). This is especially because the FEs used to fold expressions aggressively very early (and still do, especially the C FE), so not all expressions (even use in sizeof etc. counts) survive long enough where we actually would know what the lhs is corresponding to rhs. Also, we do not warn if there are any side-effects in between the rvalue use of the var and the store to it. So, if we do want to warn about m = m + 1; we still shouldn't warn for m = foo (m) + 1; or m = (n = m) + 1; etc. Handling the pre/post increment by 1 might be easiest, just remember whether the var is not "read" before processing it and reset the "read" bit if so afterwards, but as soon as you run into more complex expressions that is going to be harder and harder.
I haven't thought through the implementation challenges but defining the extended -Wunused-but-set-variabl rule that's being suggested here seems straightforward: every write to an object must be followed by another access to it (either read or write). If not, it's diagnosed. This seems analogous to the -Wuninitialized checker/rule that might be stated as: the first read of an object must be preceded by a write to it.
(In reply to Martin Sebor from comment #6) > I haven't thought through the implementation challenges but defining the > extended -Wunused-but-set-variabl rule that's being suggested here seems > straightforward: every write to an object must be followed by another access > to it (either read or write). If not, it's diagnosed. That is not straightforward at all. The FE doesn't have IL on which it can analyze write accesses being followed by something (no cfg, no SSA form), and in the middle end it is way too late for such a warning (because as soon as you optimize away something, you could optimize away those reads and warning just because the optimizers managed to optimize away some use are not really helpful).
I would expect handling -Wunused-but-set-variable during Gimplification to make detecting these sorts of things possible at least in the basic cases.
(In reply to Martin Sebor from comment #8) > I would expect handling -Wunused-but-set-variable during Gimplification to > make detecting these sorts of things possible at least in the basic cases. That is way too late.
See pr95217 for other cases to handle (-Wunused-but-set-parameter). For the test case there, Clang's static analyzer diagnoses two out of the four cases: $ cat pr95217.c && clang -S -Wall -Wextra --analyze pr95217.c void f0 (int *p) { p = 0; // -Wunused-but-set-parameter (expected) } void f1 (int *p) { p += 1; // missing warning } void f2 (int *p) { p = p + 1; // missing warning } void f3 (int *p) { ++p; // missing warning } pr95217.c:8:3: warning: Value stored to 'p' is never read p += 1; // missing warning ^ ~ pr95217.c:13:3: warning: Value stored to 'p' is never read p = p + 1; // missing warning ^ ~~~~~ 2 warnings generated.
*** Bug 100184 has been marked as a duplicate of this bug. ***
*** Bug 102909 has been marked as a duplicate of this bug. ***
I ran into this issue today on Emacs master, with both += and |=. Clang correctly diagnosed unused local variables, but GCC did not. It would be nice if GCC could do at least as well as Clang does. Here are references to patches I installed into Emacs to fix these issues that Clang found but GCC did not: https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=d9bffa1f3b121085fd8f954eb9446a4a5241c062 https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=68bc1446855c86b96d5bc22f819e63358ab250ac
It is worth to notice that this bug propagates to C++ whenever an object uses an int that increments but is never used, like the following example: class Test{ public: Test() { i = 0; i++; } private: int i; }; int main(int, char**) { Test unused; return 0; }
*** Bug 108156 has been marked as a duplicate of this bug. ***
"set but not used" (just for future searches)
(In reply to Martin Sebor from comment #10) > $ cat pr95217.c && clang -S -Wall -Wextra --analyze pr95217.c [...] > pr95217.c:8:3: warning: Value stored to 'p' is never read > p += 1; // missing warning > ^ ~ > pr95217.c:13:3: warning: Value stored to 'p' is never read > p = p + 1; // missing warning > ^ ~~~~~ > 2 warnings generated. Clang (15 and above) with -Wunused-but-set-variable now detects the issue on the "p++" and "p += 1" forms (ditto with other combined assignment operators), but not on "p = p + 1". Such forms (p++, etc.) are common, so that detecting an unused variable is very useful. Like Paul did for Emacs (comment 13), I've just fixed two issues in GNU MPFR (one cosmetic about a useless loop variable and one important in the testsuite), found with Clang 16. The references: https://gitlab.inria.fr/mpfr/mpfr/-/commit/4c110cf4773b3c07de2a33acbee591cedb083c80 https://gitlab.inria.fr/mpfr/mpfr/-/commit/b34d867fa41934d12d0d4dbaaa0242d6d3eb32c7 For the second MPFR issue, there was an "err++" for each error found by the function in the testsuite, but err was not tested at the end, so that potential errors were never reported.