Suppressing "Parameter not used" Warning

D

Dave Hansen

...

Nice, though some clever compiler could warn here whether or not you're sure
it's what you intend to do, whether or not this code has any effect.

Interesting idea, I'd never thought of that. Though the lint I use
would surely complain about a "questionable use" of the semicolon
(even if it was removed from the macro itself) unless you changed it
to something like

#define UNUSED(x) if(x){}

Regards,

-=Dave
 
D

David Brown

Michael said:
David said:
if (test()) {
doThis();
doThat();
} else {
doSomethingElse();
doThat();
}

gcc will combine the two "doThat()" calls (which is good), and then
warn that one of the "will never be executed", which is bad.

If you know any good ideas to get working "will never be executed"
warnings, even if it is "wait for gcc 4.1.x", I'd love to hear them.


Hmmm. I tried this with a couple of GCC versions at default
and -O[23] optimization levels (cross and native) and saw no
such warning. What options/versions are you using?

As is typical when you write something off the top of your head, my test
case didn't work. Additionally, you need the "-Wunreachable-code"
warning flag on to get the warning. A bit more testing showed that the
following code gives an unwanted warning with msp430-gcc (3.2.3), but
not for avr-gcc (3.4.1). Both give a correct warning on test2(). So it
looks like I've answered my own question - use gcc 3.4 or newer. (gcc
4.x for msp430 should not be too far off, I hope.)


unsigned char a, b, c, d;

void test(void) {
if (a == 1) {
b = 100; // Should be no warning here
} else if (a == 2) {
b = 200;
} else {
b = 100;
}
}

void test2(void) {
if (c) {
d = 10;
} else if (!c) {
d = 20;
} else {
d = 30; // Should give warning here
}
}
 
G

Grant Edwards

Metrowerks Codewarrior has the

#pragma unused (varname)

construct to solve this problem. I'm surprised that other compilers
don't have the same facility.

They do (or something similar).
 
M

Mark Borgerson

The trouble with such pragmas is that they are completely non-portable.
As Grant Edwards said, gcc has an equivalent (using an attribute,
which is gcc prefers over pragmas). Often non-portability is not a
problem, since there are so many other non-portable aspects to typical
embedded systems (and in the case of gcc, it is at least portable to a
few dozen other gcc ports).

I agree that such pragmas are generally non-portable. The
#define UNUSED(x) if(x){}

solution seems to be the best seen so far. I tested it out with
CodeWarrior PalmOS (which I use for some M68K embedded work) and
it issued no warnings and generated no code. Can't ask for much
more than that!

In any case, the fact that you get a warning from the compiler is
a good thing. I have a lot more problems with porting structures
where I have to worry about packing and endian problems---and where
the compiler hasn't a clue what the code on the other end of the
communications line is doing!

Mark Borgerson
 
E

Everett M. Greene

pete said:
Non executable code tends to generate warnings.


In distributions file for a sort timing program
my distribution function arguments are of this form:
(e_type *array, size_t n, long unsigned *seed)

but only some of them use the seed for a PRNG.

Others are like this:

void sorted(e_type *a, size_t n, long unsigned *seed)
{
a += n;
while (n-- != 0) {
(*--a).data = n;
}
seed;
}

So, I just make an expression statement out of seed
and that seems to stop the warnings.

But some compilers will issue a warning about the
"expression" result not being used...
 
A

Alexei A. Frounze

Everett M. Greene said:
But some compilers will issue a warning about the
"expression" result not being used...

OK, what if the seed is used in an expression containing a comma, to the
left side of the comma?

Or what if it's used in an expression as
(seed*0)
or
(seed&0)
or
(seed&&0)?
:)
Should the compiler grumble in these 3 latter cases?

Alex
 
T

Tim Rentsch

Please note crosspost.

Noted, thank you. Responders please note that I am not
a regular reader of comp.arch.embedded.

Often when writing code requiring function pointers, it is necessary
to write functions that ignore their formal parameters. For example,
a state machine function might take a status input, but a certain
error-handling state might ignore it:

typedef void (*State_Fn)(uint8_t);

void error_state(uint8_t status)
{
NOT_USED(status);

/* code handling error but ignoring status */
}

In another group, a poster asked about defining a macro NOT_USED as
shown above to quiet the compiler warning. His suggested
implementation was

#define NOT_USED(p) ((void)(p))

In this particular case, he noted the compiler he was using would
generate the warning even in the presence of this macro. I suggested
he use

#define NOT_USED(p) ((p)=(p))

