While reading parts of the code of a big C project, I found some arguments that were marked as unused but were in fact used in the function.
I thought about grepping the unused attributes but there are too many of them to manually verify if they are really unused.
My question is the following: is there a way to ask to gcc (or clang) if any attributes are not justified or not applied? Basically, for that kind of code:
int f(int arg __attribute__((unused))) {
return arg + 2;
}
I would like a warning telling my that my argument is not unused.
I can't really take credit for this, as I stumbled upon it at http://sourcefrog.net/weblog/software/languages/C/unused.html.
It causes UNUSED variables to give compiler errors when you attempt to use them.
#ifdef UNUSED
// Do notthing if UNUSED is defined
#elif defined(__GNUC__)
// Using the gcc compiler - do the magic!
#define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#elif defined(__LCLINT__)
#define UNUSED(x) /*#unused#*/ x
#else
// unknown compiler - just remove the macro
#define UNUSED(x) x
#endif
It wont help you find unused variables, but once found you can ensure they really are unused.
You can #define the unused away, like so
#define unused
Empty __attribute__ statements are ignore and the compiler shall issues a warning about "unused parameter, if ran with the right option (-Wunused-parameter) enabling warnings.
However this could break the code if the character sequence unused is used somewhere else in the code, as it would disappear there also.
I cannot speak for GCC, but you can teach Clang to scream and shout using the -Werror-used-but-marked-unused flag.
You can cover the opposite case too using -W(error-)unused-parameter.
Because there are so many useful warnings in Clang, I usually just use -Werror -Weverything, though—selectively ignoring the ones I’m not interested in, and preventing e.g. implementing/calling deprecated functions/methods to be promoted to errors using -Wno-error-....
I used alk answer but I'm giving more details for those facing the same problem.
First part:
alk suggested to define a macro named unused. Since it's a large project with several build units and Makefiles, I decided to define the macro using gcc:
gcc -Dunused= ...
Then, I've cleaned-up the project and rebuilt:
make clean && make
That went very badly because of variables called unused_something in the code. So I had to rename these variables in order to continue.
Since I'm using the -Wall option, I'm now getting a lot of warnings that all look like:
char/serial.c: In function ‘serial_write’:
char/serial.c:151:69: warning: unused parameter ‘odf’ [-Wunused-parameter]
static size_t serial_write(tty_struct_t *tty, open_file_descriptor* odf __attribute__((unused)), const unsigned char* buf, size_t count)
^
So I reran with:
make clean && make > out 2>&1
And now, I grep the result:
grep Wunused-parameter out
I'm getting all the warnings with the name of the file and the line number.
Second part:
Since I use git, I can directly do:
git grep -n "((unused))"
With that, I have all the lines containing the attribute unused. However, if a line contains two or more unused attribute, I'll get it only once.
Last part:
I check which lines are not on both outputs, manually :/.
Related
When I compile using gcc --std=c99 -g -Wall ... I get this:
warning: implicit declaration of function ‘madvise’ [-Wimplicit-function-declaration]
...
error: ‘MADV_DONTNEED’ undeclared
...
So I used this: `gcc -print-prog-name=cpp` -v to find where my compiler is looking for headers and found that there is only header for sys/mman.h so I looked at the files source and it shows this:
#ifdef __USE_BSD
/* Advise the system about particular usage patterns the program follows
for the region starting at ADDR and extending LEN bytes. */
extern int madvise (void *__addr, size_t __len, int __advice) __THROW;
#endif
I did some research into why __USE_BSD wouldn't be defined but didn't find much. What I did find is that features.h can be used to define it. So I tried putting this at the top of my code:
#define _BSD_SOURCE 1
#include <features.h>
This seems to work but I've never done this sort of thing before. am I going about this the right way? I'm just concerned that my methodology is a bit hacky...
I happened across a reference to feature_test_macros(7) which suggests defining as I have in my question, or (as I have opted to do) use the -D flag to define the macros using the compiler. I chose this option so that the macros I need defined will be defined for across multiple source files.
Firebird's C preprocessor, gpre, creates the following definition in the C code it generates from my .e source files:
static const ISC_STATUS *gds__null = 0; /* dummy status vector */
I'm not using this value anywhere in my code. Perhaps I should be, but I don't appear to have any need for it (any suggestions as to its appropriate usage are welcomed). In any case, as I'm not using the variable, I get the following compiler warning from gcc:
warning: 'gds__null' defined but not used
I'm wondering if there is some way to tell the compiler that I'm not going to be using the value of this variable, either in the code (keeping in mind that the definition is being inserted by the gpre preprocessor; I have no way to change the definition) or via a command-line argument to the compiler. Or perhaps there is some way to instruct gpre not to inject this definition into the code if we're not using it. I'd like to preserve other unused variable warnings, so -Wno-unused is not an option.
The solution here sort of works, as I can insert the following into an arbitrary function within my .e source file and it gets rid of the warning:
(void) gds__null;
However, it seems inelegant to place this line arbitrarily into a function where it's not serving any clear purpose just to get rid of the compiler warnings. I'm hopeful that there is a better solution. My last resort would be doing some sed replacement on the generated C files post-gpre/pre-gcc, but I'm hoping it doesn't come to that.
The way to tell gcc to suppress the unused-variable warning on a specific variable is to add __attribute__((unused)) to its declaration.
You could inject this attribute using the preprocessor:
-Dgds__null="gds__null __attribute__((unused))"
Or, avoiding spaces in command line arguments:
-Dgds__null=(gds__null)__attribute__((unused))
This will of course break if you do end up using that variable as it is intended.
It might be better to add a function specifically for the purpose of suppressing the warning; this would itself have to suppress its own unused function warning:
static void suppress_unused_warnings() {
(void) suppress_unused_warnings;
(void) gds__null;
}
I'm guessing that this is going to be a really obvious and simple solution.
int is_full() {
return (top == STACK_SIZE);
}
The issue could be that 'STACK_SIZE' is a macro declared on compilation simply by entering -DSTACK_SIZE=10. That 10 can be something else. I'm unsure how to handle that, or if I'm declaring it right, or need to declare it inside the program as well.
You think STACK_SIZE is being defined, but its not.
the compiler sees:
int is_full() {
return (top == );
}
figure out why the #define is not going through.
I think you are using a macro from a Makefile. I assume this looking at the -D in front of STACK_SIZE=>
-DSTACK_SIZE=10. I assume also that you are using something like gcc because Visual Studio for example uses \D to define macros. This way to define the Macro as you can see above is not portable.
The macro can be defined also in the code. In this case you need to write
#define STACK_SIZE (10)
without using the '=' symbol. This method is portable, by the way the first form is often preferred when you have to change value depending on configurations as it doesn't require to change the code. In any case the code you wrote cannot be compiled if
-DSTACK_SIZE=10 isn't properly declared in the Makefile so, if you choose to use the Makefile definition, you need to protect your code by the weird errors you posted doing something like this:
#ifndef STACK_SIZE
/* handle with a default value o with the macro #error */
#else
return (top == STACK_SIZE);
#endif
Obviously in your case you made some mistake on the Makefile, infact the STACK_SIZE is not defined and you get that return(==); error that you could simply avoid (or manage) with the instructions shown above.
I'm trying to compile -Wall -Werror and its cramping my style.
I'm trying to make explicit that certain arguments are constants and then passing them to non const qualifying functions inside a large library.
P.S. I was mostly doing this to try to make it clear that certain variables are constants, is it good or bad c style to do this when dealing with a library functions that don't use const?
If you are passing those constants into routines as reference parameters or by pointer, then there may be a damn good reason for those warnings. How do you know that those routines won't modify your "constants"? What is that gonna screw up in the rest of your code, which you told that those variables won't ever change?
If you really know for sure that what you are doing is safe, and there is no good way to recode things to get rid of the warning, you can turn some warnings off in gcc using pragmas. Do this for as small an area of code as possible, and comment why you are doing it.
Do not abuse this privelege, or you are liable to arrested by the code police and sentenced to 9 months of community service coding in Ada. That'll cure you of ever complaining about C's warnings again.
Use the -Wno-ignored-qualifiers switch.
Sometimes, when compiling with -Wall -Wextra -Werror (as I do too because it is very good practice), you face recurring warnings that you may want to disable project wide, or on a per source file basis. One that I disable often in my projects for instance is -Wno-long-long. This is not bad practice, because you know what you are doing, and you don't want to control third party code.
As I understand though, you are trying to disable the warning for specific parts of the code, since otherwise it would ruin your effort putting const everywhere. In this case, do:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
OffendingThirdPartyFunction(MyConstParam);
#pragma GCC diagnostic pop
or also (untested, I don't know where to put the semicolons, and I don't have a working GCC here at work)
#define NO_WARNING(expr) \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wignored-qualifiers\"") \
expr \
_Pragma("GCC diagnostic pop")
NO_WARNING(OffendingThirdPartyFunction(MyConstParam));
Alternatively, you can use a cast. This is by far the most portable solution.
OffendingThirdPartyFunction((param_t*)MyConstParam);
Don't use a command-line option: the warning tells you that your code is not const-safe. It's right, your code isn't const-safe, although that's the fault of whoever wrote the library you're using.
If you disable the warnings then you won't get them any more even if you write code that's unsafe and it is your fault.
Instead, whenever one of the library functions takes a pointer-to-non-const, but guarantees not to modify the referand of the pointer, then cast the const-ness away from your pointer, and pass that. The cast serves as a record in the code that you (the programmer) are claiming that nothing invalid will happen, even though the type system can't prove that, and should probably be commented.
For example:
// in this library
void print_int(int *p) { printf("%d\n", *p); }
void set_int(int *p) { *p = 6; }
// your code
const int n = 5;
print_int((int*)(&n)); // warning suppressed for this call only,
// having carefully checked the print_int docs.
// further down your code
set_int(&n); // You *want* the compiler to stop this!
Or if you can be bothered (because you have a lot of such calls), write wrappers for the offending library functions:
void print_int_const(const int *p) { print_int((int*)(p)); }
// but no wrapper for set_int
Be aware that the cast also removes volatile (and in general accepts a lot of incorrect inputs). The overload prevents you accidentally using completely the wrong type, while the in-place cast doesn't.
This question already has answers here:
How can I suppress "unused parameter" warnings in C?
(12 answers)
Closed 4 years ago.
What is the best/neatest way to suppress a compiler (in this case GCC) like "Unused variable x" warning?
I don't want to give any certain flags to GCC to remove all these warnings, just for special cases.
(void) variable might work for some compilers.
For C++ code, also see Mailbag: Shutting up compiler warnings where Herb Sutter recommends using:
template<class T> void ignore( const T& ) { }
...
ignore(variable);
Do not give the variable a name (C++)
void foo(int /*bar*/) {
...
}
Tell your compiler using a compiler specific nonstandard mechanism
See individual answers for __attribute__((unused)), various #pragmas and so on. Optionally, wrap a preprocesor macro around it for portability.
Switch the warning off
IDEs can signal unused variables visually (different color, or underline). Having that, compiler warning may be rather useless.
In GCC and Clang, add -Wno-unused-parameter option at the end of the command line (after all options that switch unused parameter warning on, like -Wall, -Wextra).
Add a cast to void
void foo(int bar) {
(void)bar;
}
As per jamesdlin's answer and Mailbag: Shutting up compiler warnings.
I found an article, http://sourcefrog.net/weblog/software/languages/C/unused.html, that explains UNUSED. It is interesting that the author also mangles the unused variable name, so you can't inadvertently use it in the future.
Excerpt:
#ifdef UNUSED
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#elif defined(__LCLINT__)
# define UNUSED(x) /*#unused#*/ x
#else
# define UNUSED(x) x
#endif
void dcc_mon_siginfo_handler(int UNUSED(whatsig))
If this is really what you want, you could use the unused attribute (GCC only), something like:
void foo(int __attribute__((__unused__)) bar) {
...
}
Not just for function parameters, of course, but that's the most common use case, since it might be a callback function for an API where you don't actually need all the input.
Additionally, GLib has a G_GNUC_UNUSED macro which I believe expands to that attribute.
You can silence the warning using #pragma
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused"
int unususedVariable = 1;
#pragma clang diagnostic pop
If you are using GCC, use #pragma gcc ...
#pragma unused <variable>
It's a very hackish solution, but try simply assigning the variable to itself.
I think that should fool most compilers into thinking that the variable is used. It should be quite portable too.
The cast to a void is the best approach because it shows that you didn't "accidentally" keep the variable in your code - ie: this function might be an instance where you have a table of function pointers that need the same parameter types and return types, but in this particular table entry you are not using the parameter.
That said, if you don't need it, get rid of it. ;)
Assign it to itself:
void f(int unused) {
unused = unused;
}
It works in GCC, but Clang needs -Wno-self-assign.
I think casting to void is the most portable solution: Both GCC and Clang understand this, even with full warnings -W{all,extra,pedantic}:
(void)unused;
Delete the unused variable declaration from the code (pun intended).
(What??? It's what I do: point that the obvious is most likely the best solution.)
Now, from comments on other answers, apparently it's garbage generated from macros. Well, that's a pleonasm.
Solutions:
refactor that macro to #if declare the variable only if it's really used;
create another version of the macro that skips the unused variable generation.
Better still, avoid using macros that bring issues to the code.
If it’s used and you are shipping the project, delete it. Worst, comment it.