gcc reports “will never be executed” about the line: while(fgets(line, MAX_LINE, stdin) != NULL)
-
22-06-2021 - |
Question
I'm looking for an explanation why gcc
are giving this warning for me.
I'm compiling with the gcc-3
on cygwin
with the -Wunreachable-code
flag, and the gcc says this warning for me:
main.c:223: warning: will never be executed
That's this line: while(fgets(line, MAX_LINE, stdin) != NULL) {
This code is inside a if(exp) { }
block where exp
is dynamically set according to command-line-arguments(parsed by getopt()
), look at the code part:
if(mystruct.hastab) {
the default value is 0
. But it's become 1
if -t
flag is passed to application, as you can see at following:
struct mystruct_t {
//...
int hastab;
} mystruct;
int main(int argc, char *argv[])
{
int opt;
memset(&mystruct, 0, sizeof(mystruct));
while((opt = getopt(argc, argv, optString)) != -1) {
switch(opt) {
case 't':
mystruct.hastab = 1;
break;
//....
}
}
proc();
return 0;
}
void
proc(void)
{
char *buf, *tmpbuf, line[MAX_LINE + 1], *p, *fullfilename;
if(mystruct.hastab) {
while(fgets(line, MAX_LINE, stdin) != NULL) {
//...
}
} else {
//...
}
}
So, there's a reason for the code be executed. As happens.
Solution
Here's another possibility: the problem is with macros. Here's a simple example that demonstrates your error:
#include <string.h>
int s;
int main(int argc, char *argv[]) {
memset(&s, 0, sizeof(s));
}
When I compile this, I get:
$ gcc -Wunreachable-code tmp.c
tmp.c: In function ‘main’:
tmp.c:4: warning: will never be executed
The error is not particularly enlightening. However, if you run the preprocessor, look what memset
expands to:
$ gcc -E tmp.c
...
int s;
int main(int argc, char *argv[]) {
((__builtin_object_size (&s, 0) != (size_t) -1) ? __builtin___memset_chk (&s, 0, sizeof(s), __builtin_object_size (&s, 0)) : __inline_memset_chk (&s, 0, sizeof(s)));
}
I suspect because of the constant size of s
, only one of the branches of the ?:
is ever executed, and this is what gcc is complaining about. In your case, it's probably that fgets
is a macro. Run gcc -E
, find your problem line in the output, and see if it's wonky (mine isn't, but I'm not running cygwin).
Moral of the story: preprocessors & macros suck.
OTHER TIPS
Sounds like gcc is convinced hastab
is never set, or that it is only set after the code it's warning about. It certainly seems like gcc is wrong, but since you only gave us snippets it is hard to be sure. I don't think anyone can help you further unless we see a complete program we can compile ourselves.
If I had to guess I'd say gcc is considering that there are 2 cases where you can call proc()
without having set mystruct.hastab
to something other than 0
.
The first case is if this evaulates to false
on the first run through, since you will drop out of the loop without executing your switch
statement:
while((opt = getopt(argc, argv, optString)) != -1) {
The second case is if opt
is never 't'
:
switch(opt) {
case 't':
mystruct.hastab = 1;
So you will fall out of the loop without ever having set mystruct.hastab
to a non-zero value.