eliminating unreferenced parameter warnings


J

John Fisher

void f(int p)
{
}

Many (most?) compilers will report that p is unreferenced here. This may not
be a problem as f may have to match some common prototype. Typically
pointers to functions are involved.

For a long time I have used

#define UNUSED(p) ((void)(p))

so that

void f(int p)
{
UNUSED(p);
}

will not cause a warning on all compilers I have tried it with. However a
third party code vendor uses

#define UNUSED(p) { (p) = (p); }

I believe this code has been ported to many different compilers. On my
compiler this will produce a useless assignment warning, so for that reason
I obviously prefer my approach.

What's your favourite trick and why? Which approach do you think is more
likely to prevent a warning? Has anyone done a survey?
 
Ad

Advertisements

C

Clark S. Cox III

void f(int p)
{
}

Many (most?) compilers will report that p is unreferenced here. This may not
be a problem as f may have to match some common prototype. Typically
pointers to functions are involved.
[snip]

What's your favourite trick and why? Which approach do you think is more
likely to prevent a warning? Has anyone done a survey?

I typically just delete the parameter name if I'm not actually using it:

void f(int)
{
}
 
M

Mike Wahler

John Fisher said:
void f(int p)
{
}

Many (most?) compilers will report that p is unreferenced here. This may not
be a problem as f may have to match some common prototype. Typically
pointers to functions are involved.

For a long time I have used

#define UNUSED(p) ((void)(p))

so that

void f(int p)
{
UNUSED(p);
}

will not cause a warning on all compilers I have tried it with. However a
third party code vendor uses

#define UNUSED(p) { (p) = (p); }

I believe this code has been ported to many different compilers. On my
compiler this will produce a useless assignment warning,

