Search code examples
cvisual-c++macroslabelredefinition

Labels redefined in Macro in C


Trying to use goto labels in a C macro (running MSVC) but if the macro is called multiple times in the same caller function, C2045 label redefined errors appear.

I've tried using __label__ from this example: https://www.geeksforgeeks.org/local-labels-in-c/ but that label keyword is probably gcc only because MSVC reports label undefined.

I understand it's really obfuscated and silly but I'm writing a transpiler to convert MASM code into C. In MASM, labels are defined locally using the LOCAL directive, __label__ is used by GCC, but what does MSVC offer as a solution?

#include <stdint.h>
#include <stdio.h>

#define     Loopy(AA) {              \
   RTSZ_0:;                          \
   if (AA >= 5) { goto RTSZ_1; }     \
   AA += 1;                          \
   goto RTSZ_0;                      \
   RTSZ_1:;                          \
}                               

int main()
{
    int AA = 0;

    Loopy(AA);
    Loopy(AA);

    return 0;
}

I was expecting the goto labels to be assigned a unique label so that when included multiple times, there would be no redefinition errors.

Is there a C keyword that can be applied to the macro or a workaround? Something like:

            __Uniquelabel__       RTSZ_0; \
            __Uniquelabel__       RTSZ_1; \

Any ideas? Thanks!


Solution

  • currently looking into using this code:

    #define S1(x) #x
    #define S2(x) S1(x)
    #define RTSZ "RTSZ_" S2(__LINE__) ":"
    

    Indeed something along the above lines can be used to generate unique labels, as long as there's not more than one macro invocation per source line:

    #define RTSZ(i) RTSZ1(i, __LINE__)
    #define RTSZ1(i, l) RTSZ2(i, l)
    #define RTSZ2(i, l) RTSZ_##i##_##l
    
    #define     Loopy(AA) {              \
       RTSZ(0):                          \
       if (AA >= 5) { goto RTSZ(1); }    \
       AA += 1;                          \
       goto RTSZ(0);                     \
       RTSZ(1): ;                        \
    }
    

    The intermediate RTSZ1() macro serves to expand the __LINE__ macro, similar to the S2() in your approach.