Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong evaluation of 0+number #7

Open
r-lyeh opened this issue Jan 29, 2018 · 4 comments
Open

Wrong evaluation of 0+number #7

r-lyeh opened this issue Jan 29, 2018 · 4 comments

Comments

@r-lyeh
Copy link

r-lyeh commented Jan 29, 2018

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
Copy link
Author

r-lyeh commented Jan 29, 2018

Ideas?

@pfultz2
Copy link
Owner

pfultz2 commented Jan 29, 2018

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

@r-lyeh
Copy link
Author

r-lyeh commented Jan 30, 2018

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) :)

@pfultz2
Copy link
Owner

pfultz2 commented Jan 31, 2018

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants