Cloak
Cloak copied to clipboard
Wrong evaluation of 0+number
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"));
}
Ideas?
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
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)
:)
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.