Search code examples
c++cbisonflex-lexer

Avoiding "warning C4005: 'INT8_MIN': macro redefinition" when using flex/bison in a C++ project


I have a C++ project that is using flex/bison.

The generated code for the lexer includes the section below:

/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */

#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L

#include <inttypes.h>
typedef int8_t flex_int8_t;
// ... more typedefs here

#else

typedef signed char flex_int8_t;
// ... more typedefs here

/* Limits of integral types. */
#ifndef INT8_MIN
#define INT8_MIN               (-128)
#endif
// ... more defines here

#endif /* ! C99 */

Windows compilations warn you about all those integral types already being defined in stdint.h (e.g. Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\include\stdint.h(49,1)).

I understand this happens because C++ compilations don't set _STDC_VERSION__.

I have tried setting it as a compile flag (/D___STDC_VERSION__:199901L /D__STDC_VERSION__:199901L) but that didn't help (it would also look very dirty if it actually did work).

Is there a way to avoid those warnings? E.g. setting __STDC_VERSION__ in some other way. Or having more control over that section of flex generated code?


Solution

  • I actually ran into the same issue when working on my own Flex + Bison project.

    The problem has nothing to do with the value of __STDC_VERSION__. The warning is for macro redefinition, e.g. for INT8_MIN, etc., which you can see when looking at the source file, e.g.

    /* Limits of integral types. */
    #ifndef INT8_MIN
    #define INT8_MIN               (-128)
    #endif
    
    /* ... */
    

    These INT8_MIN, INT16_MIN, etc. macros are defined in stdint.h, so I am guessing that you are seeing this warning because your .l file has a block enclosed with %{ and }% in the definitions section with some #include directives, one of which is transitively including stdint.h.

    You can easily fix this by adding the following to your .l file's definition section:

    %top{
      #include <stdint.h>
    }
    

    This can be replaced with <cstdint> if compiling the Flex output as C++.

    The reason %top is necessary is because contents enclosed in %{ and }%, at least for Flex 2.6.4 that I am using, are copied into the generated source after the INT8_MIN, INT16_MIN, etc. macros get defined, so any #include that transitively includes stdint.h will redefine those macros, which is what MSVC is complaining about and giving you this warning for.

    In contrast, the %top block, as noted in the Flex documentation, will have its contents copied to the top of the generated source file before any Flex definitions. You need not put all your #include directives in a top block unless, e.g. for stdint.h, there is some particular need.