He was pleased that it worked, but was concerned that the former
implementation was more widely supported, and that the latter might
generate executable code. I for one had never seen the former before,
though I've often seen the latter (usually not hidden behind a macro),
and I've never seen it actually generate code. At least, not in the
last ten years or so.

So I'm curious. Which form (if either) is more common? Are there any
implementations that will generate executable code for the latter?

Just a suggestion:

#define NOT_USED(v) ((void)(&(v)?1:0))
 
D

Dave Hansen

OK, what if the seed is used in an expression containing a comma, to the
left side of the comma?

Depends. What's on the right side on the comma? Is the comma
expression cast to void?
Or what if it's used in an expression as
(seed*0)
or
(seed&0)
or
(seed&&0)?
:)
Should the compiler grumble in these 3 latter cases?

Many compilers won't, but some will, and lint certainly will, unless
the expression is cast to void.

Regards,

-=Dave
 
A

Alexei A. Frounze

Dave Hansen said:
Depends. What's on the right side on the comma? Is the comma
expression cast to void?

I don't know. It was just an idea...
Many compilers won't, but some will, and lint certainly will, unless
the expression is cast to void.

No, my point was that to make it a part of the expression whose value *is*
used but happens to be unaffected by seed being multiplied by 0 or anded
with 0.

Alex
 
D

Dave Hansen

On Tue, 4 Oct 2005 23:23:39 +0400, "Alexei A. Frounze"

[...]
No, my point was that to make it a part of the expression whose value *is*
used but happens to be unaffected by seed being multiplied by 0 or anded
with 0.

Oh, OK, I understand now. I expect there's a good chance it will
work. But it's kind of hard to hide behind a macro.

Regards,

-=Dave
 
T

Thad Smith

Alexei said:
...



Nice, though some clever compiler could warn here whether or not you're sure
it's what you intend to do, whether or not this code has any effect.

Of course. The compiler in question (an old Keil compiler) gave a
warning for the void cast. I experimented and found that if(x);;
(another semicolon added after the macro invocation) generated no code
and no warning for that compiler. With no standard way to do this, we
are left to search about for implementation-dependent hacks.

Thad
 
B

Ben Pfaff

[suppressed "parameter not used" warnings]
With no standard way to do this, we are left to search about
for implementation-dependent hacks.

Personally, I use an implementation-dependent feature that works
for the compilers I really care about. Why worry about trying to
suppress warnings on every compiler? It's not possible and you
could waste a lot of time trying.
 
G

Grant Edwards

[suppressed "parameter not used" warnings]
With no standard way to do this, we are left to search about
for implementation-dependent hacks.

Personally, I use an implementation-dependent feature that
works for the compilers I really care about. Why worry about
trying to suppress warnings on every compiler? It's not
possible and you could waste a lot of time trying.

Here in comp.arch.embedded, anybody with too strong an aversion
to implementation-dependent "hacks" is in for a lifetime of
frustration. There are just too many times when there simply
is no other way to accomplish that which must be accomplished.

Sure, standard and portable is always a good goal, but when
theres a 90+ percent chance the program is never going to be
compiled by a different compiler or run on a different
platform, there's a limit to how much utility should be
sacrificed and much effort should be expended to avoid usign
somethign like gcc's __attribute__(()) extension.
 
T

Thad Smith

Ben said:
[suppressed "parameter not used" warnings]
With no standard way to do this, we are left to search about
for implementation-dependent hacks.

Personally, I use an implementation-dependent feature that works
for the compilers I really care about.

Same here.
Why worry about trying to suppress warnings on every compiler?

I don't know. I'm certainly not advocating such worry.
It's not possible and you could waste a lot of time trying.

True. I typically only work with a few compilers and spend a little
time to customize such things as eliminating unneeded warnings, which
allows me to more easily find real problems. Turning off warnings,
ignoring them, or sprinkling non-standard code throughout is a last
resort for me. You may have other techniques that work better for
you.

Thad
 
A

Albert van der Horst

Ben said:
[suppressed "parameter not used" warnings]
With no standard way to do this, we are left to search about
for implementation-dependent hacks.

Personally, I use an implementation-dependent feature that works
for the compilers I really care about.

Same here.
Why worry about trying to suppress warnings on every compiler?

I don't know. I'm certainly not advocating such worry.
It's not possible and you could waste a lot of time trying.

True. I typically only work with a few compilers and spend a little
time to customize such things as eliminating unneeded warnings, which
allows me to more easily find real problems. Turning off warnings,
ignoring them, or sprinkling non-standard code throughout is a last
resort for me. You may have other techniques that work better for
you.

