diff options
| -rw-r--r-- | builtin.c | 2 | ||||
| -rw-r--r-- | ident-list.h | 1 | ||||
| -rw-r--r-- | lib.c | 1 | ||||
| -rw-r--r-- | pre-process.c | 37 | ||||
| -rw-r--r-- | symbol.h | 1 | ||||
| -rw-r--r-- | validation/preprocessor/has-builtin.c | 43 |
6 files changed, 85 insertions, 0 deletions
@@ -360,6 +360,7 @@ void init_builtins(int stream) sym->ctype.base_type = ptr->base_type; sym->ctype.modifiers = ptr->modifiers; sym->op = ptr->op; + sym->builtin = 1; } } @@ -373,6 +374,7 @@ static void declare_builtin(const char *name, struct symbol *rtype, int variadic sym->ctype.base_type = fun; sym->ctype.modifiers = MOD_TOPLEVEL; + sym->builtin = 1; fun->ctype.base_type = rtype; fun->variadic = variadic; diff --git a/ident-list.h b/ident-list.h index 5394f587..a37a4a1b 100644 --- a/ident-list.h +++ b/ident-list.h @@ -59,6 +59,7 @@ IDENT_RESERVED(__label__); * sparse. */ IDENT(defined); IDENT(once); +IDENT(__has_builtin); __IDENT(pragma_ident, "__pragma__", 0); __IDENT(__VA_ARGS___ident, "__VA_ARGS__", 0); __IDENT(__func___ident, "__func__", 0); @@ -1246,6 +1246,7 @@ static void create_builtin_stream(void) assert (0); } + add_pre_buffer("#define __has_builtin(x) 0\n"); add_pre_buffer("#define __builtin_stdarg_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n"); add_pre_buffer("#define __builtin_va_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n"); add_pre_buffer("#define __builtin_ms_va_start(a,b) ((a) = (__builtin_ms_va_list)(&(b)))\n"); diff --git a/pre-process.c b/pre-process.c index b44231fd..547ce092 100644 --- a/pre-process.c +++ b/pre-process.c @@ -159,6 +159,12 @@ static void replace_with_defined(struct token *token) replace_with_bool(token, token_defined(token)); } +static void replace_with_has_builtin(struct token *token) +{ + struct symbol *sym = lookup_symbol(token->ident, NS_SYMBOL); + replace_with_bool(token, sym && sym->builtin); +} + static void expand_line(struct token *token) { replace_with_integer(token, token->pos.line); @@ -1541,6 +1547,10 @@ static int expression_value(struct token **where) state = 1; beginning = list; break; + } else if (p->ident == &__has_builtin_ident) { + state = 4; + beginning = list; + break; } if (!expand_one_symbol(list)) continue; @@ -1571,6 +1581,33 @@ static int expression_value(struct token **where) sparse_error(p->pos, "missing ')' after \"defined\""); *list = p->next; continue; + + // __has_builtin(xyz) + case 4: + if (match_op(p, '(')) { + state = 5; + } else { + sparse_error(p->pos, "missing '(' after \"__has_builtin\""); + state = 0; + } + *beginning = p; + break; + case 5: + if (token_type(p) != TOKEN_IDENT) { + sparse_error(p->pos, "identifier expected"); + state = 0; + break; + } + if (!match_op(p->next, ')')) + sparse_error(p->pos, "missing ')' after \"__has_builtin\""); + state = 6; + replace_with_has_builtin(p); + *beginning = p; + break; + case 6: + state = 0; + *list = p->next; + continue; } list = &p->next; } @@ -174,6 +174,7 @@ struct symbol { designated_init:1, forced_arg:1, accessed:1, + builtin:1, transparent_union:1; struct expression *array_size; struct ctype ctype; diff --git a/validation/preprocessor/has-builtin.c b/validation/preprocessor/has-builtin.c new file mode 100644 index 00000000..03272fc9 --- /dev/null +++ b/validation/preprocessor/has-builtin.c @@ -0,0 +1,43 @@ +#ifndef __has_builtin +__has_builtin()??? Quesako? +#define __has_builtin(x) 0 +#else +"has __has_builtin(), yeah!" +#endif + +#if __has_builtin(nothing) +#error "not a builtin!" +#endif + +#if __has_builtin(__builtin_offsetof) \ + || __has_builtin(__builtin_types_compatible_p) +#error "builtin ops are not builtin functions!" +#endif + +#if __has_builtin(__builtin_va_list) \ + || __has_builtin(__builtin_ms_va_list) +#error "builtin types are not builtin functions!" +#endif + +#if __has_builtin(__builtin_abs) +abs +#endif + +#if __has_builtin(__builtin_constant_p) +constant_p +#endif + +123 __has_builtin(abc) def + +/* + * check-name: has-builtin + * check-command: sparse -E $file + * + * check-output-start + +"has __has_builtin(), yeah!" +abs +constant_p +123 0 def + * check-output-end + */ |