The warning is telling you that what's 'useless' is your parameter
declaration (because it's not used). I suppose the warning is so that
you'll double check to see if you meant to write the parameter
name, but misspelled it as some other name that's in scope.
I think this warning can be quite useful in that case.

so for that reason
I obviously prefer my approach.

What's your favourite trick and why?

I typically won't define arguments which I won't use.

However, if I did (perhaps I'm wanting to compile before
I've completed the function body), I'd probably do one of:

void f(int)
{
/* etc */
}

or

void f(int p)
{
p;
/* etc */
}
Which approach do you think is more
likely to prevent a warning?

I can't say without knowing which compiler(s)
are involved.
Has anyone done a survey?

I doubt it. It's a very trivial issue.

-Mike
 
E

E. Robert Tisdale

John said:
void f(int p) {
}

Many (most?) compilers will report that p is unreferenced here.
This may not be a problem as f(int) may have to match some common prototype.
Typically, pointers to functions are involved.

For a long time I have used

#define UNUSED(p) ((void)(p))

so that

void f(int p) {
UNUSED(p);
}

will not cause a warning on all compilers I have tried it with.
However, a third party code vendor uses

#define UNUSED(p) { (p) = (p); }

I believe this code has been ported to many different compilers.
On my compiler, this will produce a useless assignment warning
so, for that reason, I obviously prefer my approach.

What's your favourite trick and why?
Which approach do you think is more likely to prevent a warning?
Has anyone done a survey?

You obviously have too much time on your hands.
Warning messages are supposed to be ignored if your code is correct.
Usually, there is an option to silence these warnings
if the verbosity conceals other more important errors and warnings.
 
J

John Fisher

I'm talking about situations where you can't delete the parameter, because
the function must match a common prototype e.g. in addition to my first
example

void g(int p)
{
/* Use p */
}

and

{
void (*fp)(int);
int i;

/* Assign a value to i */

/* In some circumstances we have */
fp = f;

/* Other circumstances we have */
fp = g;

/* All circumstances we have */
fp(i);
}

Apologies if I didn't make myself clear the first time
void f(int p)
{
p;
/* etc */
}

Some compilers will give a useless expression warning in this situation,
thats why I cast to void in the macro
I doubt it. It's a very trivial issue.

Getting rid of pointless warnings is important because it makes it less much
less likely that important warnings will be overlooked.
 
Ad

Advertisements

M

Mike Wahler

John Fisher said:
I'm talking about situations where you can't delete the parameter, because
the function must match a common prototype e.g. in addition to my first
example

void g(int p)
{
/* Use p */
}

and

{
void (*fp)(int);
int i;

/* Assign a value to i */

/* In some circumstances we have */
fp = f;

/* Other circumstances we have */
fp = g;

/* All circumstances we have */
fp(i);
}

Apologies if I didn't make myself clear the first time


Some compilers will give a useless expression warning in this situation,
thats why I cast to void in the macro


Getting rid of pointless warnings is important because it makes it less much
less likely that important warnings will be overlooked.

IMO every warning merits attention. I wouldn't let
the fact that I might consider some to be pointless
cause me to adopt the same attitude for other warnings.

The point I was trying to make is that the warning you
mention can indeed disclose a true problem (e.g. the
'misspelling' error I mentioned).

Once I determined that the warning is indeed about something innocuous,
I wouldn't have a problem with writing:

void func(int p)
{
(void)p;
/* etc */
}

But I'd include a comment indicating the reason (and I
wouldn't hide things with a macro).

-Mike
 
J

John Fisher

Warning messages are supposed to be ignored if your code is correct.

That's one option, but in my experience almost all warnings can easily be
eliminated and should be because it makes it less likely that important
warnings are overlooked.
Usually, there is an option to silence these warnings

If I used an option to turn warnings off, or even a class of warnings off,
then important warnings might be missed.

The point of the macro is to suppress these warnings on an individual basis.
I have seen quite widespread use of this idea. Some compilers recognize a
special comment /*ARGSUSED*/ to prevent this particular warning, but of
course thats extremely compiler specific.
 
E

E. Robert Tisdale

John said:
That's one option but, in my experience,
almost all warnings can easily be eliminated and should be
because it makes it less likely
that important warnings are overlooked.

That's understood.
But you have gone beyond that.
You are not fixing questionable code.
You are inserting implementation specific code
(always a dubious practice)
just to shut-up a verbose compiler.
If I used an option to turn warnings off, or even a class of warnings off,
then important warnings might be missed.

That's what I said.
Study your compiler warning options.
They may allow you to silence just the warnings
about code that you know is correct.
The point of the macro is to suppress these warnings on an individual basis.
I have seen quite widespread use of this idea.
Some compilers recognize a special comment /*ARGSUSED*/
to prevent this particular warning
but, of course, that's extremely compiler specific.

Don't cobble your code just to appease an inferior compiler.
Your code will be more portable,
if you avoid implementation specific features.

It isn't practical or even desirable to silence all warnings.
They are warnings and not errors so that you can ignore them
if you know that your code is correct.
 
I

infobahn

John said:
void f(int p)
{
}

Many (most?) compilers will report that p is unreferenced here. This may not
be a problem as f may have to match some common prototype. Typically
pointers to functions are involved.

For a long time I have used

#define UNUSED(p) ((void)(p))

so that

void f(int p)
{
UNUSED(p);
}

will not cause a warning on all compilers I have tried it with. However a
third party code vendor uses

#define UNUSED(p) { (p) = (p); }

I believe this code has been ported to many different compilers. On my
compiler this will produce a useless assignment warning, so for that reason
I obviously prefer my approach.

If you use enough compilers, you'll find one that warns against just
about any simple construct you care to invent. One way to avoid such
warnings, however, is to use the parameter, in such a way that the
compiler can't (easily) tell you're just kidding. (See below.)

And then, if you want to, use the preprocessor to define it away for
production code.

What's your favourite trick and why? Which approach do you think is more
likely to prevent a warning? Has anyone done a survey?

My favourite trick is:

#ifndef NDEBUG
void Sink(void *p)
{
static int i;
if(i == 0)
{
i = 1;
Sink(p);
}
}
#else
#define Sink(x)
#endif

int f(int p)
{
/* definitions go here */

Sink(&p);

/* code goes here */
}
 
Ad

Advertisements

R

Randy Howard

Don't cobble your code just to appease an inferior compiler.
Your code will be more portable,
if you avoid implementation specific features.

Care to explain how using a comment block as shown above could
impact portability? It may not have the desired result on
every compiler (making the warning go away), but I can't think
of a situation in which it would not compile as a result of
using that comment. Can you?
 
L

Lawrence Kirby

By defining a macro you can easily change it to whatever is apporpriate to
the compiler you are using. Even if you don't it doesn't make the code
incorrect for other compilers.

I would prefer

#define UNUSED(p) ((p) = (p))

although it doesn't matter that much in the context where this should be
used.

If you're worried about this just make a couple of choices available in
the header that defines UNUSED().
You obviously have too much time on your hands.
Warning messages are supposed to be ignored if your code is correct.

It would be even better if warning messages didn't exist if your code is
correct. For anybody else who has to maintain your code subsequently
warnings need to be checked. And even for code I wrote I don't want to
have to weed out the genuine errors from the "spurious" warnings each time
I compile something.
Usually, there is an option to silence these warnings
if the verbosity conceals other more important errors and warnings.

The point is that the same warning could indicate a genuine error in some
circumstances. Just disabling warnings or classes of warnings is not a
sensible solution to this.

Lawrence
 
C

Chris Croughton

What's your favourite trick and why? Which approach do you think is more
likely to prevent a warning? Has anyone done a survey?

#pragma unused x

is the cleanest I've seen. But that is supported even less than the
other methods (x=x; and (void)x;) unfortunately. Both the redundant
assignment and the cast to void tend to give "statement doesn't do
anything" type errors on various compilers.

Of course, any compiler can give any diagnostics it likes and still be
compliant ("Error 9999: this code is rubbish!") for any or no reason, as
long as it still compiles a valid program...

Chris C
 
C

CBFalconer

Randy said:
(e-mail address removed) says...


Care to explain how using a comment block as shown above could
impact portability? It may not have the desired result on
every compiler (making the warning go away), but I can't think
of a situation in which it would not compile as a result of
using that comment. Can you?

+-------------------+ .:\:\:/:/:.
| PLEASE DO NOT | :.:\:\:/:/:.:
|FEED THE TROLLSDALE| :=.' - - '.=:
| | '=(\ 9 9 /)='
| Thank you, | ( (_) )
| Management | /`-vvv-'\
+-------------------+ / \
| | @@@ / /|,,,,,|\ \
| | @@@ /_// /^\ \\_\
@[email protected]@[email protected] | | |/ WW( ( ) )WW
\||||/ | | \| __\,,\ /,,/__
\||/ | | | jgs (______Y______)
/\/\/\/\/\/\/\/\//\/\\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
==============================================================
 
C

Chris Croughton

It would be even better if warning messages didn't exist if your code is
correct. For anybody else who has to maintain your code subsequently
warnings need to be checked. And even for code I wrote I don't want to
have to weed out the genuine errors from the "spurious" warnings each time
I compile something.

Exactly. Every spurious warning which has to be checked makes it less
likely that real warnings will be noticed (as in the story of the boy
who cried 'wolf'), and slows down maintenance.
The point is that the same warning could indicate a genuine error in some
circumstances. Just disabling warnings or classes of warnings is not a
sensible solution to this.

Some compilers allow warnings to be switched on or off (or back to the
default) with a #pragma in the specific part of the code. I think that
is the best solution, because it means that warnings can be disabled
only for sections where they are known to be spurious. Having a #pragma
which says "ignore just this variable if it is unused" is even better in
this case (although not necessarily in the general case).

Chris C
 
Ad

Advertisements

D

Daniel Vallstrom

John said:
void f(int p)
{
}

Many (most?) compilers will report that p is unreferenced here. This may not
be a problem as f may have to match some common prototype. Typically
pointers to functions are involved.

For a long time I have used

#define UNUSED(p) ((void)(p))

so that

void f(int p)
{
UNUSED(p);
}

will not cause a warning on all compilers I have tried it with. However a
third party code vendor uses

#define UNUSED(p) { (p) = (p); }

I believe this code has been ported to many different compilers. On my
compiler this will produce a useless assignment warning, so for that reason
I obviously prefer my approach.

What's your favourite trick and why? Which approach do you think is more
likely to prevent a warning? Has anyone done a survey?

This is indeed not an uncommon problem.

If you only care about suppressing warnings from compilers that support
an attribute to parameters, I prefer using those compiler specific
attributes. For example you would write:

int constantEvil( int dummyArg attribute__(unused) ) { return 666; }

where attribute__ is defined something like this:

#ifdef __GNUC__
#define attribute__(a) __attribute__ ((a))
#else
#define attribute__(a)
#endif


Altering the program as such by adding spurious statements like (void)x
or x=x feels ugly regardless of the issue that it might not be
effective.


Daniel Vallstrom
 
Ad

Advertisements

J

John Fisher

To summarize the discussion:
Possible methods of eliminating the warning are

1. ((void)(p))
2. ((p) = (p))
3. #pragma unused p
4. GNU C's __attribute__((unused))
5. /*ARGUSED*/

It is not known which is supported by the largest proportion of compilers.
None of these methods are 100% portable. For this reason some believe that
it is not worth doing.
A macro could be used to switch between methods 1, 2 and nothing at all, or
method 4 and nothing at all. Either don't attempt to eliminate the warning,
or find the method or combination of methods that works best for your
particular set of compilers.
 

Top