Search code examples
ccygwinwarningsgcc3unreachable-code

gcc reports "will never be executed" about the line: while(fgets(line, MAX_LINE, stdin) != NULL)


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.