How to suppress a specific unused-but-set-variable warning?

368 Views Asked by At

I've got some old code I'm trying to compile on a new(er) compiler (armclang 6.18), and I'm currently working through resolving a lot of new warnings. One I can't seem to get past is a variable that's being set but is unused afterward.

void IMT_hw_startup(void) {
    uint32_t encoder_value_0;
//[...]
    encoder_value_0 = encoder_values[0];
}

In this case the read access to encoder_values has hardware side effects and must remain in place.

The result of this code is warning: variable 'encoder_value_0' set but not used [-Wunused-but-set-variable], and my primary question is how I can suppress the warning for this specific variable. I do want to keep this warning active globally.

In searching about this, there seems to be a lot of confusion and conflation between this warning and unused-variable, and at any rate there's an attribute that will suppress the latter but I can't find one for unused-but-set-variable.

Also a curiosity -- less important than the primary question above: There appears to be an inconsistency in what 'used' actually means. According to the above warning, the variable is not used; this seems unambiguous.

But if I add the unused attribute:

uint32_t encoder_value_0 __attribute((unused));

Then I get the warning warning: 'encoder_value_0' was marked unused but was used [-Wused-but-marked-unused] where the variable is assigned a value (final statement in the function). I can see no alternative interpretation -- this is a direct contradiction of the above warning. Either assignment is "use", or it's not.

At any rate, how do I suppress the warning for this case individually, so I can leave the warning active elsewhere?

EDIT: As suggested, changing the method of reading from the encoder_values pointer does work around the problem by eliminating the need for the variable:

if (encoder_values[0]) {}

I'm leaving this question up in case there's a more direct answer to it.

3

There are 3 best solutions below

0
Eric Postpischil On

If reading from encoder_values[0] has hardware side effects, then presumably it is declared with volatile, and the way to effect those side effects in C is simply to evaluate encoder_values[0], with no assignment necessary:

encoder_values[0];

If you do assign to encoder_value_0 for some reason and want to suppress the compiler warning about its value not being used, then simply “use” the value in a statement that tells the compiler you are deliberately discarding it:

(void) encoder_value_0;

Note that if encoder_values[0] is not declared with volatile, then writing encoder_values_0 = encoder_values[0]; will not ensure it is read. With no volatile type involved and encoder_value_0 not used for any observable behavior, the compiler is free to optimize away the assignment. (This is so even if (void) encoder_value_0; is also added, as that has no observable behavior in C semantics.)

3
0___________ On

An additional variable is not needed for the read only. The easiest way is:

encoder_values[0];

*removed (void) - as per @EricPostpischil's suggestion

Assuming that encoder_values are volatile. (If it is not the read will be optimized out anyway - so it has to be. It is also hardware register )

void IMT_hw_startup(void) {
    encoder_values[0];
}
0
dave On

You can use push and pop to save and revert the diagnostic state, so you should be able to do:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
encoder_value_0 = encoder_values[0];
#pragma GCC diagnostic pop