0

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.

halfer
  • 19,824
  • 17
  • 99
  • 186
Jack
  • 16,276
  • 55
  • 159
  • 284

3 Answers3

3

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.

Keith Randall
  • 22,985
  • 2
  • 35
  • 54
  • 1
    It's rarely that gcc is wrong. It's most likely that the code snippets aren't giving the complete story. – Paul Tomblin Jul 20 '12 at 20:20
  • @PaulTomblin: I call too in main function before first while-loop: `memset(&mystruct, 0, sizeof(mystruct));`. `if(mystruct.hastab) {` is called in other function, that's called in main. `mystruct` is a global variable. I didn't posted before in because I think this information useless. It's complete story. – Jack Jul 20 '12 at 20:32
  • @PaulTomblin: Check out the update. How my `main` function works and a significant part of `proc` function. I removed only the statements inside the blocks. – Jack Jul 20 '12 at 20:38
  • 1
    Slap it in a debugger and see what `mystruct.hastab` contains on entry to `proc()`. Chances are it's not what you expect. – Paul Tomblin Jul 20 '12 at 20:40
2

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.

Keith Randall
  • 22,985
  • 2
  • 35
  • 54
1

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.

JoeFish
  • 3,009
  • 1
  • 18
  • 23