error: jump to label 'foo' crosses initial

2019-04-29 01:19发布

问题:

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?

回答1:

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.