diff --git a/tccpp.c b/tccpp.c index 897ef15..ad87cf0 100644 --- a/tccpp.c +++ b/tccpp.c @@ -93,6 +93,12 @@ static const unsigned char tok_two_chars[] = 0 }; +static int supported_arr[4][2] = { + SUPPORTED_ATTRIBUTES, SUPPORTED_BUILTINS, + /* We have only one profile, so __has_extension == __has_feature */ + SUPPORTED_FEATURES, SUPPORTED_FEATURES +}; + static void next_nomacro(void); ST_FUNC void skip(int c) @@ -1410,6 +1416,23 @@ ST_FUNC void free_defines(Sym *b) } } +ST_INLN int supported_check(int t, int type) +{ + int* arr = supported_arr[type]; + + if (t >= arr[0] && t <= arr[0] + arr[1]) + { + return 1; + } + return 0; +} + +ST_INLN int defined_check(int t) +{ + /* Ignore __has_include because it's a dummy implementation */ + return !!define_find(t) || (t >= TOK___HAS_ATTRIBUTE && t <= TOK___HAS_FEATURE); +} + /* label lookup */ ST_FUNC Sym *label_find(int v) { @@ -1502,7 +1525,7 @@ static int expr_preprocess(void) expect("identifier"); if (tcc_state->run_test) maybe_run_test(tcc_state); - c = define_find(tok) != 0; + c = defined_check(tok); if (t == '(') { next_nomacro(); if (tok != ')') @@ -1510,7 +1533,7 @@ static int expr_preprocess(void) } tok = TOK_CINT; tokc.i = c; - } else if (1 && tok == TOK___HAS_INCLUDE) { + } else if (tok == TOK___HAS_INCLUDE) { next(); /* XXX check if correct to use expansion */ skip('('); while (tok != ')' && tok != TOK_EOF) @@ -1519,6 +1542,18 @@ static int expr_preprocess(void) expect("')'"); tok = TOK_CINT; tokc.i = 0; + } else if (tok >= TOK___HAS_ATTRIBUTE && tok <= TOK___HAS_FEATURE) { + t = tok; + next(); + skip('('); + if (tok < TOK_IDENT) + expect("identifier"); + c = supported_check(tok, t - TOK___HAS_ATTRIBUTE); + next(); + if (tok != ')') + expect("')'"); + tok = TOK_CINT; + tokc.i = c; } else if (tok >= TOK_IDENT) { /* if undefined macro, replace with zero, check for func-like */ t = tok; @@ -1965,7 +2000,7 @@ include_done: file->ifndef_macro = tok; } } - c = (define_find(tok) != 0) ^ c; + c = defined_check(tok) ^ c; do_if: if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE) tcc_error("memory full (ifdef)"); diff --git a/tcctok.h b/tcctok.h index d4c1ef5..1b89868 100644 --- a/tcctok.h +++ b/tcctok.h @@ -93,6 +93,10 @@ DEF(TOK___FUNCTION__, "__FUNCTION__") DEF(TOK___VA_ARGS__, "__VA_ARGS__") DEF(TOK___COUNTER__, "__COUNTER__") + DEF(TOK___HAS_ATTRIBUTE, "__has_attribute") + DEF(TOK___HAS_BUILTIN, "__has_builtin") + DEF(TOK___HAS_FEATURE, "__has_feature") + DEF(TOK___HAS_EXTENSION, "__has_extension") DEF(TOK___HAS_INCLUDE, "__has_include") /* special identifiers */ @@ -109,6 +113,7 @@ /* attribute identifiers */ /* XXX: handle all tokens generically since speed is not critical */ +#define SUPPORTED_ATTRIBUTES {TOK_SECTION1, TOK_MODE} DEF(TOK_SECTION1, "section") DEF(TOK_SECTION2, "__section__") DEF(TOK_ALIGNED1, "aligned") @@ -157,6 +162,7 @@ DEF(TOK_VISIBILITY1, "visibility") DEF(TOK_VISIBILITY2, "__visibility__") +#define SUPPORTED_BUILTINS {TOK_builtin_types_compatible_p, LAST_BUILTIN} DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p") DEF(TOK_builtin_choose_expr, "__builtin_choose_expr") DEF(TOK_builtin_constant_p, "__builtin_constant_p") @@ -164,17 +170,27 @@ DEF(TOK_builtin_return_address, "__builtin_return_address") DEF(TOK_builtin_expect, "__builtin_expect") /*DEF(TOK_builtin_va_list, "__builtin_va_list")*/ +#define LAST_BUILTIN TOK_builtin_va_start #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64 DEF(TOK_builtin_va_start, "__builtin_va_start") #elif defined TCC_TARGET_X86_64 +#undef LAST_BUILTIN +#define LAST_BUILTIN TOK_builtin_va_arg_types DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types") #elif defined TCC_TARGET_ARM64 - DEF(TOK_builtin_va_start, "__builtin_va_start") DEF(TOK_builtin_va_arg, "__builtin_va_arg") + DEF(TOK_builtin_va_start, "__builtin_va_start") #elif defined TCC_TARGET_RISCV64 DEF(TOK_builtin_va_start, "__builtin_va_start") #endif +#define SUPPORTED_FEATURES {TOK_c_alignas, TOK_c_static_assert} + DEF(TOK_c_alignas, "c_alignas") + DEF(TOK_c_alignof, "c_alignof") + DEF(TOK_c_atomic, "c_atomic") + DEF(TOK_c_generic_selections, "c_generic_selections") + DEF(TOK_c_static_assert, "c_static_assert") + /* atomic operations */ #define DEF_ATOMIC(ID) DEF(TOK_##__##ID, "__"#ID) DEF_ATOMIC(atomic_store)