23

So i have some code like this:

void foo (int, int);

void bar ( )
{
    //Do Stuff

   #if (IMPORTANT == 1)
       foo (1, 2);
   #endif

}

When doing a compile without "IMPORTANT" I get a compiler Warning that foo is defined and never referenced. Which got me thinking (that is the problem).

So to fix this i just added the same #if (IMPORTANT == 1) around the function definition etc... to remove the warning, and then I started to wonder if there was a different way to suppress that warning on that function. I was looking at "unused" GCC attrib and didn't know if functions had the same attribute i could set? Is there even another way to suppress it that suppresses that warning for only that function and not the file?

Jtello
  • 752
  • 1
  • 5
  • 17
  • 2
    This should be useful, specifically `ignored`: http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html. I think `push` and `pop` can be used to cover just one function, but I can't say I've ever had to. – chris Jun 20 '12 at 17:26
  • 2
    http://stackoverflow.com/questions/386220/how-can-i-hide-defined-but-not-used-warnings-in-gcc might help – another.anon.coward Jun 20 '12 at 17:30
  • Yes i saw these, but they seem to suppress the unused warnings in the entire file instead of just that specific function, unless i read it wrong. – Jtello Jun 20 '12 at 17:34
  • 2
    What warning options are you using? You should only get that warning for an unused `static` function. In which case, if you declare it `static inline` the warning should go away. – Jonathan Wakely Jun 20 '12 at 17:57
  • I only get a warning when I declare it `static` what I am missing? – Ameen Jan 30 '15 at 08:30
  • Put compiler switches around the _declaration_ rather than the _definition_? – Lundin Dec 02 '15 at 12:39
  • I don't understand why someone would do this, isn't it just plain bad practice to declare and not define a function? – The Floating Brain Aug 17 '19 at 04:36

9 Answers9

41

In C++17 you can declare your function with [[maybe_unused]]:

[[maybe_unused]] void foo (int, int);

This will suppress the warning and is the correct, idiomatic way to express a possibly unused function in C++17.

TartanLlama
  • 63,752
  • 13
  • 157
  • 193
32

I'm fairly sure the relevant warning option is this one:

-Wunused-function
Warn whenever a static function is declared but not defined or a non-inline static function is unused. This warning is enabled by -Wall.

So the warning should only be given for a static function, interesting. Makes sense. If a function is static it can only be used within the current file, so its definition must also be in this file.

And declaring it static inline avoids the warning, without resorting to ugly macros or compiler-specific pragmas or attributes.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • 2
    This should be the accepted answer, imho, as the user asked "Is there even another way to suppress it that suppresses that warning for only that function and not the file?" Declaring the function `static inline` indeed "avoids the warning [for only that function], without resorting to ugly macros or compiler-specific pragmas or attributes". If you have to have such functions in a c++ file without using them, use the `inline` tag. – alex Jun 21 '16 at 12:40
  • 5
    `static inline` doesn't (always) suppress this for clang. – robertwb Nov 16 '16 at 00:52
29

...then I started to wonder if there was a different way to suppress that warning on that function.

There might be compiler option(s) to suppress this warning. However, one trick is this:

(void)foo; //cast it to void.

It should suppress this warning.

You could write a macro:

#define SUPPRESS_WARNING(a) (void)a

void foo(int thisIsAlsoAnUnsedParameter, int usedParameter)
{
   SUPPRESS_WARNING(foo); //better do this inside the definition itself :D

   SUPPRESS_WARNING(thisIsAlsoAnUnsedParameter);
}

As you can see, the definition of foo itself suppresses the warning.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Worked this is exactly what i was looking for thanks! i already have a similar macro for suppressing single variables but not functions :-) – Jtello Jun 20 '12 at 19:53
  • 1
    @Jtello: Actually, the macro which you've can be used to suppress unused function as well. – Nawaz Jun 20 '12 at 20:01
  • 1
    This doesn't work for overloaded functions as you don't appear to be allowed to cast the address of an overloaded function to void. – davidA Jun 29 '14 at 23:51
  • 3
    Also, with Clang 3.4 at least, this appears to replace the unused function warning with a new "Function is not needed and will not be emitted" warning :) – davidA Jun 29 '14 at 23:53
  • It worked well inside the definition itself in `g++`, but not in `gcc`. any other workarounds? – Ameen Jan 30 '15 at 08:47
  • @Nawaz Could you please explain your first line a little more please? I don't understand it. You say that you make it a pointer? It doesn't look like function pointer syntax? – The Floating Brain Aug 17 '19 at 04:34
  • @TheFloatingBrain: Thanks for the comment. That line has been edited. Admittedly it was confusing and probably wrong. – Nawaz Aug 17 '19 at 14:46
  • This indeed supress the warn but for `clang` I still get `main.c:5: warning: function 'foo is not needed and will not be emitted [-Wunneeded-internal-declaration]` – Ilian Zapryanov Feb 12 '22 at 21:01