Indeed there is a much better technique.
Make clean code. Catch the warnings in a file.
Carefully inspect the warnings and head them.
Catch the warnings on the resulting cleaner code.
Now in the regression test, expect the warnings to remain
the same, i.e. make a diff with the file with the warnings
of the previous test.
Only act on warnings changes, indicative of new warnings.
Or on warnings that went away since you cleaned up your code.

Never ever becludge your code to suppress warnings.
They are there to ... warn you, which is a Good Thing.
 
S

SM Ryan

# Indeed there is a much better technique.
# Make clean code. Catch the warnings in a file.

Recompile megabytes of source code because you change one
function declaration in a header file.
 
T

Thad Smith

Albert said:
Indeed there is a much better technique.
Make clean code. Catch the warnings in a file.
Carefully inspect the warnings and head them.
Catch the warnings on the resulting cleaner code.
Now in the regression test, expect the warnings to remain
the same, i.e. make a diff with the file with the warnings
of the previous test.
Only act on warnings changes, indicative of new warnings.

That's an interesting idea! I suppose I should strip the line numbers
on the warnings so that code insertion/deletion doesn't trigger an
avalanche in the diff. It's time for a little scripting. I'll have
to give that a try. I could even fail a make if the warning file
changed.
Or on warnings that went away since you cleaned up your code.

Hmmm, the ominous disappearing warning!
Never ever becludge your code to suppress warnings.

The goal, of course, is to easily detect new warnings so that they can
be examined. Your approach is an interesting one.
They are there to ... warn you, which is a Good Thing.

Well, yes. That's why I try to hint to the compiler that its OK that
an if statement has a constant expression (because the macro it is in
takes various parameters).

Let's see, if I have conditional sections in my code, the warnings may
come and go as I change switches -- oh, dear! I suppose I should have
to have a separate expected warnings file for each configuration.

Thad
 
S

S.Tobias

In comp.lang.c Thad Smith said:
Albert van der Horst wrote: [snip]
Make clean code. Catch the warnings in a file.
Carefully inspect the warnings and head them.
Catch the warnings on the resulting cleaner code.
Now in the regression test, expect the warnings to remain
the same, i.e. make a diff with the file with the warnings
of the previous test.
Only act on warnings changes, indicative of new warnings.

That's an interesting idea! I suppose I should strip the line numbers
on the warnings so that code insertion/deletion doesn't trigger an
avalanche in the diff. It's time for a little scripting. I'll have
to give that a try. I could even fail a make if the warning file
changed.

This idea has been wandering around me for some time, too.
It could work like this: programmer puts #pramas in the code,
which contain verbatim quotes (or regexes, or identifires) of warnings
that are to be suppressed for the next line. The utility program (or
a script) calculates line numbers and produces a list of warnings
(with the line numbers) to cut out from the compiler output.
Like this:
#pragma nowarn t.c:%n: warning: comparison between signed and unsigned
if (u>s)
 
E

Eric Sosman

S.Tobias wrote On 10/13/05 17:19,:
In comp.lang.c Thad Smith said:
Albert van der Horst wrote:
[snip]
Make clean code. Catch the warnings in a file.
Carefully inspect the warnings and head them.
Catch the warnings on the resulting cleaner code.
Now in the regression test, expect the warnings to remain
the same, i.e. make a diff with the file with the warnings
of the previous test.
Only act on warnings changes, indicative of new warnings.

That's an interesting idea! I suppose I should strip the line numbers
on the warnings so that code insertion/deletion doesn't trigger an
avalanche in the diff. It's time for a little scripting. I'll have
to give that a try. I could even fail a make if the warning file
changed.


This idea has been wandering around me for some time, too.
It could work like this: programmer puts #pramas in the code,
which contain verbatim quotes (or regexes, or identifires) of warnings
that are to be suppressed for the next line. The utility program (or
a script) calculates line numbers and produces a list of warnings
(with the line numbers) to cut out from the compiler output.
Like this:
#pragma nowarn t.c:%n: warning: comparison between signed and unsigned
if (u>s)

Ugh. Ugh ugh ugh.

First, while the use of warning-suppressing tags in the
code goes back at least to lint, using #pragma to express
them is a truly terrible idea. Somewhere there'll be a
compiler that actually recognizes "#pragma nowarn" and does
something with it -- for example, suppressing all warning
messages for the entire translation unit, or turning on
ARN (automatic name rewriting) NOW. Embed such tags in
specially-formatted comments that are linquistically inert,
not in constructs that might at any moment turn into toxic
chemicals and rot your program.

