8

The following C++ example fails to compile with gcc or clang, but only generates a warning with ICC, and nothing at all with MSVC:

int main(int argc, char *argv[])
{
    if (argc < 2)
        goto clean_up;

#if 1   // FAIL
    int i = 0;
#elif 0 // workaround - OK
    {
        int i = 0;
    }
#else   // workaround - OK
    int i;
    i = 0;
#endif

clean_up:
    return 0;
}

g++:

init.cpp:13: error: jump to label ‘clean_up’
init.cpp:4: error:   from here
init.cpp:7: error:   crosses initialization of ‘int i’

clang++:

init.cpp:4:9: error: cannot jump from this goto statement to its label
        goto clean_up;
        ^
init.cpp:7:9: note: jump bypasses variable initialization
    int i = 0;
        ^

ICC:

init.cpp(4): warning #589: transfer of control bypasses initialization of:
            variable "i" (declared at line 7)
          goto clean_up;
          ^

I understand the cause of the error, and for a simple example such as this it is fairly easy to work around (I've included a couple of possible workarounds in the example above), but I'm working on a large cross-platform legacy code base that is peppered with error-handling macros which use a similar goto construct. Other developers working with MSVC or ICC keep introducing inline initialisations which subsequently result in errors for gcc or clang builds (and of course they just ignore the warnings they get with MSVC/ICC).

So I need to find a way to either (a) make such cases result in errors on ICC/MSVC or (b) reduce them to warnings with gcc/clang. I tried -fpermissive with gcc but that doesn't seem to help.


For extra credit I'm also curious as to the rationale behind this error for simple scalar initialisation - I can see why jumping over a constructor might be problematic, but initialising an int as in the above example doesn't seem like it could ever be an issue, and simply splitting the definition+initialisation into a definition + assignment makes the error go away?
Paul R
  • 208,748
  • 37
  • 389
  • 560
  • In C, this is allowed (although frowned upon). Not sure about C++. – Bathsheba Jul 20 '15 at 10:13
  • 1
    Developers should fix their compiler warnings too, not only errors. – Melebius Jul 20 '15 at 10:15
  • @Bathsheba: yes, these legacy macros come originally from a C code base, but now C++ code is being increasingly used and I keep having to fix each new occurrence of this problem. – Paul R Jul 20 '15 at 10:15
  • 1
    @Melebius: I know - I've been banging this particular drum for some time, but it seems it would need a cultural shift of seismic proportions to get everyone on board with this. – Paul R Jul 20 '15 at 10:16
  • This might help. http://stackoverflow.com/questions/14274225/statement-goto-can-not-cross-pointer-definition – Bathsheba Jul 20 '15 at 10:18
  • 1
    If you surround the definition with braces `{ int i = 0 }` it will compile okay but that is not a solution I guess? You need to know only which compiler flags can make it build? – VP. Jul 20 '15 at 10:19
  • (a) is definitely the way to go in my opinion. I would use `#pragma warning(error: xxxx)` (or the equivalent command line option) for MSVC, and I suppose there are similar options for ICC. – bogdan Jul 20 '15 at 10:21
  • 1
    @VictorPolevoy: yes, as I mentioned above, it's fairly easy to fix for a simple example like this, but for a large code base with many similar occurrences of the above then it becomes a recurring problem that I'm looking to find a permanent solution for, rather than keep working around it. – Paul R Jul 20 '15 at 10:23
  • @bogdan: yes, you're probably right - it's a fairly large code base, so ideally I need command line switches that I can add to our makefile(s) - I guess I need to do more research to see if ICC/MSVC have suitable switches. – Paul R Jul 20 '15 at 10:25
  • 1
    @PaulR `/we` does it for MSVC. https://msdn.microsoft.com/en-us/library/thxezb7y.aspx – Melebius Jul 20 '15 at 10:28
  • @Melebius: thanks - that's helpful - feel free to post that as an answer and get an up-vote from me. ;-) – Paul R Jul 20 '15 at 10:31
  • 1
    @PaulR [C4533](https://msdn.microsoft.com/en-us/library/f7687yks%28v=vs.120%29.aspx) is a relevant warning for MSVC, but it's only triggered when class types are involved. – bogdan Jul 20 '15 at 11:20

1 Answers1

2

The MSVC flag for treating a warning as en error is /we n where n is the number of the warning.

For example, /we4326 flags warning number C4326 as an error.

See https://msdn.microsoft.com/en-us/library/thxezb7y.aspx for details.

Melebius
  • 6,183
  • 4
  • 39
  • 52
  • Close - it looks like `C2362` would be the appropriate warning/error, but `cl` doesn't generate this unless you use `/Za` it seems, in which case it's an error anyway. Using `/Za` is not an option unfortunately, as it breaks lots of other things. Hmmm... – Paul R Jul 20 '15 at 11:02
  • `/Za` seems to disable the Microsoft extensions of C++ standard. https://msdn.microsoft.com/en-us/library/0k0w269d.aspx You have to decide whether to use Microsoft extensions, or compile with GCC… – Melebius Jul 20 '15 at 11:27
  • Yes, unfortunately `/Za` breaks a lot of our existing code (code which compiles OK with all other compilers), so it's not an option. This is one of the big headaches with legacy code bases - you can't "just fix" things. – Paul R Jul 20 '15 at 11:32