23

One solution is via function attributes.

void foo (int, int) __attribute__ ((unused));

This will tell gcc not to issue an unused function warning for the function foo. If you're worried about portability, you can define a macro UNUSED_FUNCTION_ATTRIBUTE that expands to __attribute__ ((unused)) with compilers that support attributes, but expands to nothing otherwise.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • 2
    You don't need the `UNUSED_FUNCTION_ATTRIBUTE`. You can define on the compiler that does not support gnu attributes `#define __attribute__(x)` to make them disappear. It has the advantage that it annuls all attributes (pure, const, malloc, printf etc.) and you don't need several ad-hoc macros for all different variants. That was the original rationale for the strange double parenthesis syntax of the `__attribute__` gnu extension, so that even archaic preprocessors without `VARARGS` could neutralize them. – Patrick Schlüter Dec 02 '15 at 16:14
  • 1
    @PatrickSchlüter -- Yes, you could do it that way, but that is essentially invoking undefined behavior. Any identifier, macro or otherwise, that starts with a double underscore is the sole property of the implementation. To be compliant with the standard, user level code can use those (as extensions to the standard provided by the implementation), but user code should not modify or define such identifiers. – David Hammen Dec 02 '15 at 16:37
  • This solution is especially nice if whether or not your function is going to be used depends on a compile-time choice, but you still want to include the function object e.g. for the sake of unit tests. It's then a matter of modifying the header at compile-time. – Joost Apr 26 '17 at 08:04
  • Works for gcc and clang. +1. – akhan Apr 27 '18 at 18:36
  • This does not work on function _definitions_, only on declarations. – Jakub Klinkovský Dec 29 '20 at 18:47
3

A good way to encapsulate compiler- and system-dependent stuff is to factor it out into headers. Then you adjust the include path depending on the compiler and system and perhaps other things. You can do the same for source code files.

In this case the declaration doesn't seem to depend on compiler- or system, so just add the following common header:

// [foo.h]
#pragma once
void foo( int, int );

With implementation file

// [foo.cpp]
#include <foo.virtual.cpp>

Then for the build where something should happen, add to the include path a directory containing

// [foo.virtual.cpp]
#include <foo.h>
void foo( int const a, int const b )
{
    // Do the thing.
}

And for the build where nothing should happen, add to the include path a directory containing

// [foo.virtual.cpp]
#include <foo.h>
void foo( int, int ) {}

If you are afraid that the call of an empty function will be very time consuming, like, a nano-second wasted, then simply move the definitions to headers and add the word inline.

If foo is also used for other purposes, define a function bar that calls it for the should-or-should-not-happen thing, and do the above for bar instead of for foo.

Then, you have removed all the preprocessor stuff.

Remember that preprocessor directives in code are ungood.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
3

I find a way to do that globally and it works also in c

#define SUPPRESS_UNUSED_WARN(var) \
    int _dummy_tmp_##var = ((int)(var) & 0)

then you use it like:

static int foo(int a, int b)
{
    // ....
}
SUPRESS_UNUSED_WARN(foo);
  • it can be used on functions and global variables
  • it should be placed globally in order to work work
  • it can't be used for local variables
Ameen
  • 1,747
  • 3
  • 16
  • 31
  • But if you include your .h file into two .c files - wouldn't that create two dummy tmp variables with the same name? And if you mark it as static - wouldn't that lead to another unused variable warning? – zserge Jan 14 '17 at 00:34
  • To get it work without without invalid pointer casting you should change your macro to: `#define SUPPRESS_UNUSED_WARN(var) int _dummy_tmp_##var = ((uintptr_t)(var) & 0)` – Esato Jul 23 '20 at 06:08
  • I couldn't get this to work, I was getting the error "initializer element is not a compile-time constant". This change worked for me: `#define SUPPRESS_UNUSED_WARN(var) int _dummy_tmp_##var = (0 && (int)(var))` – Jeremy Sep 07 '22 at 19:44
1

For ARM target platform while using, ARM compiler, Use the following compiler directive around the target function to suppress "Warning[Pe177]: function declared but never referenced" warning messages:

#pragma diag_suppress=Pe177
void foo(void)
{
/* does something but is not being called for the current build */
}
Amit
  • 327
  • 1
  • 4
  • 12
0
#define SUPPRESS_UNUSED_WARN(var) \
    int _dummy_tmp_##var = ((int)(var) & 0)

not work in IAR, change to this will work:

#define SUPPRESS_UNUSED_WARN(var) \
     void _dummy_tmp_##var(void) { (void)(var); }
-6

You can also define _CRT_SECURE_NO_DEPRECATE macro in Visual studio project settings.

Goto project Properties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions

Add _CRT_SECURE_NO_DEPRECATE.

Thats it.!

Shivaraj Bhat
  • 841
  • 2
  • 9
  • 20