(Aside: I quite understand that the idea of "a different
compiler" may well be foreign to many projects of interest
in comp.arch.embedded. However, the thread is cross-posted
to comp.lang.c as well, where portability concerns appear to
carry somewhat more weight.)

Second, a far better way to suppress the warning you
mention is

if (u > (unsigned)s)

Sometimes it can be a bad thing for a "last resort" mechanism
to exist: it's too easy for people to give up searching for
the "first resort."

Finally, and it's been said before: The goal of turning
of ALL warnings from ALL compilers is ultimately futile,
because compilers are allowed to complain about anything
they feel like. "Warning: Source was modified at 2:37 AM;
sleep-deprived programmer may have made more mistakes than
usaul."
 
S

S.Tobias

In comp.lang.c Eric Sosman said:
S.Tobias wrote On 10/13/05 17:19,:
In comp.lang.c Thad Smith said:
Albert van der Horst wrote:
[snip]
Make clean code. Catch the warnings in a file.
Carefully inspect the warnings and head them.
Catch the warnings on the resulting cleaner code.
Now in the regression test, expect the warnings to remain
the same, i.e. make a diff with the file with the warnings
of the previous test.
Only act on warnings changes, indicative of new warnings.
That's an interesting idea! I suppose I should strip the line numbers
on the warnings so that code insertion/deletion doesn't trigger an
avalanche in the diff. It's time for a little scripting. I'll have
to give that a try. I could even fail a make if the warning file
changed.
This idea has been wandering around me for some time, too.
It could work like this: programmer puts #pramas in the code,
which contain verbatim quotes (or regexes, or identifires) of warnings
that are to be suppressed for the next line. The utility program (or
a script) calculates line numbers and produces a list of warnings
(with the line numbers) to cut out from the compiler output.
Like this:
#pragma nowarn t.c:%n: warning: comparison between signed and unsigned
if (u>s)

Ugh. Ugh ugh ugh.
That's how great ideas die - someone says "ugh"... ;-)
First, while the use of warning-suppressing tags in the
code goes back at least to lint, using #pragma to express
them is a truly terrible idea. Somewhere there'll be a
compiler that actually recognizes "#pragma nowarn" and does
something with it -- for example, suppressing all warning
messages for the entire translation unit, or turning on
ARN (automatic name rewriting) NOW. :)
Embed such tags in
specially-formatted comments that are linquistically inert,
not in constructs that might at any moment turn into toxic
chemicals and rot your program.
That's true. All #pragmas (with a small exception) suffer from this
disease. OTOH the whole concept is subject to implementation behaviour
and is not (universally) portable. But I agree, it's always better to
avoid a mine-field, and take a quiet and safe path.
(Only, what if the compiler uses the same tags embedded in comments
for its own purposes, too?)

What might actually be bad in practice with #pragmas is that a
compiler might issue warnings about unrecognized #pragmas, thus
we'd be chasing our tail.

Let's make that:
/* $ nowarn: ... $ */
(Actually, only `$ nowarn: ... $' part is recognized by the utility.)

Second, a far better way to suppress the warning you
mention is

if (u > (unsigned)s)

Sometimes it can be a bad thing for a "last resort" mechanism
to exist: it's too easy for people to give up searching for
the "first resort."
That was just a poor example how it could be used. Anyway,
you had to clutter the code to suppress the warning, too.
Sometimes there's no way of "fixing" warnings for all compilers,
you do it for one, and some other issue arises for another.

Consider this (semi-real-life example):
off_t off;
size_t siz;

if (siz > off) ;
may cause:
warning: signed/unsigned in comparison
on one implementation, whereas
if (siz > (size_t)off) ;
on another may issue:
warning: possible loss of data in cast
(besides that casting always makes me feel uneasy).
It's not obvious which side to cast to which.

(I actually solved it this way (through a macro):
if(siz + (off_t)0 > off + (size_t)0) ;
(clue: usual arithmetic conversions).
)
Finally, and it's been said before: The goal of turning
of ALL warnings from ALL compilers is ultimately futile,
because compilers are allowed to complain about anything
they feel like. "Warning: Source was modified at 2:37 AM;
sleep-deprived programmer may have made more mistakes than
usaul."
Well, yes, but my goal is not to turn off ALL warnings, but
only *known* and *inspected* warnings. The idea is that
I don't waste my work when line numbers change.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top