Cloak icon indicating copy to clipboard operation
Cloak copied to clipboard

Wrong evaluation of 0+number

Open r-lyeh opened this issue 6 years ago • 4 comments

Hello @pfultz2 ,

Ty for the wiki doc. Very illustrative! :)

I found that this program fails in both gcc & clang. Works ok in VS.

// ref: https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms

#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
#define IIF(c) PRIMITIVE_CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t

#define COMPL(b) PRIMITIVE_CAT(COMPL_, b)
#define COMPL_0 1
#define COMPL_1 0

#define EXPAND__( x ) x
#define CHECK_N(x, n, ...) n
#define CHECK(...) EXPAND__(CHECK_N(__VA_ARGS__, 0,))
#define PROBE(x)   x, 1,
#define NOT(x)  CHECK(EXPAND__(PRIMITIVE_CAT(NOT_, x)))
#define NOT_0   PROBE(~)
#define BOOL(x) COMPL(NOT(x))
#define IF(c)   IIF(BOOL(c))

#include <stdio.h>

int main() {
    IF(0+0)(puts("error"), puts("ok"));
    IF(0+1)(puts("ok"), puts("error"));
    IF(1+0)(puts("ok"), puts("error"));
    IF(1+1)(puts("ok"), puts("error"));
}

r-lyeh avatar Jan 29 '18 12:01 r-lyeh

Ideas?

r-lyeh avatar Jan 29 '18 12:01 r-lyeh

This is because it only checks the first token(I am not sure why it would work on MSVC):

NOT(0+0) // Expands to 1
NOT(0+1) // Expands to 1
NOT(0 1) // Expands to 1
NOT(0) // Expands to 1

You can update NOT to check for emptiness after 0, so doing NOT(0+0) will be 0:

#define PAREN() ()
#define IS_EMPTY(x) IS_PAREN(PAREN x ())

#define EAT_0
#define NOT(x) BITAND(CHECK(PRIMITIVE_CAT(NOT_, x)))(IS_EMPTY(PRIMITIVE_CAT(EAT_, x)))
#define NOT_0 PROBE(~)

So now it will result in this:

NOT(0+0) // Expands to 0
NOT(0+1) // Expands to 0
NOT(0 1) // Expands to 0
NOT(0) // Expands to 1

pfultz2 avatar Jan 29 '18 17:01 pfultz2

Hmmm I see. I was thinking about if I could exploit the preprocessor to transform a MACRO(2+1,a,b,c) into MACRO3(a,b,c) :)

r-lyeh avatar Jan 30 '18 09:01 r-lyeh

I was thinking about if I could exploit the preprocessor to transform a MACRO(2+1,a,b,c) into MACRO3(a,b,c)

Well the preprocessor cant parse symbols, so I dont think it would be possible.

pfultz2 avatar Jan 31 '18 19:01 pfultz2