diff options
| -rw-r--r-- | Documentation/api.rst | 1 | ||||
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | builtin.c | 100 | ||||
| -rw-r--r-- | ident-list.h | 6 | ||||
| -rw-r--r-- | lib.c | 183 | ||||
| -rw-r--r-- | lib.h | 4 | ||||
| -rw-r--r-- | pre-process.c | 255 | ||||
| -rw-r--r-- | symbol.c | 9 | ||||
| -rw-r--r-- | symbol.h | 5 | ||||
| -rw-r--r-- | tokenize.c | 9 | ||||
| -rw-r--r-- | utils.c | 17 | ||||
| -rw-r--r-- | utils.h | 25 | ||||
| -rw-r--r-- | validation/builtin-overflow.c | 246 | ||||
| -rw-r--r-- | validation/preprocessor/base-file.c | 17 | ||||
| -rw-r--r-- | validation/preprocessor/base-file.h | 2 | ||||
| -rw-r--r-- | validation/preprocessor/builtin.c | 17 | ||||
| -rw-r--r-- | validation/preprocessor/dynamic.c | 37 | ||||
| -rw-r--r-- | validation/preprocessor/has-builtin.c | 43 | ||||
| -rw-r--r-- | validation/preprocessor/include-level.c | 14 | ||||
| -rw-r--r-- | validation/preprocessor/include-level.h | 1 |
20 files changed, 820 insertions, 172 deletions
diff --git a/Documentation/api.rst b/Documentation/api.rst index d1a1d3ca..1270551c 100644 --- a/Documentation/api.rst +++ b/Documentation/api.rst @@ -9,6 +9,7 @@ Utilities ~~~~~~~~~ .. c:autodoc:: ptrlist.c +.. c:autodoc:: utils.h Parsing ~~~~~~~ @@ -61,6 +61,7 @@ LIB_OBJS += symbol.o LIB_OBJS += target.o LIB_OBJS += tokenize.o LIB_OBJS += unssa.o +LIB_OBJS += utils.o PROGRAMS := PROGRAMS += compile @@ -82,7 +82,7 @@ error: return 0; } -static int arguments_choose(struct expression *expr) +static int args_triadic(struct expression *expr) { return eval_args(expr, 3); } @@ -195,8 +195,8 @@ static struct symbol_op expect_op = { }; static struct symbol_op choose_op = { + .args = args_triadic, .evaluate = evaluate_choose, - .args = arguments_choose, }; /* The argument is constant and valid if the cost is zero */ @@ -251,6 +251,71 @@ static struct symbol_op fp_unop_op = { }; +static int evaluate_overflow_gen(struct expression *expr, int ptr) +{ + struct expression *arg; + int n = 0; + + /* there will be exactly 3; we'd already verified that */ + FOR_EACH_PTR(expr->args, arg) { + struct symbol *type; + + n++; + if (!arg || !(type = arg->ctype)) + return 0; + // 1st & 2nd args must be a basic integer type + // 3rd arg must be a pointer to such a type. + if (n == 3 && ptr) { + if (type->type == SYM_NODE) + type = type->ctype.base_type; + if (!type) + return 0; + if (type->type != SYM_PTR) + goto err; + type = type->ctype.base_type; + if (!type) + return 0; + } + if (type->type == SYM_NODE) + type = type->ctype.base_type; + if (!type) + return 0; + if (type->ctype.base_type != &int_type || type == &bool_ctype) + goto err; + } END_FOR_EACH_PTR(arg); + + // the builtin returns a bool + expr->ctype = &bool_ctype; + return 1; + +err: + sparse_error(arg->pos, "invalid type for argument %d:", n); + info(arg->pos, " %s", show_typename(arg->ctype)); + expr->ctype = &bad_ctype; + return 0; +} + +static int evaluate_overflow(struct expression *expr) +{ + return evaluate_overflow_gen(expr, 1); +} + +static struct symbol_op overflow_op = { + .args = args_triadic, + .evaluate = evaluate_overflow, +}; + +static int evaluate_overflow_p(struct expression *expr) +{ + return evaluate_overflow_gen(expr, 0); +} + +static struct symbol_op overflow_p_op = { + .args = args_triadic, + .evaluate = evaluate_overflow_p, +}; + + /* * Builtin functions */ @@ -275,6 +340,12 @@ static struct sym_init { { "__builtin_isnan", &builtin_fn_type, MOD_TOPLEVEL, &fp_unop_op }, { "__builtin_isnormal", &builtin_fn_type, MOD_TOPLEVEL, &fp_unop_op }, { "__builtin_signbit", &builtin_fn_type, MOD_TOPLEVEL, &fp_unop_op }, + { "__builtin_add_overflow", &builtin_fn_type, MOD_TOPLEVEL, &overflow_op }, + { "__builtin_sub_overflow", &builtin_fn_type, MOD_TOPLEVEL, &overflow_op }, + { "__builtin_mul_overflow", &builtin_fn_type, MOD_TOPLEVEL, &overflow_op }, + { "__builtin_add_overflow_p", &builtin_fn_type, MOD_TOPLEVEL, &overflow_p_op }, + { "__builtin_sub_overflow_p", &builtin_fn_type, MOD_TOPLEVEL, &overflow_p_op }, + { "__builtin_mul_overflow_p", &builtin_fn_type, MOD_TOPLEVEL, &overflow_p_op }, { NULL, NULL, 0 } }; @@ -289,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; } } @@ -302,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; @@ -397,9 +470,18 @@ void declare_builtins(void) declare_builtin("__builtin_realloc", &ptr_ctype, 0, &ptr_ctype, size_t_ctype, NULL); declare_builtin("__builtin_return_address", &ptr_ctype, 0, &uint_ctype, NULL); declare_builtin("__builtin_rindex", &string_ctype, 0, &const_string_ctype, &int_ctype, NULL); + declare_builtin("__builtin_sadd_overflow", &bool_ctype, 0, &int_ctype, &int_ctype, &int_ptr_ctype, NULL); + declare_builtin("__builtin_saddl_overflow", &bool_ctype, 0, &long_ctype, &long_ctype, &long_ptr_ctype, NULL); + declare_builtin("__builtin_saddll_overflow", &bool_ctype, 0, &llong_ctype, &llong_ctype, &llong_ptr_ctype, NULL); declare_builtin("__builtin_signbit", &int_ctype, 1, NULL); + declare_builtin("__builtin_smul_overflow", &bool_ctype, 0, &int_ctype, &int_ctype, &int_ptr_ctype, NULL); + declare_builtin("__builtin_smull_overflow", &bool_ctype, 0, &long_ctype, &long_ctype, &long_ptr_ctype, NULL); + declare_builtin("__builtin_smulll_overflow", &bool_ctype, 0, &llong_ctype, &llong_ctype, &llong_ptr_ctype, NULL); declare_builtin("__builtin_snprintf", &int_ctype, 1, &string_ctype, size_t_ctype, &const_string_ctype, NULL); declare_builtin("__builtin_sprintf", &int_ctype, 1, &string_ctype, &const_string_ctype, NULL); + declare_builtin("__builtin_ssub_overflow", &bool_ctype, 0, &int_ctype, &int_ctype, &int_ptr_ctype, NULL); + declare_builtin("__builtin_ssubl_overflow", &bool_ctype, 0, &long_ctype, &long_ctype, &long_ptr_ctype, NULL); + declare_builtin("__builtin_ssubll_overflow", &bool_ctype, 0, &llong_ctype, &llong_ctype, &llong_ptr_ctype, NULL); declare_builtin("__builtin_stpcpy", &string_ctype, 0, &const_string_ctype, &const_string_ctype, NULL); declare_builtin("__builtin_stpncpy", &string_ctype, 0, &const_string_ctype, &const_string_ctype, size_t_ctype, NULL); declare_builtin("__builtin_strcasecmp", &int_ctype, 0, &const_string_ctype, &const_string_ctype, NULL); @@ -422,7 +504,16 @@ void declare_builtins(void) declare_builtin("__builtin_strspn", size_t_ctype, 0, &const_string_ctype, &const_string_ctype, NULL); declare_builtin("__builtin_strstr", &string_ctype, 0, &const_string_ctype, &const_string_ctype, NULL); declare_builtin("__builtin_trap", &void_ctype, 0, NULL); + declare_builtin("__builtin_uadd_overflow", &bool_ctype, 0, &uint_ctype, &uint_ctype, &uint_ptr_ctype, NULL); + declare_builtin("__builtin_uaddl_overflow", &bool_ctype, 0, &ulong_ctype, &ulong_ctype, &ulong_ptr_ctype, NULL); + declare_builtin("__builtin_uaddll_overflow", &bool_ctype, 0, &ullong_ctype, &ullong_ctype, &ullong_ptr_ctype, NULL); + declare_builtin("__builtin_umul_overflow", &bool_ctype, 0, &uint_ctype, &uint_ctype, &uint_ptr_ctype, NULL); + declare_builtin("__builtin_umull_overflow", &bool_ctype, 0, &ulong_ctype, &ulong_ctype, &ulong_ptr_ctype, NULL); + declare_builtin("__builtin_umulll_overflow", &bool_ctype, 0, &ullong_ctype, &ullong_ctype, &ullong_ptr_ctype, NULL); declare_builtin("__builtin_unreachable", &void_ctype, 0, NULL); + declare_builtin("__builtin_usub_overflow", &bool_ctype, 0, &uint_ctype, &uint_ctype, &uint_ptr_ctype, NULL); + declare_builtin("__builtin_usubl_overflow", &bool_ctype, 0, &ulong_ctype, &ulong_ctype, &ulong_ptr_ctype, NULL); + declare_builtin("__builtin_usubll_overflow", &bool_ctype, 0, &ullong_ctype, &ullong_ctype, &ullong_ptr_ctype, NULL); declare_builtin("__builtin_va_arg_pack_len", size_t_ctype, 0, NULL); declare_builtin("__builtin_vprintf", &int_ctype, 0, &const_string_ctype, va_list_ctype, NULL); declare_builtin("__builtin_vsnprintf", &int_ctype, 0, &string_ctype, size_t_ctype, &const_string_ctype, va_list_ctype, NULL); @@ -459,4 +550,9 @@ void declare_builtins(void) declare_builtin("__sync_synchronize", &void_ctype, 0, NULL); declare_builtin("__sync_val_compare_and_swap", &int_ctype, 1, &ptr_ctype, NULL); declare_builtin("__sync_xor_and_fetch", &int_ctype, 1, &ptr_ctype, NULL); + + // Blackfin-specific stuff + declare_builtin("__builtin_bfin_csync", &void_ctype, 0, NULL); + declare_builtin("__builtin_bfin_ssync", &void_ctype, 0, NULL); + declare_builtin("__builtin_bfin_norm_fr1x32", &int_ctype, 0, &int_ctype, NULL); } diff --git a/ident-list.h b/ident-list.h index 2f1fecb4..a37a4a1b 100644 --- a/ident-list.h +++ b/ident-list.h @@ -59,16 +59,12 @@ IDENT_RESERVED(__label__); * sparse. */ IDENT(defined); IDENT(once); +IDENT(__has_builtin); __IDENT(pragma_ident, "__pragma__", 0); __IDENT(__VA_ARGS___ident, "__VA_ARGS__", 0); -__IDENT(__LINE___ident, "__LINE__", 0); -__IDENT(__FILE___ident, "__FILE__", 0); -__IDENT(__DATE___ident, "__DATE__", 0); -__IDENT(__TIME___ident, "__TIME__", 0); __IDENT(__func___ident, "__func__", 0); __IDENT(__FUNCTION___ident, "__FUNCTION__", 0); __IDENT(__PRETTY_FUNCTION___ident, "__PRETTY_FUNCTION__", 0); -__IDENT(__COUNTER___ident, "__COUNTER__", 0); /* Sparse commands */ IDENT_RESERVED(__context__); @@ -60,6 +60,8 @@ int gcc_major = __GNUC__; int gcc_minor = __GNUC_MINOR__; int gcc_patchlevel = __GNUC_PATCHLEVEL__; +const char *base_filename; + static const char *gcc_base_dir = GCC_BASE; static const char *multiarch_dir = MULTIARCH_TRIPLET; @@ -475,8 +477,8 @@ static void handle_arch_m64_finalize(void) switch (arch_m64) { case ARCH_X32: max_int_alignment = 8; - add_pre_buffer("#weak_define __ILP32__ 1\n"); - add_pre_buffer("#weak_define _ILP32 1\n"); + predefine("__ILP32__", 1, "1"); + predefine("_ILP32", 1, "1"); goto case_x86_64; case ARCH_LP32: /* default values */ @@ -486,15 +488,15 @@ static void handle_arch_m64_finalize(void) max_int_alignment = 8; size_t_ctype = &ulong_ctype; ssize_t_ctype = &long_ctype; - add_pre_buffer("#weak_define __LP64__ 1\n"); - add_pre_buffer("#weak_define _LP64 1\n"); + predefine("__LP64__", 1, "1"); + predefine("_LP64", 1, "1"); goto case_64bit_common; case ARCH_LLP64: bits_in_long = 32; max_int_alignment = 8; size_t_ctype = &ullong_ctype; ssize_t_ctype = &llong_ctype; - add_pre_buffer("#weak_define __LLP64__ 1\n"); + predefine("__LLP64__", 1, "1"); goto case_64bit_common; case_64bit_common: bits_in_pointer = 64; @@ -502,8 +504,8 @@ static void handle_arch_m64_finalize(void) /* fall through */ case_x86_64: #if defined(__x86_64__) || defined(__x86_64) - add_pre_buffer("#weak_define __x86_64__ 1\n"); - add_pre_buffer("#weak_define __x86_64 1\n"); + predefine("__x86_64__", 1, "1"); + predefine("__x86_64", 1, "1"); #endif break; } @@ -1109,14 +1111,19 @@ static char **handle_switch(char *arg, char **next) static void predefined_sizeof(const char *name, unsigned bits) { - add_pre_buffer("#weak_define __SIZEOF_%s__ %d\n", name, bits/8); + char buf[32]; + + snprintf(buf, sizeof(buf), "__SIZEOF_%s__", name); + predefine(buf, 1, "%d", bits/8); } static void predefined_max(const char *name, const char *suffix, unsigned bits) { unsigned long long max = (1ULL << (bits - 1 )) - 1; + char buf[32]; - add_pre_buffer("#weak_define __%s_MAX__ %#llx%s\n", name, max, suffix); + snprintf(buf, sizeof(buf), "__%s_MAX__", name); + predefine(buf, 1, "%#llx%s", max, suffix); } static void predefined_type_size(const char *name, const char *suffix, unsigned bits) @@ -1127,13 +1134,50 @@ static void predefined_type_size(const char *name, const char *suffix, unsigned static void predefined_macros(void) { - add_pre_buffer("#define __CHECKER__ 1\n"); + predefine("__CHECKER__", 0, "1"); + predefine("__GNUC__", 1, "%d", gcc_major); + predefine("__GNUC_MINOR__", 1, "%d", gcc_minor); + predefine("__GNUC_PATCHLEVEL__", 1, "%d", gcc_patchlevel); + + predefine("__STDC__", 1, "1"); + switch (standard) { + case STANDARD_C89: + predefine("__STRICT_ANSI__", 1, "1"); + break; + + case STANDARD_C94: + predefine("__STDC_VERSION__", 1, "199409L"); + predefine("__STRICT_ANSI__", 1, "1"); + break; + + case STANDARD_C99: + predefine("__STDC_VERSION__", 1, "199901L"); + predefine("__STRICT_ANSI__", 1, "1"); + break; + + case STANDARD_GNU89: + default: + break; + + case STANDARD_GNU99: + predefine("__STDC_VERSION__", 1, "199901L"); + break; + + case STANDARD_C11: + predefine("__STRICT_ANSI__", 1, "1"); + case STANDARD_GNU11: + predefine("__STDC_NO_ATOMICS__", 1, "1"); + predefine("__STDC_NO_COMPLEX__", 1, "1"); + predefine("__STDC_NO_THREADS__", 1, "1"); + predefine("__STDC_VERSION__", 1, "201112L"); + break; + } predefined_sizeof("SHORT", bits_in_short); predefined_max("SHRT", "", bits_in_short); predefined_max("SCHAR", "", bits_in_char); predefined_max("WCHAR", "", bits_in_wchar); - add_pre_buffer("#weak_define __CHAR_BIT__ %d\n", bits_in_char); + predefine("__CHAR_BIT__", 1, "%d", bits_in_char); predefined_type_size("INT", "", bits_in_int); predefined_type_size("LONG", "L", bits_in_long); @@ -1149,52 +1193,30 @@ static void predefined_macros(void) predefined_sizeof("DOUBLE", bits_in_double); predefined_sizeof("LONG_DOUBLE", bits_in_longdouble); - add_pre_buffer("#weak_define __%s_ENDIAN__ 1\n", - arch_big_endian ? "BIG" : "LITTLE"); - - add_pre_buffer("#weak_define __ORDER_LITTLE_ENDIAN__ 1234\n"); - add_pre_buffer("#weak_define __ORDER_BIG_ENDIAN__ 4321\n"); - add_pre_buffer("#weak_define __ORDER_PDP_ENDIAN__ 3412\n"); - add_pre_buffer("#weak_define __BYTE_ORDER__ __ORDER_%s_ENDIAN__\n", - arch_big_endian ? "BIG" : "LITTLE"); -} + predefine("__ORDER_LITTLE_ENDIAN__", 1, "1234"); + predefine("__ORDER_BIG_ENDIAN__", 1, "4321"); + predefine("__ORDER_PDP_ENDIAN__", 1, "3412"); + if (arch_big_endian) { + predefine("__BIG_ENDIAN__", 1, "1"); + predefine("__BYTE_ORDER__", 1, "__ORDER_BIG_ENDIAN__"); + } else { + predefine("__LITTLE_ENDIAN__", 1, "1"); + predefine("__BYTE_ORDER__", 1, "__ORDER_LITTLE_ENDIAN__"); + } -static void declare_builtin_functions(void) -{ - /* Note: - * Most builtin functions are declared in builtin.c:declare_builtins(). - * Some are also defined in builtin:init_builtins(). - */ + if (optimize_level) + predefine("__OPTIMIZE__", 0, "1"); + if (optimize_size) + predefine("__OPTIMIZE_SIZE__", 0, "1"); - /* Add Blackfin-specific stuff */ - add_pre_buffer( - "#ifdef __bfin__\n" - "extern void __builtin_bfin_csync(void);\n" - "extern void __builtin_bfin_ssync(void);\n" - "extern int __builtin_bfin_norm_fr1x32(int);\n" - "#endif\n" - ); + // Temporary hacks + predefine("__extension__", 0, NULL); + predefine("__pragma__", 0, NULL); } static void create_builtin_stream(void) { - add_pre_buffer("#weak_define __GNUC__ %d\n", gcc_major); - add_pre_buffer("#weak_define __GNUC_MINOR__ %d\n", gcc_minor); - add_pre_buffer("#weak_define __GNUC_PATCHLEVEL__ %d\n", gcc_patchlevel); - - /* add the multiarch include directories, if any */ - if (multiarch_dir && *multiarch_dir) { - add_pre_buffer("#add_system \"/usr/include/%s\"\n", multiarch_dir); - add_pre_buffer("#add_system \"/usr/local/include/%s\"\n", multiarch_dir); - } - - /* We add compiler headers path here because we have to parse - * the arguments to get it, falling back to default. */ - add_pre_buffer("#add_system \"%s/include\"\n", gcc_base_dir); - add_pre_buffer("#add_system \"%s/include-fixed\"\n", gcc_base_dir); - - add_pre_buffer("#define __extension__\n"); - add_pre_buffer("#define __pragma__\n"); + // Temporary hack add_pre_buffer("#define _Pragma(x)\n"); // gcc defines __SIZE_TYPE__ to be size_t. For linux/i86 and @@ -1206,44 +1228,20 @@ static void create_builtin_stream(void) add_pre_buffer("#weak_define __SIZE_TYPE__ long unsigned int\n"); else add_pre_buffer("#weak_define __SIZE_TYPE__ unsigned int\n"); - add_pre_buffer("#weak_define __STDC__ 1\n"); - - switch (standard) - { - case STANDARD_C89: - add_pre_buffer("#weak_define __STRICT_ANSI__\n"); - break; - - case STANDARD_C94: - add_pre_buffer("#weak_define __STDC_VERSION__ 199409L\n"); - add_pre_buffer("#weak_define __STRICT_ANSI__\n"); - break; - case STANDARD_C99: - add_pre_buffer("#weak_define __STDC_VERSION__ 199901L\n"); - add_pre_buffer("#weak_define __STRICT_ANSI__\n"); - break; - - case STANDARD_GNU89: - break; - - case STANDARD_GNU99: - add_pre_buffer("#weak_define __STDC_VERSION__ 199901L\n"); - break; - - case STANDARD_C11: - add_pre_buffer("#weak_define __STRICT_ANSI__ 1\n"); - case STANDARD_GNU11: - add_pre_buffer("#weak_define __STDC_NO_ATOMICS__ 1\n"); - add_pre_buffer("#weak_define __STDC_NO_COMPLEX__ 1\n"); - add_pre_buffer("#weak_define __STDC_NO_THREADS__ 1\n"); - add_pre_buffer("#weak_define __STDC_VERSION__ 201112L\n"); - break; - default: - assert (0); + /* add the multiarch include directories, if any */ + if (multiarch_dir && *multiarch_dir) { + add_pre_buffer("#add_system \"/usr/include/%s\"\n", multiarch_dir); + add_pre_buffer("#add_system \"/usr/local/include/%s\"\n", multiarch_dir); } + /* We add compiler headers path here because we have to parse + * the arguments to get it, falling back to default. */ + add_pre_buffer("#add_system \"%s/include\"\n", gcc_base_dir); + add_pre_buffer("#add_system \"%s/include-fixed\"\n", gcc_base_dir); + + 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"); @@ -1255,14 +1253,6 @@ static void create_builtin_stream(void) add_pre_buffer("#define __builtin_va_end(arg)\n"); add_pre_buffer("#define __builtin_ms_va_end(arg)\n"); add_pre_buffer("#define __builtin_va_arg_pack()\n"); - - /* FIXME! We need to do these as special magic macros at expansion time! */ - add_pre_buffer("#define __BASE_FILE__ \"base_file.c\"\n"); - - if (optimize_level) - add_pre_buffer("#define __OPTIMIZE__ 1\n"); - if (optimize_size) - add_pre_buffer("#define __OPTIMIZE_SIZE__ 1\n"); } static struct symbol_list *sparse_tokenstream(struct token *token) @@ -1314,6 +1304,7 @@ static struct symbol_list *sparse_file(const char *filename) if (fd < 0) die("No such file: %s", filename); } + base_filename = filename; // Tokenize the input stream token = tokenize(filename, fd, NULL, includepath); @@ -1375,11 +1366,9 @@ struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list // Initialize type system init_ctype(); - declare_builtins(); - create_builtin_stream(); predefined_macros(); - if (!preprocess_only) - declare_builtin_functions(); + create_builtin_stream(); + declare_builtins(); list = sparse_initial(); @@ -33,6 +33,7 @@ #include "compat.h" #include "ptrlist.h" +#include "utils.h" #define DO_STRINGIFY(x) #x #define STRINGIFY(x) DO_STRINGIFY(x) @@ -46,6 +47,8 @@ extern int die_if_error; extern int repeat_phase; extern int gcc_major, gcc_minor, gcc_patchlevel; +extern const char *base_filename; + extern unsigned int hexval(unsigned int c); struct position { @@ -127,6 +130,7 @@ enum phase { extern void add_pre_buffer(const char *fmt, ...) FORMAT_ATTR(1); +extern void predefine(const char *name, int weak, const char *fmt, ...) FORMAT_ATTR(3); extern int preprocess_only; diff --git a/pre-process.c b/pre-process.c index 7d335ab0..da4b7acd 100644 --- a/pre-process.c +++ b/pre-process.c @@ -47,6 +47,7 @@ static struct ident_list *macros; // only needed for -dD static int false_nesting = 0; static int counter_macro = 0; // __COUNTER__ expansion +static int include_level = 0; #define INCLUDEPATHS 300 const char *includepath[INCLUDEPATHS+1] = { @@ -145,48 +146,89 @@ static int token_defined(struct token *token) return 0; } -static void replace_with_defined(struct token *token) +static void replace_with_bool(struct token *token, bool val) { static const char *string[] = { "0", "1" }; - int defined = token_defined(token); token_type(token) = TOKEN_NUMBER; - token->number = string[defined]; + token->number = string[val]; +} + +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); +} + +static void expand_file(struct token *token) +{ + replace_with_string(token, stream_name(token->pos.stream)); +} + +static void expand_basefile(struct token *token) +{ + replace_with_string(token, base_filename); +} + +static time_t t = 0; +static void expand_date(struct token *token) +{ + static char buffer[12]; /* __DATE__: 3 + ' ' + 2 + ' ' + 4 + '\0' */ + + if (!t) + time(&t); + strftime(buffer, 12, "%b %e %Y", localtime(&t)); + replace_with_string(token, buffer); +} + +static void expand_time(struct token *token) +{ + static char buffer[9]; /* __TIME__: 2 + ':' + 2 + ':' + 2 + '\0' */ + + if (!t) + time(&t); + strftime(buffer, 9, "%T", localtime(&t)); + replace_with_string(token, buffer); +} + +static void expand_counter(struct token *token) +{ + replace_with_integer(token, counter_macro++); +} + +static void expand_include_level(struct token *token) +{ + replace_with_integer(token, include_level - 1); } static int expand_one_symbol(struct token **list) { struct token *token = *list; struct symbol *sym; - static char buffer[12]; /* __DATE__: 3 + ' ' + 2 + ' ' + 4 + '\0' */ - static time_t t = 0; if (token->pos.noexpand) return 1; sym = lookup_macro(token->ident); - if (sym) { + if (!sym) + return 1; + if (sym->expander) { + sym->expander(token); + return 1; + } else { sym->used_in = file_scope; return expand(list, sym); } - if (token->ident == &__LINE___ident) { - replace_with_integer(token, token->pos.line); - } else if (token->ident == &__FILE___ident) { - replace_with_string(token, stream_name(token->pos.stream)); - } else if (token->ident == &__DATE___ident) { - if (!t) - time(&t); - strftime(buffer, 12, "%b %e %Y", localtime(&t)); - replace_with_string(token, buffer); - } else if (token->ident == &__TIME___ident) { - if (!t) - time(&t); - strftime(buffer, 9, "%T", localtime(&t)); - replace_with_string(token, buffer); - } else if (token->ident == &__COUNTER___ident) { - replace_with_integer(token, counter_macro++); - } - return 1; } static inline struct token *scan_next(struct token **where) @@ -511,13 +553,10 @@ static int merge(struct token *left, struct token *right) left->pos.noexpand = 0; return 1; - case TOKEN_NUMBER: { - char *number = __alloc_bytes(strlen(buffer) + 1); - memcpy(number, buffer, strlen(buffer) + 1); + case TOKEN_NUMBER: token_type(left) = TOKEN_NUMBER; /* could be . + num */ - left->number = number; + left->number = xstrdup(buffer); return 1; - } case TOKEN_SPECIAL: if (buffer[2] && buffer[3]) @@ -868,8 +907,7 @@ static int try_include(const char *path, const char *filename, int flen, struct return 1; fd = open(fullname, O_RDONLY); if (fd >= 0) { - char * streamname = __alloc_bytes(plen + flen); - memcpy(streamname, fullname, plen + flen); + char *streamname = xmemdup(fullname, plen + flen); *where = tokenize(streamname, fd, *where, next_path); close(fd); return 1; @@ -1299,40 +1337,16 @@ Earg: return NULL; } -static int do_handle_define(struct stream *stream, struct token **line, struct token *token, int attr) +static int do_define(struct position pos, struct token *token, struct ident *name, + struct token *arglist, struct token *expansion, int attr) { - struct token *arglist, *expansion; - struct token *left = token->next; struct symbol *sym; - struct ident *name; - int ret; - - if (token_type(left) != TOKEN_IDENT) { - sparse_error(token->pos, "expected identifier to 'define'"); - return 1; - } - - name = left->ident; - - arglist = NULL; - expansion = left->next; - if (!expansion->pos.whitespace) { - if (match_op(expansion, '(')) { - arglist = expansion; - expansion = parse_arguments(expansion); - if (!expansion) - return 1; - } else if (!eof_token(expansion)) { - warning(expansion->pos, - "no whitespace before object-like macro body"); - } - } + int ret = 1; expansion = parse_expansion(expansion, arglist, name); if (!expansion) return 1; - ret = 1; sym = lookup_symbol(name, NS_MACRO | NS_UNDEF); if (sym) { int clean; @@ -1347,7 +1361,7 @@ static int do_handle_define(struct stream *stream, struct token **line, struct t ret = 0; if ((clean && attr == SYM_ATTR_NORMAL) || sym->used_in == file_scope) { - warning(left->pos, "preprocessor token %.*s redefined", + warning(pos, "preprocessor token %.*s redefined", name->len, name->name); info(sym->pos, "this was the original definition"); } @@ -1356,7 +1370,7 @@ static int do_handle_define(struct stream *stream, struct token **line, struct t } if (!sym || sym->scope != file_scope) { - sym = alloc_symbol(left->pos, SYM_NODE); + sym = alloc_symbol(pos, SYM_NODE); bind_symbol(sym, name, NS_MACRO); add_ident(¯os, name); ret = 0; @@ -1365,7 +1379,8 @@ static int do_handle_define(struct stream *stream, struct token **line, struct t if (!ret) { sym->expansion = expansion; sym->arglist = arglist; - __free_token(token); /* Free the "define" token, but not the rest of the line */ + if (token) /* Free the "define" token, but not the rest of the line */ + __free_token(token); } sym->namespace = NS_MACRO; @@ -1375,6 +1390,74 @@ out: return ret; } +/// +// predefine a macro with a printf-formatted value +// @name: the name of the macro +// @weak: 0/1 for a normal or a weak define +// @fmt: the printf format followed by it's arguments. +// +// The type of the value is automatically infered: +// TOKEN_NUMBER if it starts by a digit, TOKEN_IDENT otherwise. +// If @fmt is null or empty, the macro is defined with an empty definition. +void predefine(const char *name, int weak, const char *fmt, ...) +{ + struct ident *ident = built_in_ident(name); + struct token *value = &eof_token_entry; + int attr = weak ? SYM_ATTR_WEAK : SYM_ATTR_NORMAL; + + if (fmt && fmt[0]) { + static char buf[256]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + value = __alloc_token(0); + if (isdigit(buf[0])) { + token_type(value) = TOKEN_NUMBER; + value->number = xstrdup(buf); + } else { + token_type(value) = TOKEN_IDENT; + value->ident = built_in_ident(buf); + } + value->pos.whitespace = 1; + value->next = &eof_token_entry; + } + + do_define(value->pos, NULL, ident, NULL, value, attr); +} + +static int do_handle_define(struct stream *stream, struct token **line, struct token *token, int attr) +{ + struct token *arglist, *expansion; + struct token *left = token->next; + struct ident *name; + + if (token_type(left) != TOKEN_IDENT) { + sparse_error(token->pos, "expected identifier to 'define'"); + return 1; + } + + name = left->ident; + + arglist = NULL; + expansion = left->next; + if (!expansion->pos.whitespace) { + if (match_op(expansion, '(')) { + arglist = expansion; + expansion = parse_arguments(expansion); + if (!expansion) + return 1; + } else if (!eof_token(expansion)) { + warning(expansion->pos, + "no whitespace before object-like macro body"); + } + } + + return do_define(left->pos, token, name, arglist, expansion, attr); +} + static int handle_define(struct stream *stream, struct token **line, struct token *token) { return do_handle_define(stream, line, token, SYM_ATTR_NORMAL); @@ -1505,6 +1588,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; @@ -1535,6 +1622,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; } @@ -1891,6 +2005,18 @@ static void init_preprocessor(void) { "if", handle_if }, { "elif", handle_elif }, }; + static struct { + const char *name; + void (*expander)(struct token *); + } dynamic[] = { + { "__LINE__", expand_line }, + { "__FILE__", expand_file }, + { "__BASE_FILE__", expand_basefile }, + { "__DATE__", expand_date }, + { "__TIME__", expand_time }, + { "__COUNTER__", expand_counter }, + { "__INCLUDE_LEVEL__", expand_include_level }, + }; for (i = 0; i < ARRAY_SIZE(normal); i++) { struct symbol *sym; @@ -1904,6 +2030,11 @@ static void init_preprocessor(void) sym->handler = special[i].handler; sym->normal = 0; } + for (i = 0; i < ARRAY_SIZE(dynamic); i++) { + struct symbol *sym; + sym = create_symbol(stream, dynamic[i].name, SYM_NODE, NS_MACRO); + sym->expander = dynamic[i].expander; + } counter_macro = 0; } @@ -1985,9 +2116,11 @@ static void do_preprocess(struct token **list) if (!stream->dirty) stream->constant = CONSTANT_FILE_YES; *list = next->next; + include_level--; continue; case TOKEN_STREAMBEGIN: *list = next->next; + include_level++; continue; default: @@ -697,6 +697,9 @@ struct symbol bool_ctype, void_ctype, type_ctype, string_ctype, ptr_ctype, lazy_ptr_ctype, incomplete_ctype, label_ctype, bad_ctype, null_ctype; +struct symbol int_ptr_ctype, uint_ptr_ctype; +struct symbol long_ptr_ctype, ulong_ptr_ctype; +struct symbol llong_ptr_ctype, ullong_ptr_ctype; struct symbol float32_ctype, float32x_ctype; struct symbol float64_ctype, float64x_ctype; struct symbol float128_ctype; @@ -779,6 +782,12 @@ static const struct ctype_declare { { &null_ctype, SYM_PTR, 0, &bits_in_pointer, &pointer_alignment, &void_ctype }, { &label_ctype, SYM_PTR, 0, &bits_in_pointer, &pointer_alignment, &void_ctype }, { &lazy_ptr_ctype, SYM_PTR, 0, &bits_in_pointer, &pointer_alignment, &void_ctype }, + { &int_ptr_ctype, SYM_PTR, 0, &bits_in_pointer, &pointer_alignment, &int_ctype }, + { &uint_ptr_ctype, SYM_PTR, 0, &bits_in_pointer, &pointer_alignment, &uint_ctype }, + { &long_ptr_ctype, SYM_PTR, 0, &bits_in_pointer, &pointer_alignment, &long_ctype }, + { &ulong_ptr_ctype, SYM_PTR, 0, &bits_in_pointer, &pointer_alignment, &ulong_ctype }, + { &llong_ptr_ctype, SYM_PTR, 0, &bits_in_pointer, &pointer_alignment, &llong_ctype }, + { &ullong_ptr_ctype,SYM_PTR, 0, &bits_in_pointer, &pointer_alignment, &ullong_ctype }, { &const_void_ctype, SYM_NODE, MOD_CONST, NULL, NULL, &void_ctype }, { &const_char_ctype, SYM_NODE, MOD_CONST, &bits_in_char, &max_int_alignment, &char_ctype }, @@ -155,6 +155,7 @@ struct symbol { struct token *expansion; struct token *arglist; struct scope *used_in; + void (*expander)(struct token *); }; struct /* NS_PREPROCESSOR */ { int (*handler)(struct stream *, struct token **, struct token *); @@ -173,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; @@ -267,6 +269,9 @@ extern struct symbol bool_ctype, void_ctype, type_ctype, string_ctype, ptr_ctype, lazy_ptr_ctype, incomplete_ctype, label_ctype, bad_ctype, null_ctype; +extern struct symbol int_ptr_ctype, uint_ptr_ctype; +extern struct symbol long_ptr_ctype, ulong_ptr_ctype; +extern struct symbol llong_ptr_ctype, ullong_ptr_ctype; extern struct symbol float32_ctype, float32x_ctype; extern struct symbol float64_ctype, float64x_ctype; extern struct symbol float128_ctype; @@ -528,8 +528,7 @@ static int get_one_number(int c, int next, stream_t *stream) { struct token *token; static char buffer[4095]; - char *p = buffer, *buf, *buffer_end = buffer + sizeof (buffer); - int len; + char *p = buffer, *buffer_end = buffer + sizeof (buffer); *p++ = c; for (;;) { @@ -557,13 +556,9 @@ static int get_one_number(int c, int next, stream_t *stream) } *p++ = 0; - len = p - buffer; - buf = __alloc_bytes(len); - memcpy(buf, buffer, len); - token = stream->token; token_type(token) = TOKEN_NUMBER; - token->number = buf; + token->number = xmemdup(buffer, p - buffer); add_token(stream); return next; diff --git a/utils.c b/utils.c new file mode 100644 index 00000000..4945e1ca --- /dev/null +++ b/utils.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +// Copyright (C) 2018 Luc Van Oostenryck + +#include "utils.h" +#include "allocate.h" +#include <string.h> + + +void *xmemdup(const void *src, size_t len) +{ + return memcpy(__alloc_bytes(len), src, len); +} + +char *xstrdup(const char *src) +{ + return xmemdup(src, strlen(src) + 1); +} diff --git a/utils.h b/utils.h new file mode 100644 index 00000000..38749be2 --- /dev/null +++ b/utils.h @@ -0,0 +1,25 @@ +#ifndef UTILS_H +#define UTILS_H + +/// +// Miscellaneous utilities +// ----------------------- + +#include <stddef.h> + +/// +// duplicate a memory buffer in a newly allocated buffer. +// @src: a pointer to the memory buffer to be duplicated +// @len: the size of the memory buffer to be duplicated +// @return: a pointer to a copy of @src allocated via +// :func:`__alloc_bytes()`. +void *xmemdup(const void *src, size_t len); + +/// +// duplicate a null-terminated string in a newly allocated buffer. +// @src: a pointer to string to be duplicated +// @return: a pointer to a copy of @str allocated via +// :func:`__alloc_bytes()`. +char *xstrdup(const char *src); + +#endif diff --git a/validation/builtin-overflow.c b/validation/builtin-overflow.c new file mode 100644 index 00000000..867eb42f --- /dev/null +++ b/validation/builtin-overflow.c @@ -0,0 +1,246 @@ +enum e { OK }; +typedef _Bool bool; + +static int test(int i, long l, long long ll, enum e e, bool b, void *p) +{ + int rc = 0; + + // should be OK + rc += __builtin_add_overflow(i, i, &i); + rc += __builtin_add_overflow(l, i, &i); + rc += __builtin_add_overflow(i, l, &i); + rc += __builtin_add_overflow(i, i, &l); + rc += __builtin_add_overflow(ll, i, &i); + rc += __builtin_add_overflow(i, ll, &i); + rc += __builtin_add_overflow(i, i, &ll); + + rc += __builtin_add_overflow_p(i, i, i); + rc += __builtin_add_overflow_p(l, i, i); + rc += __builtin_add_overflow_p(i, l, i); + rc += __builtin_add_overflow_p(i, i, l); + rc += __builtin_add_overflow_p(ll, i, i); + rc += __builtin_add_overflow_p(i, ll, i); + rc += __builtin_add_overflow_p(i, i, ll); + + rc += __builtin_sub_overflow(i, i, &i); + rc += __builtin_sub_overflow(l, i, &i); + rc += __builtin_sub_overflow(i, l, &i); + rc += __builtin_sub_overflow(i, i, &l); + rc += __builtin_sub_overflow(ll, i, &i); + rc += __builtin_sub_overflow(i, ll, &i); + rc += __builtin_sub_overflow(i, i, &ll); + + rc += __builtin_sub_overflow_p(i, i, i); + rc += __builtin_sub_overflow_p(l, i, i); + rc += __builtin_sub_overflow_p(i, l, i); + rc += __builtin_sub_overflow_p(i, i, l); + rc += __builtin_sub_overflow_p(ll, i, i); + rc += __builtin_sub_overflow_p(i, ll, i); + rc += __builtin_sub_overflow_p(i, i, ll); + + rc += __builtin_mul_overflow(i, i, &i); + rc += __builtin_mul_overflow(l, i, &i); + rc += __builtin_mul_overflow(i, l, &i); + rc += __builtin_mul_overflow(i, i, &l); + rc += __builtin_mul_overflow(ll, i, &i); + rc += __builtin_mul_overflow(i, ll, &i); + rc += __builtin_mul_overflow(i, i, &ll); + + rc += __builtin_mul_overflow_p(i, i, i); + rc += __builtin_mul_overflow_p(l, i, i); + rc += __builtin_mul_overflow_p(i, l, i); + rc += __builtin_mul_overflow_p(i, i, l); + rc += __builtin_mul_overflow_p(ll, i, i); + rc += __builtin_mul_overflow_p(i, ll, i); + rc += __builtin_mul_overflow_p(i, i, ll); + + // should be KO + rc += __builtin_add_overflow(); + rc += __builtin_add_overflow(i); + rc += __builtin_add_overflow(i, i); + rc += __builtin_add_overflow(i, i, &i, i); + rc += __builtin_add_overflow(e, i, &i); + rc += __builtin_add_overflow(i, e, &i); + rc += __builtin_add_overflow(i, i, &e); + rc += __builtin_add_overflow(b, i, &i); + rc += __builtin_add_overflow(i, b, &i); + rc += __builtin_add_overflow(i, i, &b); + rc += __builtin_add_overflow(i, i, p); + + rc += __builtin_add_overflow_p(); + rc += __builtin_add_overflow_p(i); + rc += __builtin_add_overflow_p(i, i); + rc += __builtin_add_overflow_p(i, i, i, i); + rc += __builtin_add_overflow_p(e, i, i); + rc += __builtin_add_overflow_p(i, e, i); + rc += __builtin_add_overflow_p(i, i, e); + rc += __builtin_add_overflow_p(b, i, i); + rc += __builtin_add_overflow_p(i, b, i); + rc += __builtin_add_overflow_p(i, i, b); + rc += __builtin_add_overflow_p(i, i, p); + + rc += __builtin_sub_overflow(); + rc += __builtin_sub_overflow(i); + rc += __builtin_sub_overflow(i, i); + rc += __builtin_sub_overflow(i, i, &i, i); + rc += __builtin_sub_overflow(e, i, &i); + rc += __builtin_sub_overflow(i, e, &i); + rc += __builtin_sub_overflow(i, i, &e); + rc += __builtin_sub_overflow(b, i, &i); + rc += __builtin_sub_overflow(i, b, &i); + rc += __builtin_sub_overflow(i, i, &b); + rc += __builtin_sub_overflow(i, i, p); + + rc += __builtin_sub_overflow_p(); + rc += __builtin_sub_overflow_p(i); + rc += __builtin_sub_overflow_p(i, i); + rc += __builtin_sub_overflow_p(i, i, i, i); + rc += __builtin_sub_overflow_p(e, i, i); + rc += __builtin_sub_overflow_p(i, e, i); + rc += __builtin_sub_overflow_p(i, i, e); + rc += __builtin_sub_overflow_p(b, i, i); + rc += __builtin_sub_overflow_p(i, b, i); + rc += __builtin_sub_overflow_p(i, i, b); + rc += __builtin_sub_overflow_p(i, i, p); + + rc += __builtin_mul_overflow(); + rc += __builtin_mul_overflow(i); + rc += __builtin_mul_overflow(i, i); + rc += __builtin_mul_overflow(i, i, &i, i); + rc += __builtin_mul_overflow(e, i, &i); + rc += __builtin_mul_overflow(i, e, &i); + rc += __builtin_mul_overflow(i, i, &e); + rc += __builtin_mul_overflow(b, i, &i); + rc += __builtin_mul_overflow(i, b, &i); + rc += __builtin_mul_overflow(i, i, &b); + rc += __builtin_mul_overflow(i, i, p); + + rc += __builtin_mul_overflow_p(); + rc += __builtin_mul_overflow_p(i); + rc += __builtin_mul_overflow_p(i, i); + rc += __builtin_mul_overflow_p(i, i, i, i); + rc += __builtin_mul_overflow_p(e, i, i); + rc += __builtin_mul_overflow_p(i, e, i); + rc += __builtin_mul_overflow_p(i, i, e); + rc += __builtin_mul_overflow_p(b, i, i); + rc += __builtin_mul_overflow_p(i, b, i); + rc += __builtin_mul_overflow_p(i, i, b); + rc += __builtin_mul_overflow_p(i, i, p); + + return rc; +} + +/* + * check-name: builtin-overflow + * + * check-error-start +builtin-overflow.c:58:37: error: not enough arguments for __builtin_add_overflow +builtin-overflow.c:59:37: error: not enough arguments for __builtin_add_overflow +builtin-overflow.c:60:37: error: not enough arguments for __builtin_add_overflow +builtin-overflow.c:61:37: error: too many arguments for __builtin_add_overflow +builtin-overflow.c:62:38: error: invalid type for argument 1: +builtin-overflow.c:62:38: int enum e [signed] e +builtin-overflow.c:63:41: error: invalid type for argument 2: +builtin-overflow.c:63:41: int enum e [signed] e +builtin-overflow.c:64:45: error: invalid type for argument 3: +builtin-overflow.c:64:45: int enum e *<noident> +builtin-overflow.c:65:38: error: invalid type for argument 1: +builtin-overflow.c:65:38: bool [unsigned] [usertype] b +builtin-overflow.c:66:41: error: invalid type for argument 2: +builtin-overflow.c:66:41: bool [unsigned] [usertype] b +builtin-overflow.c:67:45: error: invalid type for argument 3: +builtin-overflow.c:67:45: bool *<noident> +builtin-overflow.c:68:44: error: invalid type for argument 3: +builtin-overflow.c:68:44: void *p +builtin-overflow.c:70:39: error: not enough arguments for __builtin_add_overflow_p +builtin-overflow.c:71:39: error: not enough arguments for __builtin_add_overflow_p +builtin-overflow.c:72:39: error: not enough arguments for __builtin_add_overflow_p +builtin-overflow.c:73:39: error: too many arguments for __builtin_add_overflow_p +builtin-overflow.c:74:40: error: invalid type for argument 1: +builtin-overflow.c:74:40: int enum e [signed] [addressable] e +builtin-overflow.c:75:43: error: invalid type for argument 2: +builtin-overflow.c:75:43: int enum e [signed] [addressable] e +builtin-overflow.c:76:46: error: invalid type for argument 3: +builtin-overflow.c:76:46: int enum e [signed] [addressable] e +builtin-overflow.c:77:40: error: invalid type for argument 1: +builtin-overflow.c:77:40: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:78:43: error: invalid type for argument 2: +builtin-overflow.c:78:43: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:79:46: error: invalid type for argument 3: +builtin-overflow.c:79:46: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:80:46: error: invalid type for argument 3: +builtin-overflow.c:80:46: void *p +builtin-overflow.c:82:37: error: not enough arguments for __builtin_sub_overflow +builtin-overflow.c:83:37: error: not enough arguments for __builtin_sub_overflow +builtin-overflow.c:84:37: error: not enough arguments for __builtin_sub_overflow +builtin-overflow.c:85:37: error: too many arguments for __builtin_sub_overflow +builtin-overflow.c:86:38: error: invalid type for argument 1: +builtin-overflow.c:86:38: int enum e [signed] [addressable] e +builtin-overflow.c:87:41: error: invalid type for argument 2: +builtin-overflow.c:87:41: int enum e [signed] [addressable] e +builtin-overflow.c:88:45: error: invalid type for argument 3: +builtin-overflow.c:88:45: int enum e *<noident> +builtin-overflow.c:89:38: error: invalid type for argument 1: +builtin-overflow.c:89:38: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:90:41: error: invalid type for argument 2: +builtin-overflow.c:90:41: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:91:45: error: invalid type for argument 3: +builtin-overflow.c:91:45: bool *<noident> +builtin-overflow.c:92:44: error: invalid type for argument 3: +builtin-overflow.c:92:44: void *p +builtin-overflow.c:94:39: error: not enough arguments for __builtin_sub_overflow_p +builtin-overflow.c:95:39: error: not enough arguments for __builtin_sub_overflow_p +builtin-overflow.c:96:39: error: not enough arguments for __builtin_sub_overflow_p +builtin-overflow.c:97:39: error: too many arguments for __builtin_sub_overflow_p +builtin-overflow.c:98:40: error: invalid type for argument 1: +builtin-overflow.c:98:40: int enum e [signed] [addressable] e +builtin-overflow.c:99:43: error: invalid type for argument 2: +builtin-overflow.c:99:43: int enum e [signed] [addressable] e +builtin-overflow.c:100:46: error: invalid type for argument 3: +builtin-overflow.c:100:46: int enum e [signed] [addressable] e +builtin-overflow.c:101:40: error: invalid type for argument 1: +builtin-overflow.c:101:40: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:102:43: error: invalid type for argument 2: +builtin-overflow.c:102:43: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:103:46: error: invalid type for argument 3: +builtin-overflow.c:103:46: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:104:46: error: invalid type for argument 3: +builtin-overflow.c:104:46: void *p +builtin-overflow.c:106:37: error: not enough arguments for __builtin_mul_overflow +builtin-overflow.c:107:37: error: not enough arguments for __builtin_mul_overflow +builtin-overflow.c:108:37: error: not enough arguments for __builtin_mul_overflow +builtin-overflow.c:109:37: error: too many arguments for __builtin_mul_overflow +builtin-overflow.c:110:38: error: invalid type for argument 1: +builtin-overflow.c:110:38: int enum e [signed] [addressable] e +builtin-overflow.c:111:41: error: invalid type for argument 2: +builtin-overflow.c:111:41: int enum e [signed] [addressable] e +builtin-overflow.c:112:45: error: invalid type for argument 3: +builtin-overflow.c:112:45: int enum e *<noident> +builtin-overflow.c:113:38: error: invalid type for argument 1: +builtin-overflow.c:113:38: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:114:41: error: invalid type for argument 2: +builtin-overflow.c:114:41: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:115:45: error: invalid type for argument 3: +builtin-overflow.c:115:45: bool *<noident> +builtin-overflow.c:116:44: error: invalid type for argument 3: +builtin-overflow.c:116:44: void *p +builtin-overflow.c:118:39: error: not enough arguments for __builtin_mul_overflow_p +builtin-overflow.c:119:39: error: not enough arguments for __builtin_mul_overflow_p +builtin-overflow.c:120:39: error: not enough arguments for __builtin_mul_overflow_p +builtin-overflow.c:121:39: error: too many arguments for __builtin_mul_overflow_p +builtin-overflow.c:122:40: error: invalid type for argument 1: +builtin-overflow.c:122:40: int enum e [signed] [addressable] e +builtin-overflow.c:123:43: error: invalid type for argument 2: +builtin-overflow.c:123:43: int enum e [signed] [addressable] e +builtin-overflow.c:124:46: error: invalid type for argument 3: +builtin-overflow.c:124:46: int enum e [signed] [addressable] e +builtin-overflow.c:125:40: error: invalid type for argument 1: +builtin-overflow.c:125:40: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:126:43: error: invalid type for argument 2: +builtin-overflow.c:126:43: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:127:46: error: invalid type for argument 3: +builtin-overflow.c:127:46: bool [unsigned] [addressable] [usertype] b +builtin-overflow.c:128:46: error: invalid type for argument 3: +builtin-overflow.c:128:46: void *p + * check-error-end + */ diff --git a/validation/preprocessor/base-file.c b/validation/preprocessor/base-file.c new file mode 100644 index 00000000..61a290cb --- /dev/null +++ b/validation/preprocessor/base-file.c @@ -0,0 +1,17 @@ +__FILE__ +__BASE_FILE__ + +#include "base-file.h" + +/* + * check-name: base file + * check-command: sparse -E $file + * + * check-output-start + +"preprocessor/base-file.c" +"preprocessor/base-file.c" +"preprocessor/base-file.h" +"preprocessor/base-file.c" + * check-output-end + */ diff --git a/validation/preprocessor/base-file.h b/validation/preprocessor/base-file.h new file mode 100644 index 00000000..018b16c5 --- /dev/null +++ b/validation/preprocessor/base-file.h @@ -0,0 +1,2 @@ +__FILE__ +__BASE_FILE__ diff --git a/validation/preprocessor/builtin.c b/validation/preprocessor/builtin.c new file mode 100644 index 00000000..6c3aa176 --- /dev/null +++ b/validation/preprocessor/builtin.c @@ -0,0 +1,17 @@ +__CHECKER__ +F(__CHECKER__,__CHECKER__) +S(#__CHECKER__) +const char str[] = "__CHECKER__"; + +/* + * check-name: builtin + * check-command: sparse -E $file + * + * check-output-start + +1 +F(1,1) +S(#1) +const char str[] = "__CHECKER__"; + * check-output-end + */ diff --git a/validation/preprocessor/dynamic.c b/validation/preprocessor/dynamic.c new file mode 100644 index 00000000..f791ba39 --- /dev/null +++ b/validation/preprocessor/dynamic.c @@ -0,0 +1,37 @@ +#if defined(__LINE__) +__LINE__ +#endif +#if defined(__FILE__) +__FILE__ +#endif +#if defined(__BASE_FILE__) +__BASE_FILE__ +#endif +#if defined(__DATE__) +date +#endif +#if defined(__TIME__) +time +#endif +#if defined(__COUNTER__) +counter +#endif +#if defined(__INCLUDE_LEVEL__) +__INCLUDE_LEVEL__ +#endif + +/* + * check-name: dynamic-macros + * check-command: sparse -E $file + * + * check-output-start + +2 +"preprocessor/dynamic.c" +"preprocessor/dynamic.c" +date +time +counter +0 + * check-output-end + */ 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 + */ diff --git a/validation/preprocessor/include-level.c b/validation/preprocessor/include-level.c new file mode 100644 index 00000000..b5e5e603 --- /dev/null +++ b/validation/preprocessor/include-level.c @@ -0,0 +1,14 @@ +__FILE__: __INCLUDE_LEVEL__ + +#include "include-level.h" + +/* + * check-name: include-level + * check-command: sparse -E $file + * + * check-output-start + +"preprocessor/include-level.c": 0 +"preprocessor/include-level.h": 1 + * check-output-end + */ diff --git a/validation/preprocessor/include-level.h b/validation/preprocessor/include-level.h new file mode 100644 index 00000000..cbc10182 --- /dev/null +++ b/validation/preprocessor/include-level.h @@ -0,0 +1 @@ +__FILE__: __INCLUDE_LEVEL__ |
