0

Following shows two errors generated by GCC:

 In file included from /home/omar/Desktop/Lovelace/src/main.cpp:22:
         /home/omar/Desktop/Lovelace/include/stb/stb_image.h: In function ‘void* stbi__load_gif_main(stbi__context*, int**, int*, int*,
 int*, int*, int)’:
         /home/omar/Desktop/Lovelace/include/stb/stb_image.h:6778:11: **error: variable ‘out_size’ set but not used** [-Werror=unused-but-set-variable]
          6778 |       int out_size = 0;
               |           ^~~~~~~~
         /home/omar/Desktop/Lovelace/include/stb/stb_image.h:6779:11: **error: variable ‘delays_size’ set but not used** [-Werror=unused-but-set-variable]
          6779 |       int delays_size = 0;
               |           ^~~~~~~~~~~
         cc1plus: all warnings being treated as errors
         make[2]: *** [CMakeFiles/lovelace.dir/build.make:102: CMakeFiles/lovelace.dir/src/main.cpp.o] Error 1
         make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/lovelace.dir/all] Error 2
         make: *** [Makefile:84: all] Error 2

Yet there doesn't seem to be any problem as the variables are indeed used:

  int out_size = 0;
  int delays_size = 0;
  memset(&g, 0, sizeof(g));
  if (delays) {
     *delays = 0;
  }

  do {
     u = stbi__gif_load_next(s, &g, comp, req_comp, two_back);
     if (u == (stbi_uc *) s) u = 0;  // end of animated gif marker

     if (u) {
        *x = g.w;
        *y = g.h;
        ++layers;
        stride = g.w * g.h * 4;

        if (out) {
           void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride );
           if (NULL == tmp) {
              STBI_FREE(g.out);
              STBI_FREE(g.history);
              STBI_FREE(g.background);
              return stbi__errpuc("outofmem", "Out of memory");
           }
           else {
               out = (stbi_uc*) tmp;
               out_size = layers * stride;
           }

           if (delays) {
              *delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers );
              delays_size = layers * sizeof(int);
           }
        } else {
           out = (stbi_uc*)stbi__malloc( layers * stride );
           out_size = layers * stride;
           if (delays) {
              *delays = (int*) stbi__malloc( layers * sizeof(int) );
              delays_size = layers * sizeof(int);
           }
        }      int out_size = 0;

Is this a compiler bug?

Edit: Version of GCC is 9.3.0

OS: Linux Mint latest

Clifford
  • 88,407
  • 13
  • 85
  • 165

3 Answers3

0

It seems as by using stbi__load_gif_main(...), warnings are generated. This isn't the compilers fault, nor is it yours.

I reproduced this and got the same results.

Without diving deeper in why, you could solve this by compiling without the flag -Werror.

Anyone who can fill in why the warnings are there in the first place, please do.

saffronjam
  • 59
  • 1
  • 5
0

The code initialises and modifies out_sizeand delay_size but does not use them (they are only ever written, and never read). The one place it appears to be used is the STBI_REALLOC_SIZED() calls, but STBI_REALLOC_SIZED is a macro defined thus:

#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz)

so oldsz is unused.

Compiling without -Wunused-variable (or one of the -W options that imply this) and -Werror is an unsatisfactory solution as it will suppress warnings in your own code that you might want. Had this been normal library code rather the static functions in a header (a nasty thing in itself), then you could compile the third-party code with different options that your own code. The simplest solution is to modify the stb_image.h file such that it has:

int out_size = 0; out_size = out_size ;
int delays_size = 0; delays_size = delays_size ;

or

int out_size = 0; (void)out_size ;
int delays_size = 0; (void)delays_size ;

It turns out the header already has a macro for that:

int out_size = 0; STBI_NOTUSED(out_size) ;
int delays_size = 0; STBI_NOTUSED(delays_size) ;

That will "use" the variables in a manner that has no real effect and can be optimised out (though clearly that is not a concern if you choose to use this hideous abuse of a header file). The dummy use suppresses the warning.

Ordinarily you might not want to change a header to a third-party library, but in this case the header is the library so there is no risk of inconsistency if say it weer a header for an shared object library. The change is visible to all code that uses it. The only issue is that you might have to re-implement the fix if you adopt an updated version. One solution to that is to submit a change request to the author, so the problem goes away for everyone.

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • Those two solutions are nasty but I don't want to turn off -Werror. Thanks for the answer. – saccharineboi Jan 23 '21 at 21:13
  • They are not nasty, they are idiomatic - what is nasty is the idea of a single file library in a header-file! This is the least of your worries. It has the advantage of continuing to work if the realloc macro is changed to a version that uses old-size. The macro has a `#ifndef defined STBI_REALLOC_SIZED` wrapper so it can be overridden by an external definition, so you must maintain support for the unused argument. – Clifford Jan 23 '21 at 21:19
  • I found out that someone already opened a pull request regarding this issue: https://github.com/nothings/stb/pull/1024/commits/f6523ac2a636af517060d31b5606ee3620cb49e9 But this was 5 months ago and it's still open. – saccharineboi Jan 23 '21 at 21:37
  • Good spot - that STBI_NOTUSED macro already exists, so use that. It wraps the solution I already suggested. – Clifford Jan 23 '21 at 21:47
0

Everything what @Cliffort wrote in his answer is right but (using gcc) instead of (void) which is hard to search as it will also show functions with no parameters I would use

int aUnused __attribute__((unused)); as when I see the code it is self explanatory and it is very easy to search.

(void) sometimes have some side effects like generating dead code for (void)variable if variable is volatile

https://godbolt.org/z/MrKW1d

0___________
  • 60,014
  • 4
  • 34
  • 74
  • The problem with `__attribute__((unused))` is 1) it is not portable, an the rest of tehi sfile has conditional compilation for MSC, 2) the variables concerned are initialised and I tried it and `int x = 0 __attribute__((unused)) ;` is invalid, so you would have to further change it to add an assignment after declaration. The solution is to wrap the idiomatic `(void)x ;` in a macro. It turns out that this code already has that in `STBI_NOTUSED(x)`. – Clifford Jan 23 '21 at 21:53