Table of "safe" methods to suppress "unused parameter" warnings?

Discussion in 'C Programming' started by mathog, Mar 26, 2014.

  1. mathog

    mathog Guest

    Sometimes the same parameter list must be passed to a lot of different
    functions, and some of those will not use all of the parameters,
    resulting in some compilers emitting "unused parameter" warnings. Here
    are all of the methods I have found so far for suppressing these:

    This first set of UNUSED's are applied where the parameters are declared
    in the function, as in

    int function( UNUSED(x)){

    #ifdef UNUSED
    #elif defined(__GNUC__)
    # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
    #elif defined(__LCLINT__)
    # define UNUSED(x) /*@unused@*/ x
    # define UNUSED(x) x

    The main problem with these is that the method only works for compilers
    and tools that define a way to ignore the extra parameter in this
    manner. It also ruins the readability of the function declarations.

    This second set of UNUSED's is more general and it is applied within the
    function like:

    int function (x){

    #define UNUSED(x) ((void)x)
    #define UNUSED(x) x=x
    #define UNUSED(x) ( *(volatile typeof(x) *)&(x) = (x); )
    #define UNUSED(x) if(x);

    Unfortunately the members of the second set tend to convert the "unused
    parameter" message into some variant of a "this line does nothing"
    message on other compilers. For instance, that is what the "x=x" form,
    which works with gcc does when clang sees it.

    What I'm wondering is if any of you have a table of compiler
    identification macros vs. members of the second set, that can be used in
    a header file to pick the appropriate method for each compiler, so that
    compilation with the strictest warnings is silent about unused
    parameters. Like this (this example is entirely made up, I am NOT
    saying that the associations below are correct):

    #if defined (__GNUC__)
    #define UNUSED(x) x=x
    #elif defined (__CLANG__)
    #define UNUSED(x) ((void)x)
    #elif defind (__INTELC__)
    #define UNUSED(x) ( *(volatile typeof(x) *)&(x) = (x); )
    /* etc. */

    There is one other method I know of, which is to actually use the
    parameter "harmlessly", but it has its own issues. For instance to do

    extern unsigned int junk;

    and within the function


    With junk defined globally in the c file that holds main(). If the
    compiler only sees one module at a time it cannot tell if junk will ever
    be used, so it should not give any warnings. If the program is a single
    file though, or all modules are compiled together, the compiler will be
    able to detect that nothing is actually happening and issue warnings to
    that effect.


    David Mathog
    mathog, Mar 26, 2014
    1. Advertisements

  2. If the parameter x is not a function pointer, why not use the simpler

    If x is a function pointer, a couple of options come to mind
    if (0) x(appropriate dummy arguments);
    or if the compiler generates a diagnostic for the if expression being
    constant then you could use an expression you know to be false but the
    compiler would not, such as
    if (agrc < 0) x(...);
    Barry Schwarz, Mar 26, 2014
    1. Advertisements

  3. [...]



    version is perfectly valid whether x is a function pointer or not.

    BTW, argc, assuming it's the conventional first argument to main,
    isn't visible outside main, unless you've declared something with
    that name yourself.
    Keith Thompson, Mar 26, 2014
  4. mathog

    Javier Lopez Guest

    El 26/03/2014 18:55, Barry Schwarz escribió:
    This works for pointer to function, at least on gcc 4.6.3.
    Unless you don't care about CPU cycles, it's better to see a compiler
    warning than to write code the compiler cannot optimize out.
    Javier Lopez, Mar 26, 2014
  5. mathog

    Kaz Kylheku Guest

    (void) x works even if x is a struct. Though the standard doesn't seem
    to spell it out, any expression can be converted to void, which results
    in a "void expression" that is evaluated for its side effects only.

    Also, the void type is the only non-scalar type that may be used in a cast.
    Furthermore, the constraint that the operand be scalar does not apply
    if the cast is to (void).
    Kaz Kylheku, Mar 26, 2014
  6. mathog

    mathog Guest

    Here is a small example program to test these methods on
    various compilers. The results I found follow the program.
    (I don't have access to all that many compilers, and some of them are
    very old.)

    ---cut here -- test_unused.c --
    #include <stdlib.h>
    #include <stdio.h>

    #ifdef UNUSED
    #elif defined(__GNUC__)
    # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
    #elif defined(__LCLINT__)
    # define UNUSED(x) /*@unused@*/ x
    # define UNUSED(x) x

    void method1(int x){
    (void) x;
    printf("method 1\n");

    void method2(int x){
    x = x;
    printf("method 2\n");

    void method3(int x){
    *(volatile typeof(x) *) &(x) = (x);
    printf("method 3\n");

    void method4(int x){
    printf("method 4\n");

    void method5(int UNUSED(x)){
    printf("method 5\n");

    int main(void){
    ---cut here ----


    (gcc 4.6.3 and 4.7.2 tested, they did the same thing)
    gcc -Wall -Wextra --std=c99 -o test_unused test_unused.c
    test_unused.c: In function 'method3':
    test_unused.c:24:4: error: unknown type name 'typeof'
    test_unused.c:24:22: error: expected ')' before 'x'
    test_unused.c:24:25: error: expected ')' before '*' token

    gcc -Wall -Wextra -o test_unused test_unused.c
    no warnings

    (Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on
    LLVM 3.0))
    clang -Wall -o test_unused test_unused.c
    test_unused.c:20:6: warning: explicitly assigning a variable
    of type 'int' to itself [-Wself-assign]
    x = x;
    ~ ^ ~

    (A very old version of the intel linux compiler == 9.0)
    iccbin -Wall -std=c99 -gcc-version=340 -i-static \
    -o test_unused test_unused.c
    warns about "external definition with no prior declaration" for all
    of the functions, but did not warn about anything else.

    (A very old version of the Sun Forte Developer 7.0 C 5.4
    on an equally old Sparc)
    cc -o test_unused test_unused.c
    "test_unused.c", line 25: warning: no explicit type given
    "test_unused.c", line 25: syntax error before or at: typeof
    "test_unused.c", line 29: type specifier can not be used as array size
    expression qualifier
    "test_unused.c", line 29: warning: no explicit type given
    "test_unused.c", line 29: cannot recover from previous errors

    And that's all the compilers I have to test.


    David Mathog
    mathog, Mar 27, 2014
  7. mathog

    Javier Lopez Guest

    (gcc 4.6.3 and 4.7.2 tested, they did the same thing)
    typeof is a GNU C extension, so enabling c99 disables GNU extensions
    This goes away if you forward-declare the functions.
    See above
    You should be using (void)x regardless the compiler as any of them
    accept it and can optimize that out.
    Javier Lopez, Mar 27, 2014
  8. mathog

    Thomas Jahns Guest

    I've found __typeof to be reasonably portable (supported by gcc, xlc, pgcc and icc).

    Thomas Jahns, Mar 27, 2014
  9. mathog

    Ian Collins Guest

    I wonder why C doesn't just follow C++ and allow unnamed parameters?
    Ian Collins, Mar 27, 2014
  10. In comp.lang.c, there is no such thing as "reasonably" portable.

    (The old saw about being "sorta pregnant" comes to mind...)
    Kenny McCormack, Mar 27, 2014
  11. mathog

    David Brown Guest

    Even if typeof is accepted by the compiler, the usage here is /really/
    bad - it forces a volatile write to the function's parameter which will
    undoubtedly generate extra code, and may force a number of additional
    effects such as blocked optimisations, copying of register parameters
    into a stack frame (which may in itself force the use of a stack frame
    that could otherwise be omitted), etc.

    It also means that if you have more sophisticated optimisation at play,
    such as inlining, function cloning, etc., then you will make a mess with
    such extra volatile accesses.

    The simple "(void) x" should work on all compilers and produce no effect
    on the code.
    David Brown, Mar 27, 2014
  12. mathog

    Tim Rentsch Guest

    I suggest trying this form:

    #define UNUSED(x) ( (void) (0 ? 0 : &(x)) )

    or perhaps this alternate definition:

    #define UNUSED(x) ( (void) (0 ? &(x) : &(x)) )

    I'm interested to hear what you results you get if you
    try these with different compilers.
    Tim Rentsch, Mar 30, 2014
  13. mathog

    Tim Rentsch Guest

    Assuming for the sake of discussion that C did this, it
    still doesn't solve the problem, because sometimes you
    want the parameter name there but still have it not used,
    eg, when a function body has multiple definitions under
    control of a C preprocessor conditional. And there are
    variables besides parameter names that are important to
    mark UNUSED in certain circumstances.
    Tim Rentsch, Mar 30, 2014
  14. mathog

    Ian Collins Guest

    I disagree. Allowing unnamed parameters would address the exact problem
    stated in the question. I don't see how multiple definitions under
    control of a C preprocessor conditional would make a difference. If an
    "unused" parameter is used in the function body, you have a bug waiting
    to happen. It would be better to have it unnamed to allow the compiler
    to spot the mistake.

    If you turn the argument on its head, why does C require parameters to
    be named? There doesn't appear to be any logical reason for this rule.
    I assume you are referring to unused function return values? I don't
    see how this is relevant to the original question.
    Ian Collins, Mar 30, 2014
  15. mathog

    David Brown Guest

    I disagree (at least a bit) here - I don't see any reason to have
    unnamed parameters in C. If the parameter is completely useless, then
    it should be removed entirely - if not, then the name is part of the
    documentation for the function's interface. Just because it is not used
    in this particular version of the implementation of the function, does
    not mean it should not be named.

    And the solution to the original problem is nothing more dramatic than
    "(void) x;", which is neither hard to write nor hard to understand.

    In C++, I can think of a situation where unnamed parameters make sense -
    you might want a function that requires you to have an object of a
    particular class but does not care about the contents. This can be used
    to give compile-time checking of constraints. For example, if your
    system has a global interrupt lock, then you might use a class
    "InterruptDisabler" whose constructor preserves the old interrupt state
    and disables interrupts, and whose destructor restores the state. A
    function that expects interrupts to be disabled could take an unnamed
    parameter of type "const InterruptDisabler&".
    David Brown, Mar 31, 2014
  16. I think the OP mentionned callbacks (see above, I hope I have the
    quoting right), where the interface is imposed. Typically, GUI toolkits
    make massive use of this, but pthread_create is another example---there
    are cases where a thread does not take a parameter, and relies on shared
    data only.

    I've had this situation often, I would like to see unnamed parameters in
    C (a simple comment solves the "documentation issue").
    Agree. It is still somewhat strange to insert a statement with no
    Not only. Virtual member functions are a (fairly frequent) variant of
    the "callback" approach.
    Not sure about your last sentence... And the whole idea seems rather,
    well, unusual.

    -- Alain.
    Alain Ketterlin, Mar 31, 2014
  17. mathog

    Ian Collins Guest

    How so? Consider for example a device driver interface that uses a
    struct of function pointers (a pretty common case). All divers use the
    same struct, but not all divers require all of the parameters that are
    passed. Having the parameter unnamed clearly documents that it is unused.
    True, but it is ugly. What possible harm could unnamed parameters cause?
    Unnamed parameters are quite common in C++, probably more common than
    cases where they would be useful in C. While the potential uses aren't
    a common in C, the feature would still be a useful, cost free, addition.
    Ian Collins, Mar 31, 2014
  18. mathog

    David Brown Guest

    Such code may be inefficient on some compilers (and with some options) -
    if "x" has been passed in a register, the compiler may copy it onto the
    stack in order for it to have an address, even though the address is not

    I have yet to see any reason to why anyone would need something other
    than "(void) x;" as a way to say "do nothing with x". An endless supply
    of suggestions of macros that mess around with "x" in weird ways does
    not help anyone.

    (Tool-specific annotations such as gcc "unused" attribute or PC-Lint
    annotations can be a useful addition if you use those particular tools.)
    David Brown, Mar 31, 2014
  19. mathog

    James Kuyper Guest

    On 03/31/2014 07:26 AM, David Brown wrote:
    Because they're looking for something that will work on compilers where
    (void)x doesn't work. It could "not work" in two different ways: the
    compiler is too dumb to avoid wasting time evaluating 'x', even though
    nothing is done with the value of that expression, or it is too "smart"
    to be fooled by (void)x, and still complains either about x being
    unused, or about (void)x not doing anything.

    I don't know of any such compilers, but neither have I bothered testing.
    I have a policy of not changing my code to turn off non-mandatory
    diagnostics unless I agree that they have detected an actual problem for
    which the re-write is an appropriate solution.

    (void)x is one of the possibilities considered by mathog, yet it's not
    the only one he considered, so I presume he found at least one platform
    where it didn't work.
    James Kuyper, Mar 31, 2014
  20. mathog

    David Brown Guest

    I missed that bit - sometimes threads in c.l.c. get so long that I have
    to skip many details.

    But you are right - that /is/ a good reason to have unnamed parameters
    in C. If you have to fit a function into a particular general function
    type, then you will sometimes be forced to have parameters that are
    never used, and typically have generic names like "param1" in the
    function type declaration - leaving them unnamed in the function
    definition would be clear documentation that they are never used in that
    particular function.

    So I'll make a minor U-turn and say that unnamed parameters in C /would/
    sometimes be a useful feature.
    True, but without any standard way of handling this then "(void) x;" is
    the simplest and clearest way to have a statement with no effect.
    I think the idea is perhaps unusual - and it is certainly heretic in
    c.l.c. If you haven't done embedded development, then the idea of
    "disabling interrupts" is probably a bit odd. But let's take another
    example. Suppose you have some sort of lock, with two functions
    "getBigLock()" and "releaseBigLock()":

    extern void getBigLock(void);
    extern void releaseBigLock(void);

    // Don't call this unless you've got the big lock!
    extern void doSomethingDangerous(void);

    void foo(void) {

    void bar(void) {

    In this case, the compiler cannot help spot that bar() is going to cause
    trouble - you are reliant on comments and programmer care to get the
    locking right.

    In C++, you could do this:

    class BigLock {
    BigLock() { getBigLock(); }
    ~BigLock() { releaseBigLock(); }

    extern void doSomethingDangerous(const BigLock&);

    void foo(void) {
    BigLock bl;

    void bar(void) {

    bar() is now clearly a compile-time error. doSomethingDangerous()
    doesn't actually do anything with the parameter - it just uses
    type-checking to ensure that you have a BigLock.

    With enough care, templates, and hierarchies, you can do quite a bit of
    compile-time checking using types like this.
    David Brown, Mar 31, 2014
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.