Print this page
new smatch

*** 21,30 **** --- 21,31 ---- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include <ctype.h> + #include <errno.h> #include <fcntl.h> #include <stdarg.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h>
*** 38,61 **** #include "allocate.h" #include "token.h" #include "parse.h" #include "symbol.h" #include "expression.h" #include "scope.h" #include "linearize.h" #include "target.h" #include "version.h" ! static const char *progname; ! ! int sparse_errors = 0; ! int sparse_warnings = 0; ! ! int verbose, optimize, optimize_size, preprocessing; int die_if_error = 0; int parse_error; int has_error = 0; #ifndef __GNUC__ # define __GNUC__ 2 # define __GNUC_MINOR__ 95 # define __GNUC_PATCHLEVEL__ 0 --- 39,61 ---- #include "allocate.h" #include "token.h" #include "parse.h" #include "symbol.h" #include "expression.h" + #include "evaluate.h" #include "scope.h" #include "linearize.h" #include "target.h" + #include "machine.h" #include "version.h" + #include "bits.h" ! int verbose, optimize_level, optimize_size, preprocessing; int die_if_error = 0; int parse_error; int has_error = 0; + int do_output = 0; #ifndef __GNUC__ # define __GNUC__ 2 # define __GNUC_MINOR__ 95 # define __GNUC_PATCHLEVEL__ 0
*** 63,86 **** int gcc_major = __GNUC__; int gcc_minor = __GNUC_MINOR__; int gcc_patchlevel = __GNUC_PATCHLEVEL__; static const char *gcc_base_dir = GCC_BASE; static const char *multiarch_dir = MULTIARCH_TRIPLET; struct token *skip_to(struct token *token, int op) { while (!match_op(token, op) && !eof_token(token)) token = token->next; return token; } struct token *expect(struct token *token, int op, const char *where) { if (!match_op(token, op)) { - static struct token bad_token; if (token != &bad_token) { bad_token.next = token; sparse_error(token->pos, "Expected %s %s", show_special(op), where); sparse_error(token->pos, "got %s", show_token(token)); } --- 63,90 ---- int gcc_major = __GNUC__; int gcc_minor = __GNUC_MINOR__; int gcc_patchlevel = __GNUC_PATCHLEVEL__; + const char *base_filename; + + static const char *diag_prefix = ""; static const char *gcc_base_dir = GCC_BASE; static const char *multiarch_dir = MULTIARCH_TRIPLET; + static const char *outfile = NULL; struct token *skip_to(struct token *token, int op) { while (!match_op(token, op) && !eof_token(token)) token = token->next; return token; } + static struct token bad_token = { .pos.type = TOKEN_BAD }; struct token *expect(struct token *token, int op, const char *where) { if (!match_op(token, op)) { if (token != &bad_token) { bad_token.next = token; sparse_error(token->pos, "Expected %s %s", show_special(op), where); sparse_error(token->pos, "got %s", show_token(token)); }
*** 89,98 **** --- 93,117 ---- return &bad_token; } return token->next; } + /// + // issue an error message on new parsing errors + // @token: the current token + // @errmsg: the error message + // If the current token is from a previous error, an error message + // has already been issued, so nothing more is done. + // Otherwise, @errmsg is displayed followed by the current token. + void unexpected(struct token *token, const char *errmsg) + { + if (token == &bad_token) + return; + sparse_error(token->pos, "%s", errmsg); + sparse_error(token->pos, "got %s", show_token(token)); + } + unsigned int hexval(unsigned int c) { int retval = 256; switch (c) { case '0'...'9':
*** 111,128 **** static void do_warn(const char *type, struct position pos, const char * fmt, va_list args) { static char buffer[512]; const char *name; vsprintf(buffer, fmt, args); name = stream_name(pos.stream); fprintf(stderr, "%s: %s:%d:%d: %s%s\n", ! progname, name, pos.line, pos.pos, type, buffer); } ! static int max_warnings = 100; static int show_info = 1; void info(struct position pos, const char * fmt, ...) { va_list args; --- 130,152 ---- static void do_warn(const char *type, struct position pos, const char * fmt, va_list args) { static char buffer[512]; const char *name; + /* Shut up warnings if position is bad_token.pos */ + if (pos.type == TOKEN_BAD) + return; + vsprintf(buffer, fmt, args); name = stream_name(pos.stream); + fflush(stdout); fprintf(stderr, "%s: %s:%d:%d: %s%s\n", ! diag_prefix, name, pos.line, pos.pos, type, buffer); } ! unsigned int fmax_warnings = 100; static int show_info = 1; void info(struct position pos, const char * fmt, ...) { va_list args;
*** 139,148 **** --- 163,175 ---- static int errors = 0; parse_error = 1; die_if_error = 1; show_info = 1; + /* Shut up warnings if position is bad_token.pos */ + if (pos.type == TOKEN_BAD) + return; /* Shut up warnings after an error */ has_error |= ERROR_CURR_PHASE; if (errors > 100) { static int once = 0; show_info = 0;
*** 165,180 **** do_error(pos, fmt, args); va_end(args); return; } ! if (!max_warnings || has_error) { show_info = 0; return; } ! if (!--max_warnings) { show_info = 0; fmt = "too many warnings"; } va_start(args, fmt); --- 192,207 ---- do_error(pos, fmt, args); va_end(args); return; } ! if (!fmax_warnings || has_error) { show_info = 0; return; } ! if (!--fmax_warnings) { show_info = 0; fmt = "too many warnings"; } va_start(args, fmt);
*** 217,236 **** va_start(args, fmt); vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); ! fprintf(stderr, "%s: %s\n", progname, buffer); exit(1); } static struct token *pre_buffer_begin = NULL; static struct token *pre_buffer_end = NULL; int Waddress = 0; int Waddress_space = 1; int Wbitwise = 1; int Wcast_to_as = 0; int Wcast_truncate = 1; int Wconstant_suffix = 0; int Wconstexpr_not_const = 0; int Wcontext = 1; --- 244,265 ---- va_start(args, fmt); vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); ! fprintf(stderr, "%s: %s\n", diag_prefix, buffer); exit(1); } static struct token *pre_buffer_begin = NULL; static struct token *pre_buffer_end = NULL; int Waddress = 0; int Waddress_space = 1; int Wbitwise = 1; + int Wbitwise_pointer = 0; + int Wcast_from_as = 0; int Wcast_to_as = 0; int Wcast_truncate = 1; int Wconstant_suffix = 0; int Wconstexpr_not_const = 0; int Wcontext = 1;
*** 239,248 **** --- 268,278 ---- int Wdefault_bitfield_sign = 0; int Wdesignated_init = 1; int Wdo_while = 0; int Wimplicit_int = 1; int Winit_cstring = 0; + int Wint_to_pointer_cast = 1; int Wenum_mismatch = 1; int Wexternal_function_has_definition = 1; int Wsparse_error = 0; int Wmemcpy_max_count = 1; int Wnon_pointer_null = 1;
*** 252,264 **** --- 282,297 ---- int Woverride_init = 1; int Woverride_init_all = 0; int Woverride_init_whole_range = 0; int Wparen_string = 0; int Wpointer_arith = 0; + int Wpointer_to_int_cast = 1; int Wptr_subtraction_blows = 0; int Wreturn_void = 0; int Wshadow = 0; + int Wshift_count_negative = 1; + int Wshift_count_overflow = 1; int Wsizeof_bool = 0; int Wstrict_prototypes = 1; int Wtautological_compare = 0; int Wtransparent_union = 0; int Wtypesign = 0;
*** 266,282 **** int Wuninitialized = 1; int Wunknown_attribute = 0; int Wvla = 1; int dump_macro_defs = 0; ! int dbg_entry = 0; int dbg_dead = 0; int fmem_report = 0; - int fdump_linearize; unsigned long long fmemcpy_max_count = 100000; int preprocess_only; static enum { STANDARD_C89, STANDARD_C94, --- 299,322 ---- int Wuninitialized = 1; int Wunknown_attribute = 0; int Wvla = 1; int dump_macro_defs = 0; + int dump_macros_only = 0; ! int dbg_compound = 0; int dbg_dead = 0; + int dbg_domtree = 0; + int dbg_entry = 0; + int dbg_ir = 0; + int dbg_postorder = 0; + unsigned long fdump_ir; int fmem_report = 0; unsigned long long fmemcpy_max_count = 100000; + unsigned long fpasses = ~0UL; + int funsigned_char = UNSIGNED_CHAR; int preprocess_only; static enum { STANDARD_C89, STANDARD_C94,
*** 284,312 **** STANDARD_C11, STANDARD_GNU11, STANDARD_GNU89, STANDARD_GNU99, } standard = STANDARD_GNU89; - #define ARCH_LP32 0 - #define ARCH_LP64 1 - #define ARCH_LLP64 2 - - #ifdef __x86_64__ - #define ARCH_M64_DEFAULT ARCH_LP64 - #else - #define ARCH_M64_DEFAULT ARCH_LP32 - #endif - int arch_m64 = ARCH_M64_DEFAULT; int arch_msize_long = 0; - - #ifdef __BIG_ENDIAN__ - #define ARCH_BIG_ENDIAN 1 - #else - #define ARCH_BIG_ENDIAN 0 - #endif int arch_big_endian = ARCH_BIG_ENDIAN; #define CMDLINE_INCLUDE 20 static int cmdline_include_nr = 0; static char *cmdline_include[CMDLINE_INCLUDE]; --- 324,337 ---- STANDARD_C11, STANDARD_GNU11, STANDARD_GNU89, STANDARD_GNU99, } standard = STANDARD_GNU89; int arch_m64 = ARCH_M64_DEFAULT; int arch_msize_long = 0; int arch_big_endian = ARCH_BIG_ENDIAN; + int arch_mach = MACH_NATIVE; #define CMDLINE_INCLUDE 20 static int cmdline_include_nr = 0; static char *cmdline_include[CMDLINE_INCLUDE];
*** 431,442 **** static char **handle_switch_m(char *arg, char **next) { if (!strcmp(arg, "m64")) { arch_m64 = ARCH_LP64; ! } else if (!strcmp(arg, "m32")) { arch_m64 = ARCH_LP32; } else if (!strcmp(arg, "msize-llp64")) { arch_m64 = ARCH_LLP64; } else if (!strcmp(arg, "msize-long")) { arch_msize_long = 1; } else if (!strcmp(arg, "multiarch-dir")) { --- 456,469 ---- static char **handle_switch_m(char *arg, char **next) { if (!strcmp(arg, "m64")) { arch_m64 = ARCH_LP64; ! } else if (!strcmp(arg, "m32") || !strcmp(arg, "m16")) { arch_m64 = ARCH_LP32; + } else if (!strcmp(arg, "mx32")) { + arch_m64 = ARCH_X32; } else if (!strcmp(arg, "msize-llp64")) { arch_m64 = ARCH_LLP64; } else if (!strcmp(arg, "msize-long")) { arch_msize_long = 1; } else if (!strcmp(arg, "multiarch-dir")) {
*** 447,494 **** arch_big_endian = 0; } return next; } - static void handle_arch_m64_finalize(void) - { - switch (arch_m64) { - case ARCH_LP32: - /* default values */ - #if defined(__x86_64__) || defined (__i386) - add_pre_buffer("#weak_define __i386__ 1\n"); - add_pre_buffer("#weak_define __i386 1\n"); - add_pre_buffer("#weak_define i386 1\n"); - #endif - return; - case ARCH_LP64: - bits_in_long = 64; - 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"); - add_pre_buffer("#weak_define _LP64 1\n"); - goto case_64bit_common; - case ARCH_LLP64: - bits_in_long = 32; - max_int_alignment = 4; - size_t_ctype = &ullong_ctype; - ssize_t_ctype = &llong_ctype; - add_pre_buffer("#weak_define __LLP64__ 1\n"); - goto case_64bit_common; - case_64bit_common: - bits_in_pointer = 64; - pointer_alignment = 8; - #if defined(__x86_64__) || defined (__i386) - add_pre_buffer("#weak_define __x86_64__ 1\n"); - add_pre_buffer("#weak_define __x86_64 1\n"); - #endif - break; - } - } - static void handle_arch_msize_long_finalize(void) { if (arch_msize_long) { size_t_ctype = &ulong_ctype; ssize_t_ctype = &long_ctype; --- 474,483 ----
*** 495,546 **** } } static void handle_arch_finalize(void) { - handle_arch_m64_finalize(); handle_arch_msize_long_finalize(); } ! static int handle_simple_switch(const char *arg, const char *name, int *flag) { int val = 1; // Prefixe "no-" mean to turn flag off. if (strncmp(arg, "no-", 3) == 0) { arg += 3; val = 0; } ! if (strcmp(arg, name) == 0) { ! *flag = val; return 1; } // not handled return 0; } static char **handle_switch_o(char *arg, char **next) { if (!strcmp (arg, "o")) { // "-o foo" if (!*++next) die("argument to '-o' is missing"); } // else "-ofoo" return next; } ! static const struct warning { ! const char *name; ! int *flag; ! } warnings[] = { { "address", &Waddress }, { "address-space", &Waddress_space }, { "bitwise", &Wbitwise }, { "cast-to-as", &Wcast_to_as }, { "cast-truncate", &Wcast_truncate }, { "constant-suffix", &Wconstant_suffix }, { "constexpr-not-const", &Wconstexpr_not_const}, { "context", &Wcontext }, --- 484,648 ---- } } static void handle_arch_finalize(void) { handle_arch_msize_long_finalize(); } + static const char *match_option(const char *arg, const char *prefix) + { + unsigned int n = strlen(prefix); + if (strncmp(arg, prefix, n) == 0) + return arg + n; + return NULL; + } ! ! struct mask_map { ! const char *name; ! unsigned long mask; ! }; ! ! static int apply_mask(unsigned long *val, const char *str, unsigned len, const struct mask_map *map, int neg) { + const char *name; + + for (;(name = map->name); map++) { + if (!strncmp(name, str, len) && !name[len]) { + if (neg == 0) + *val |= map->mask; + else + *val &= ~map->mask; + return 0; + } + } + return 1; + } + + static int handle_suboption_mask(const char *arg, const char *opt, const struct mask_map *map, unsigned long *flag) + { + if (*opt == '\0') { + apply_mask(flag, "", 0, map, 0); + return 1; + } + if (*opt++ != '=') + return 0; + while (1) { + unsigned int len = strcspn(opt, ",+"); + int neg = 0; + if (len == 0) + goto end; + if (!strncmp(opt, "no-", 3)) { + opt += 3; + len -= 3; + neg = 1; + } + if (apply_mask(flag, opt, len, map, neg)) + die("error: wrong option '%.*s' for \'%s\'", len, opt, arg); + + end: + opt += len; + if (*opt++ == '\0') + break; + } + return 1; + } + + + #define OPT_INVERSE 1 + struct flag { + const char *name; + int *flag; + int (*fun)(const char *arg, const char *opt, const struct flag *, int options); + unsigned long mask; + }; + + static int handle_switches(const char *ori, const char *opt, const struct flag *flags) + { + const char *arg = opt; int val = 1; // Prefixe "no-" mean to turn flag off. if (strncmp(arg, "no-", 3) == 0) { arg += 3; val = 0; } ! for (; flags->name; flags++) { ! const char *opt = match_option(arg, flags->name); ! int rc; ! ! if (!opt) ! continue; ! ! if (flags->fun) { ! int options = 0; ! if (!val) ! options |= OPT_INVERSE; ! if ((rc = flags->fun(ori, opt, flags, options))) ! return rc; ! } ! ! // boolean flag ! if (opt[0] == '\0' && flags->flag) { ! if (flags->mask & OPT_INVERSE) ! val = !val; ! *flags->flag = val; return 1; } + } // not handled return 0; } + + #define OPTNUM_ZERO_IS_INF 1 + #define OPTNUM_UNLIMITED 2 + + #define OPT_NUMERIC(NAME, TYPE, FUNCTION) \ + static int opt_##NAME(const char *arg, const char *opt, TYPE *ptr, int flag) \ + { \ + char *end; \ + TYPE val; \ + \ + val = FUNCTION(opt, &end, 0); \ + if (*end != '\0' || end == opt) { \ + if ((flag & OPTNUM_UNLIMITED) && !strcmp(opt, "unlimited")) \ + val = ~val; \ + else \ + die("error: wrong argument to \'%s\'", arg); \ + } \ + if ((flag & OPTNUM_ZERO_IS_INF) && val == 0) \ + val = ~val; \ + *ptr = val; \ + return 1; \ + } + + OPT_NUMERIC(ullong, unsigned long long, strtoull) + OPT_NUMERIC(uint, unsigned int, strtoul) + + static char **handle_switch_o(char *arg, char **next) { if (!strcmp (arg, "o")) { // "-o foo" if (!*++next) die("argument to '-o' is missing"); + outfile = *next; } // else "-ofoo" return next; } ! static const struct flag warnings[] = { { "address", &Waddress }, { "address-space", &Waddress_space }, { "bitwise", &Wbitwise }, + { "bitwise-pointer", &Wbitwise_pointer}, + { "cast-from-as", &Wcast_from_as }, { "cast-to-as", &Wcast_to_as }, { "cast-truncate", &Wcast_truncate }, { "constant-suffix", &Wconstant_suffix }, { "constexpr-not-const", &Wconstexpr_not_const}, { "context", &Wcontext },
*** 551,571 **** --- 653,677 ---- { "do-while", &Wdo_while }, { "enum-mismatch", &Wenum_mismatch }, { "external-function-has-definition", &Wexternal_function_has_definition }, { "implicit-int", &Wimplicit_int }, { "init-cstring", &Winit_cstring }, + { "int-to-pointer-cast", &Wint_to_pointer_cast }, { "memcpy-max-count", &Wmemcpy_max_count }, { "non-pointer-null", &Wnon_pointer_null }, { "old-initializer", &Wold_initializer }, { "old-style-definition", &Wold_style_definition }, { "one-bit-signed-bitfield", &Wone_bit_signed_bitfield }, { "override-init", &Woverride_init }, { "override-init-all", &Woverride_init_all }, { "paren-string", &Wparen_string }, + { "pointer-to-int-cast", &Wpointer_to_int_cast }, { "ptr-subtraction-blows", &Wptr_subtraction_blows }, { "return-void", &Wreturn_void }, { "shadow", &Wshadow }, + { "shift-count-negative", &Wshift_count_negative }, + { "shift-count-overflow", &Wshift_count_overflow }, { "sizeof-bool", &Wsizeof_bool }, { "strict-prototypes", &Wstrict_prototypes }, { "pointer-arith", &Wpointer_arith }, { "sparse-error", &Wsparse_error }, { "tautological-compare", &Wtautological_compare },
*** 582,592 **** WARNING_ON, WARNING_FORCE_OFF }; ! static char **handle_onoff_switch(char *arg, char **next, const struct warning warnings[], int n) { int flag = WARNING_ON; char *p = arg + 1; unsigned i; --- 688,698 ---- WARNING_ON, WARNING_FORCE_OFF }; ! static char **handle_onoff_switch(char *arg, char **next, const struct flag warnings[], int n) { int flag = WARNING_ON; char *p = arg + 1; unsigned i;
*** 593,602 **** --- 699,709 ---- if (!strcmp(p, "sparse-all")) { for (i = 0; i < n; i++) { if (*warnings[i].flag != WARNING_FORCE_OFF && warnings[i].flag != &Wsparse_error) *warnings[i].flag = WARNING_ON; } + return NULL; } // Prefixes "no" and "no-" mean to turn warning off. if (p[0] == 'n' && p[1] == 'o') { p += 2;
*** 624,636 **** // Unknown. return next; } ! static struct warning debugs[] = { ! { "entry", &dbg_entry}, { "dead", &dbg_dead}, }; static char **handle_switch_v(char *arg, char **next) { --- 731,747 ---- // Unknown. return next; } ! static struct flag debugs[] = { ! { "compound", &dbg_compound}, { "dead", &dbg_dead}, + { "domtree", &dbg_domtree}, + { "entry", &dbg_entry}, + { "ir", &dbg_ir}, + { "postorder", &dbg_postorder}, }; static char **handle_switch_v(char *arg, char **next) {
*** 643,667 **** verbose++; } while (*++arg == 'v'); return next; } - static struct warning dumps[] = { - { "D", &dump_macro_defs}, - }; - static char **handle_switch_d(char *arg, char **next) { ! char ** ret = handle_onoff_switch(arg, next, dumps, ARRAY_SIZE(dumps)); ! if (ret) ! return ret; return next; } ! static void handle_onoff_switch_finalize(const struct warning warnings[], int n) { unsigned i; for (i = 0; i < n; i++) { if (*warnings[i].flag == WARNING_FORCE_OFF) --- 754,796 ---- verbose++; } while (*++arg == 'v'); return next; } static char **handle_switch_d(char *arg, char **next) { ! char *arg_char = arg + 1; + /* + * -d<CHARS>, where <CHARS> is a sequence of characters, not preceded + * by a space. If you specify characters whose behaviour conflicts, + * the result is undefined. + */ + while (*arg_char) { + switch (*arg_char) { + case 'M': /* dump just the macro definitions */ + dump_macros_only = 1; + dump_macro_defs = 0; + break; + case 'D': /* like 'M', but also output pre-processed text */ + dump_macro_defs = 1; + dump_macros_only = 0; + break; + case 'N': /* like 'D', but only output macro names not bodies */ + break; + case 'I': /* like 'D', but also output #include directives */ + break; + case 'U': /* like 'D', but only output expanded macros */ + break; + } + arg_char++; + } return next; } ! static void handle_onoff_switch_finalize(const struct flag warnings[], int n) { unsigned i; for (i = 0; i < n; i++) { if (*warnings[i].flag == WARNING_FORCE_OFF)
*** 715,806 **** static char **handle_switch_O(char *arg, char **next) { int level = 1; if (arg[1] >= '0' && arg[1] <= '9') level = arg[1] - '0'; ! optimize = level; optimize_size = arg[1] == 's'; return next; } ! static char **handle_switch_fmemcpy_max_count(char *arg, char **next) { ! unsigned long long val; char *end; ! val = strtoull(arg, &end, 0); ! if (*end != '\0' || end == arg) ! die("error: missing argument to \"-fmemcpy-max-count=\""); - if (val == 0) - val = ~0ULL; - fmemcpy_max_count = val; - return next; - } - - static char **handle_switch_ftabstop(char *arg, char **next) - { - char *end; - unsigned long val; - - if (*arg == '\0') - die("error: missing argument to \"-ftabstop=\""); - /* we silently ignore silly values */ ! val = strtoul(arg, &end, 10); if (*end == '\0' && 1 <= val && val <= 100) tabstop = val; ! return next; } ! static int funsigned_char; ! static void handle_funsigned_char(void) { ! if (funsigned_char) { ! char_ctype.ctype.modifiers &= ~MOD_SIGNED; ! char_ctype.ctype.modifiers |= MOD_UNSIGNED; } } ! static char **handle_switch_fdump(char *arg, char **next) { ! if (!strncmp(arg, "linearize", 9)) { ! arg += 9; ! if (*arg == '\0') ! fdump_linearize = 1; ! else if (!strcmp(arg, "=only")) ! fdump_linearize = 2; ! else ! goto err; } ! /* ignore others flags */ ! return next; ! err: ! die("error: unknown flag \"-fdump-%s\"", arg); } ! static char **handle_switch_f(char *arg, char **next) { ! arg++; ! if (!strncmp(arg, "tabstop=", 8)) ! return handle_switch_ftabstop(arg+8, next); ! if (!strncmp(arg, "dump-", 5)) ! return handle_switch_fdump(arg+5, next); ! if (!strncmp(arg, "memcpy-max-count=", 17)) ! return handle_switch_fmemcpy_max_count(arg+17, next); ! if (!strcmp(arg, "unsigned-char")) { ! funsigned_char = 1; ! return next; ! } ! /* handle switches w/ arguments above, boolean and only boolean below */ ! if (handle_simple_switch(arg, "mem-report", &fmem_report)) return next; return next; } --- 844,962 ---- static char **handle_switch_O(char *arg, char **next) { int level = 1; if (arg[1] >= '0' && arg[1] <= '9') level = arg[1] - '0'; ! optimize_level = level; optimize_size = arg[1] == 's'; return next; } ! static int handle_ftabstop(const char *arg, const char *opt, const struct flag *flag, int options) { ! unsigned long val; char *end; ! if (*opt == '\0') ! die("error: missing argument to \"%s\"", arg); /* we silently ignore silly values */ ! val = strtoul(opt, &end, 10); if (*end == '\0' && 1 <= val && val <= 100) tabstop = val; ! return 1; } ! static int handle_fpasses(const char *arg, const char *opt, const struct flag *flag, int options) { ! unsigned long mask; ! ! mask = flag->mask; ! if (*opt == '\0') { ! if (options & OPT_INVERSE) ! fpasses &= ~mask; ! else ! fpasses |= mask; ! return 1; } + if (options & OPT_INVERSE) + return 0; + if (!strcmp(opt, "-enable")) { + fpasses |= mask; + return 1; + } + if (!strcmp(opt, "-disable")) { + fpasses &= ~mask; + return 1; + } + if (!strcmp(opt, "=last")) { + // clear everything above + mask |= mask - 1; + fpasses &= mask; + return 1; + } + return 0; } ! static int handle_fdiagnostic_prefix(const char *arg, const char *opt, const struct flag *flag, int options) { ! switch (*opt) { ! case '\0': ! diag_prefix = "sparse"; ! return 1; ! case '=': ! diag_prefix = xasprintf("%s", opt+1); ! return 1; ! default: ! return 0; } + } ! static int handle_fdump_ir(const char *arg, const char *opt, const struct flag *flag, int options) ! { ! static const struct mask_map dump_ir_options[] = { ! { "", PASS_LINEARIZE }, ! { "linearize", PASS_LINEARIZE }, ! { "mem2reg", PASS_MEM2REG }, ! { "final", PASS_FINAL }, ! { }, ! }; ! return handle_suboption_mask(arg, opt, dump_ir_options, &fdump_ir); } ! static int handle_fmemcpy_max_count(const char *arg, const char *opt, const struct flag *flag, int options) { ! opt_ullong(arg, opt, &fmemcpy_max_count, OPTNUM_ZERO_IS_INF|OPTNUM_UNLIMITED); ! return 1; ! } ! static int handle_fmax_warnings(const char *arg, const char *opt, const struct flag *flag, int options) ! { ! opt_uint(arg, opt, &fmax_warnings, OPTNUM_UNLIMITED); ! return 1; ! } ! static struct flag fflags[] = { ! { "diagnostic-prefix", NULL, handle_fdiagnostic_prefix }, ! { "dump-ir", NULL, handle_fdump_ir }, ! { "linearize", NULL, handle_fpasses, PASS_LINEARIZE }, ! { "max-warnings=", NULL, handle_fmax_warnings }, ! { "mem-report", &fmem_report }, ! { "memcpy-max-count=", NULL, handle_fmemcpy_max_count }, ! { "tabstop=", NULL, handle_ftabstop }, ! { "mem2reg", NULL, handle_fpasses, PASS_MEM2REG }, ! { "optim", NULL, handle_fpasses, PASS_OPTIM }, ! { "signed-char", &funsigned_char, NULL, OPT_INVERSE }, ! { "unsigned-char", &funsigned_char, NULL, }, ! { }, ! }; ! static char **handle_switch_f(char *arg, char **next) ! { ! if (handle_switches(arg-1, arg+1, fflags)) return next; return next; }
*** 818,833 **** standard = STANDARD_C89; return next; } ! static char **handle_switch_s(char *arg, char **next) { ! if (!strncmp (arg, "std=", 4)) ! { ! arg += 4; ! if (!strcmp (arg, "c89") || !strcmp (arg, "iso9899:1990")) standard = STANDARD_C89; else if (!strcmp (arg, "iso9899:199409")) --- 974,986 ---- standard = STANDARD_C89; return next; } ! static char **handle_switch_s(const char *arg, char **next) { ! if ((arg = match_option(arg, "std="))) { if (!strcmp (arg, "c89") || !strcmp (arg, "iso9899:1990")) standard = STANDARD_C89; else if (!strcmp (arg, "iso9899:199409"))
*** 894,903 **** --- 1047,1063 ---- return handle_base_dir(arg, next); return next; } + static char **handle_switch_x(char *arg, char **next) + { + if (!*++next) + die("missing argument for -x option"); + return next; + } + static char **handle_version(char *arg, char **next) { printf("%s\n", SPARSE_VERSION); exit(0); }
*** 908,918 **** /* Ignore smatch's --param-mapper */ if (strcmp(arg, "-mapper") == 0) return next; - /* For now just skip any '--param=*' or '--param *' */ if (*arg == '\0') { value = *++next; } else if (isspace((unsigned char)*arg) || *arg == '=') { value = ++arg; --- 1068,1077 ----
*** 970,979 **** --- 1129,1139 ---- case 'O': return handle_switch_O(arg, next); case 's': return handle_switch_s(arg, next); case 'U': return handle_switch_U(arg, next); case 'v': return handle_switch_v(arg, next); case 'W': return handle_switch_W(arg, next); + case 'x': return handle_switch_x(arg, next); case '-': return handle_long_options(arg + 1, next); default: break; }
*** 982,1231 **** * they're probably gcc switches */ return next; } ! static void predefined_sizeof(const char *name, unsigned bits) { ! add_pre_buffer("#weak_define __SIZEOF_%s__ %d\n", name, bits/8); } ! static void predefined_max(const char *name, const char *suffix, unsigned bits) { ! unsigned long long max = (1ULL << (bits - 1 )) - 1; ! add_pre_buffer("#weak_define __%s_MAX__ %#llx%s\n", name, max, suffix); } ! static void predefined_type_size(const char *name, const char *suffix, unsigned bits) { ! predefined_max(name, suffix, bits); ! predefined_sizeof(name, bits); } ! static void predefined_macros(void) { ! add_pre_buffer("#define __CHECKER__ 1\n"); ! 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); ! predefined_type_size("INT", "", bits_in_int); ! predefined_type_size("LONG", "L", bits_in_long); ! predefined_type_size("LONG_LONG", "LL", bits_in_longlong); ! predefined_sizeof("INT128", 128); ! predefined_sizeof("SIZE_T", bits_in_pointer); ! predefined_sizeof("PTRDIFF_T", bits_in_pointer); ! predefined_sizeof("POINTER", bits_in_pointer); ! predefined_sizeof("FLOAT", bits_in_float); ! 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"); ! add_pre_buffer("#weak_define __PRAGMA_REDEFINE_EXTNAME 1\n"); ! /* ! * This is far from perfect... ! */ ! #ifdef __sun ! add_pre_buffer("#weak_define __unix__ 1\n"); ! add_pre_buffer("#weak_define __unix 1\n"); ! add_pre_buffer("#weak_define unix 1\n"); ! add_pre_buffer("#weak_define __sun__ 1\n"); ! add_pre_buffer("#weak_define __sun 1\n"); ! add_pre_buffer("#weak_define sun 1\n"); ! add_pre_buffer("#weak_define __svr4__ 1\n"); ! #endif ! } ! void declare_builtin_functions(void) ! { ! /* Gaah. gcc knows tons of builtin <string.h> functions */ ! add_pre_buffer("extern void *__builtin_memchr(const void *, int, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern void *__builtin_memcpy(void *, const void *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern void *__builtin_mempcpy(void *, const void *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern void *__builtin_memmove(void *, const void *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern void *__builtin_memset(void *, int, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern int __builtin_memcmp(const void *, const void *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern char *__builtin_strcat(char *, const char *);\n"); ! add_pre_buffer("extern char *__builtin_strncat(char *, const char *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern int __builtin_strcmp(const char *, const char *);\n"); ! add_pre_buffer("extern int __builtin_strncmp(const char *, const char *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern int __builtin_strcasecmp(const char *, const char *);\n"); ! add_pre_buffer("extern int __builtin_strncasecmp(const char *, const char *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern char *__builtin_strchr(const char *, int);\n"); ! add_pre_buffer("extern char *__builtin_strrchr(const char *, int);\n"); ! add_pre_buffer("extern char *__builtin_strcpy(char *, const char *);\n"); ! add_pre_buffer("extern char *__builtin_strncpy(char *, const char *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern char *__builtin_strdup(const char *);\n"); ! add_pre_buffer("extern char *__builtin_strndup(const char *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern __SIZE_TYPE__ __builtin_strspn(const char *, const char *);\n"); ! add_pre_buffer("extern __SIZE_TYPE__ __builtin_strcspn(const char *, const char *);\n"); ! add_pre_buffer("extern char * __builtin_strpbrk(const char *, const char *);\n"); ! add_pre_buffer("extern char* __builtin_stpcpy(const char *, const char*);\n"); ! add_pre_buffer("extern char* __builtin_stpncpy(const char *, const char*, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern __SIZE_TYPE__ __builtin_strlen(const char *);\n"); ! add_pre_buffer("extern char *__builtin_strstr(const char *, const char *);\n"); ! add_pre_buffer("extern char *__builtin_strcasestr(const char *, const char *);\n"); ! add_pre_buffer("extern char *__builtin_strnstr(const char *, const char *, __SIZE_TYPE__);\n"); ! /* And even some from <strings.h> */ ! add_pre_buffer("extern int __builtin_bcmp(const void *, const void *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern void __builtin_bcopy(const void *, void *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern void __builtin_bzero(void *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern char*__builtin_index(const char *, int);\n"); ! add_pre_buffer("extern char*__builtin_rindex(const char *, int);\n"); ! /* And bitwise operations.. */ ! add_pre_buffer("extern int __builtin_clrsb(int);\n"); ! add_pre_buffer("extern int __builtin_clrsbl(long);\n"); ! add_pre_buffer("extern int __builtin_clrsbll(long long);\n"); ! add_pre_buffer("extern int __builtin_clz(int);\n"); ! add_pre_buffer("extern int __builtin_clzl(long);\n"); ! add_pre_buffer("extern int __builtin_clzll(long long);\n"); ! add_pre_buffer("extern int __builtin_ctz(int);\n"); ! add_pre_buffer("extern int __builtin_ctzl(long);\n"); ! add_pre_buffer("extern int __builtin_ctzll(long long);\n"); ! add_pre_buffer("extern int __builtin_ffs(int);\n"); ! add_pre_buffer("extern int __builtin_ffsl(long);\n"); ! add_pre_buffer("extern int __builtin_ffsll(long long);\n"); ! add_pre_buffer("extern int __builtin_parity(unsigned int);\n"); ! add_pre_buffer("extern int __builtin_parityl(unsigned long);\n"); ! add_pre_buffer("extern int __builtin_parityll(unsigned long long);\n"); ! add_pre_buffer("extern int __builtin_popcount(unsigned int);\n"); ! add_pre_buffer("extern int __builtin_popcountl(unsigned long);\n"); ! add_pre_buffer("extern int __builtin_popcountll(unsigned long long);\n"); ! /* And byte swaps.. */ ! add_pre_buffer("extern unsigned short __builtin_bswap16(unsigned short);\n"); ! add_pre_buffer("extern unsigned int __builtin_bswap32(unsigned int);\n"); ! add_pre_buffer("extern unsigned long long __builtin_bswap64(unsigned long long);\n"); ! /* And atomic memory access functions.. */ ! add_pre_buffer("extern int __sync_fetch_and_add(void *, ...);\n"); ! add_pre_buffer("extern int __sync_fetch_and_sub(void *, ...);\n"); ! add_pre_buffer("extern int __sync_fetch_and_or(void *, ...);\n"); ! add_pre_buffer("extern int __sync_fetch_and_and(void *, ...);\n"); ! add_pre_buffer("extern int __sync_fetch_and_xor(void *, ...);\n"); ! add_pre_buffer("extern int __sync_fetch_and_nand(void *, ...);\n"); ! add_pre_buffer("extern int __sync_add_and_fetch(void *, ...);\n"); ! add_pre_buffer("extern int __sync_sub_and_fetch(void *, ...);\n"); ! add_pre_buffer("extern int __sync_or_and_fetch(void *, ...);\n"); ! add_pre_buffer("extern int __sync_and_and_fetch(void *, ...);\n"); ! add_pre_buffer("extern int __sync_xor_and_fetch(void *, ...);\n"); ! add_pre_buffer("extern int __sync_nand_and_fetch(void *, ...);\n"); ! add_pre_buffer("extern int __sync_bool_compare_and_swap(void *, ...);\n"); ! add_pre_buffer("extern int __sync_val_compare_and_swap(void *, ...);\n"); ! add_pre_buffer("extern void __sync_synchronize();\n"); ! add_pre_buffer("extern int __sync_lock_test_and_set(void *, ...);\n"); ! add_pre_buffer("extern void __sync_lock_release(void *, ...);\n"); ! /* And some random ones.. */ ! add_pre_buffer("extern void *__builtin_return_address(unsigned int);\n"); ! add_pre_buffer("extern void *__builtin_extract_return_addr(void *);\n"); ! add_pre_buffer("extern void *__builtin_frame_address(unsigned int);\n"); ! add_pre_buffer("extern void __builtin_trap(void);\n"); ! add_pre_buffer("extern void *__builtin_alloca(__SIZE_TYPE__);\n"); ! add_pre_buffer("extern void __builtin_prefetch (const void *, ...);\n"); ! add_pre_buffer("extern long __builtin_alpha_extbl(long, long);\n"); ! add_pre_buffer("extern long __builtin_alpha_extwl(long, long);\n"); ! add_pre_buffer("extern long __builtin_alpha_insbl(long, long);\n"); ! add_pre_buffer("extern long __builtin_alpha_inswl(long, long);\n"); ! add_pre_buffer("extern long __builtin_alpha_insql(long, long);\n"); ! add_pre_buffer("extern long __builtin_alpha_inslh(long, long);\n"); ! add_pre_buffer("extern long __builtin_alpha_cmpbge(long, long);\n"); ! add_pre_buffer("extern int __builtin_abs(int);\n"); ! add_pre_buffer("extern long __builtin_labs(long);\n"); ! add_pre_buffer("extern long long __builtin_llabs(long long);\n"); ! add_pre_buffer("extern double __builtin_fabs(double);\n"); ! add_pre_buffer("extern __SIZE_TYPE__ __builtin_va_arg_pack_len(void);\n"); ! /* 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" ! ); ! /* And some floating point stuff.. */ ! add_pre_buffer("extern int __builtin_isgreater(float, float);\n"); ! add_pre_buffer("extern int __builtin_isgreaterequal(float, float);\n"); ! add_pre_buffer("extern int __builtin_isless(float, float);\n"); ! add_pre_buffer("extern int __builtin_islessequal(float, float);\n"); ! add_pre_buffer("extern int __builtin_islessgreater(float, float);\n"); ! add_pre_buffer("extern int __builtin_isunordered(float, float);\n"); ! /* And some INFINITY / NAN stuff.. */ ! add_pre_buffer("extern double __builtin_huge_val(void);\n"); ! add_pre_buffer("extern float __builtin_huge_valf(void);\n"); ! add_pre_buffer("extern long double __builtin_huge_vall(void);\n"); ! add_pre_buffer("extern double __builtin_inf(void);\n"); ! add_pre_buffer("extern float __builtin_inff(void);\n"); ! add_pre_buffer("extern long double __builtin_infl(void);\n"); ! add_pre_buffer("extern double __builtin_nan(const char *);\n"); ! add_pre_buffer("extern float __builtin_nanf(const char *);\n"); ! add_pre_buffer("extern long double __builtin_nanl(const char *);\n"); ! add_pre_buffer("extern int __builtin_isinf_sign(float);\n"); ! add_pre_buffer("extern int __builtin_isfinite(float);\n"); ! add_pre_buffer("extern int __builtin_isnan(float);\n"); ! /* And some __FORTIFY_SOURCE ones.. */ ! add_pre_buffer ("extern __SIZE_TYPE__ __builtin_object_size(const void *, int);\n"); ! add_pre_buffer ("extern void * __builtin___memcpy_chk(void *, const void *, __SIZE_TYPE__, __SIZE_TYPE__);\n"); ! add_pre_buffer ("extern void * __builtin___memmove_chk(void *, const void *, __SIZE_TYPE__, __SIZE_TYPE__);\n"); ! add_pre_buffer ("extern void * __builtin___mempcpy_chk(void *, const void *, __SIZE_TYPE__, __SIZE_TYPE__);\n"); ! add_pre_buffer ("extern void * __builtin___memset_chk(void *, int, __SIZE_TYPE__, __SIZE_TYPE__);\n"); ! add_pre_buffer ("extern int __builtin___sprintf_chk(char *, int, __SIZE_TYPE__, const char *, ...);\n"); ! add_pre_buffer ("extern int __builtin___snprintf_chk(char *, __SIZE_TYPE__, int , __SIZE_TYPE__, const char *, ...);\n"); ! add_pre_buffer ("extern char * __builtin___stpcpy_chk(char *, const char *, __SIZE_TYPE__);\n"); ! add_pre_buffer ("extern char * __builtin___strcat_chk(char *, const char *, __SIZE_TYPE__);\n"); ! add_pre_buffer ("extern char * __builtin___strcpy_chk(char *, const char *, __SIZE_TYPE__);\n"); ! add_pre_buffer ("extern char * __builtin___strncat_chk(char *, const char *, __SIZE_TYPE__, __SIZE_TYPE__);\n"); ! add_pre_buffer ("extern char * __builtin___strncpy_chk(char *, const char *, __SIZE_TYPE__, __SIZE_TYPE__);\n"); ! add_pre_buffer ("extern int __builtin___vsprintf_chk(char *, int, __SIZE_TYPE__, const char *, __builtin_va_list);\n"); ! add_pre_buffer ("extern int __builtin___vsnprintf_chk(char *, __SIZE_TYPE__, int, __SIZE_TYPE__, const char *, __builtin_va_list ap);\n"); ! add_pre_buffer ("extern void __builtin_unreachable(void);\n"); ! /* And some from <stdlib.h> */ ! add_pre_buffer("extern void __builtin_abort(void);\n"); ! add_pre_buffer("extern void *__builtin_calloc(__SIZE_TYPE__, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern void __builtin_exit(int);\n"); ! add_pre_buffer("extern void *__builtin_malloc(__SIZE_TYPE__);\n"); ! add_pre_buffer("extern void *__builtin_realloc(void *, __SIZE_TYPE__);\n"); ! add_pre_buffer("extern void __builtin_free(void *);\n"); ! /* And some from <stdio.h> */ ! add_pre_buffer("extern int __builtin_printf(const char *, ...);\n"); ! add_pre_buffer("extern int __builtin_sprintf(char *, const char *, ...);\n"); ! add_pre_buffer("extern int __builtin_snprintf(char *, __SIZE_TYPE__, const char *, ...);\n"); ! add_pre_buffer("extern int __builtin_puts(const char *);\n"); ! add_pre_buffer("extern int __builtin_vprintf(const char *, __builtin_va_list);\n"); ! add_pre_buffer("extern int __builtin_vsprintf(char *, const char *, __builtin_va_list);\n"); ! add_pre_buffer("extern int __builtin_vsnprintf(char *, __SIZE_TYPE__, const char *, __builtin_va_list ap);\n"); } ! 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); --- 1142,1428 ---- * they're probably gcc switches */ return next; } ! #define PTYPE_SIZEOF (1U << 0) ! #define PTYPE_T (1U << 1) ! #define PTYPE_MAX (1U << 2) ! #define PTYPE_MIN (1U << 3) ! #define PTYPE_WIDTH (1U << 4) ! #define PTYPE_TYPE (1U << 5) ! #define PTYPE_ALL (PTYPE_MAX|PTYPE_SIZEOF|PTYPE_WIDTH) ! #define PTYPE_ALL_T (PTYPE_MAX|PTYPE_SIZEOF|PTYPE_WIDTH|PTYPE_T) ! ! static void predefined_sizeof(const char *name, const char *suffix, unsigned bits) { ! char buf[32]; ! ! snprintf(buf, sizeof(buf), "__SIZEOF_%s%s__", name, suffix); ! predefine(buf, 1, "%d", bits/8); } ! static void predefined_width(const char *name, unsigned bits) { ! char buf[32]; ! snprintf(buf, sizeof(buf), "__%s_WIDTH__", name); ! predefine(buf, 1, "%d", bits); } ! static void predefined_max(const char *name, struct symbol *type) { ! const char *suffix = builtin_type_suffix(type); ! unsigned bits = type->bit_size - is_signed_type(type); ! unsigned long long max = bits_mask(bits); ! char buf[32]; ! ! snprintf(buf, sizeof(buf), "__%s_MAX__", name); ! predefine(buf, 1, "%#llx%s", max, suffix); } ! static void predefined_min(const char *name, struct symbol *type) { ! const char *suffix = builtin_type_suffix(type); ! char buf[32]; ! snprintf(buf, sizeof(buf), "__%s_MIN__", name); ! if (is_signed_type(type)) ! predefine(buf, 1, "(-__%s_MAX__ - 1)", name); ! else ! predefine(buf, 1, "0%s", suffix); ! } ! static void predefined_type(const char *name, struct symbol *type) ! { ! const char *typename = builtin_typename(type); ! add_pre_buffer("#weak_define __%s_TYPE__ %s\n", name, typename); ! } ! static void predefined_ctype(const char *name, struct symbol *type, int flags) ! { ! unsigned bits = type->bit_size; ! if (flags & PTYPE_SIZEOF) { ! const char *suffix = (flags & PTYPE_T) ? "_T" : ""; ! predefined_sizeof(name, suffix, bits); ! } ! if (flags & PTYPE_MAX) ! predefined_max(name, type); ! if (flags & PTYPE_MIN) ! predefined_min(name, type); ! if (flags & PTYPE_TYPE) ! predefined_type(name, type); ! if (flags & PTYPE_WIDTH) ! predefined_width(name, bits); ! } ! static void predefined_macros(void) ! { ! 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; ! } ! predefine("__CHAR_BIT__", 1, "%d", bits_in_char); ! if (funsigned_char) ! predefine("__CHAR_UNSIGNED__", 1, "1"); ! predefined_ctype("SHORT", &short_ctype, PTYPE_SIZEOF); ! predefined_ctype("SHRT", &short_ctype, PTYPE_MAX|PTYPE_WIDTH); ! predefined_ctype("SCHAR", &schar_ctype, PTYPE_MAX|PTYPE_WIDTH); ! predefined_ctype("WCHAR", wchar_ctype, PTYPE_ALL_T|PTYPE_MIN|PTYPE_TYPE); ! predefined_ctype("WINT", wint_ctype, PTYPE_ALL_T|PTYPE_MIN|PTYPE_TYPE); ! predefined_ctype("CHAR16", &ushort_ctype, PTYPE_TYPE); ! predefined_ctype("CHAR32", &uint_ctype, PTYPE_TYPE); ! predefined_ctype("INT", &int_ctype, PTYPE_ALL); ! predefined_ctype("LONG", &long_ctype, PTYPE_ALL); ! predefined_ctype("LONG_LONG", &llong_ctype, PTYPE_ALL); ! predefined_ctype("INT8", &schar_ctype, PTYPE_MAX|PTYPE_TYPE); ! predefined_ctype("UINT8", &uchar_ctype, PTYPE_MAX|PTYPE_TYPE); ! predefined_ctype("INT16", &short_ctype, PTYPE_MAX|PTYPE_TYPE); ! predefined_ctype("UINT16", &ushort_ctype, PTYPE_MAX|PTYPE_TYPE); ! predefined_ctype("INT32", int32_ctype, PTYPE_MAX|PTYPE_TYPE); ! predefined_ctype("UINT32", uint32_ctype, PTYPE_MAX|PTYPE_TYPE); ! predefined_ctype("INT64", int64_ctype, PTYPE_MAX|PTYPE_TYPE); ! predefined_ctype("UINT64", uint64_ctype, PTYPE_MAX|PTYPE_TYPE); ! predefined_sizeof("INT128", "", 128); ! predefined_ctype("INTMAX", intmax_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); ! predefined_ctype("UINTMAX", uintmax_ctype, PTYPE_MAX|PTYPE_TYPE); ! predefined_ctype("INTPTR", ssize_t_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); ! predefined_ctype("UINTPTR", size_t_ctype, PTYPE_MAX|PTYPE_TYPE); ! predefined_ctype("PTRDIFF", ssize_t_ctype, PTYPE_ALL_T|PTYPE_TYPE); ! predefined_ctype("SIZE", size_t_ctype, PTYPE_ALL_T|PTYPE_TYPE); ! predefined_ctype("POINTER", &ptr_ctype, PTYPE_SIZEOF); ! predefined_sizeof("FLOAT", "", bits_in_float); ! predefined_sizeof("DOUBLE", "", bits_in_double); ! predefined_sizeof("LONG_DOUBLE", "", bits_in_longdouble); ! 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__"); ! } ! if (optimize_level) ! predefine("__OPTIMIZE__", 0, "1"); ! if (optimize_size) ! predefine("__OPTIMIZE_SIZE__", 0, "1"); ! ! // Temporary hacks ! predefine("__extension__", 0, NULL); ! predefine("__pragma__", 0, NULL); ! ! switch (arch_m64) { ! case ARCH_LP32: ! break; ! case ARCH_X32: ! predefine("__ILP32__", 1, "1"); ! predefine("_ILP32", 1, "1"); ! break; ! case ARCH_LP64: ! predefine("__LP64__", 1, "1"); ! predefine("__LP64", 1, "1"); ! predefine("_LP64", 1, "1"); ! break; ! case ARCH_LLP64: ! predefine("__LLP64__", 1, "1"); ! break; ! } ! ! switch (arch_mach) { ! case MACH_ARM64: ! predefine("__aarch64__", 1, "1"); ! break; ! case MACH_ARM: ! predefine("__arm__", 1, "1"); ! break; ! case MACH_M68K: ! predefine("__m68k__", 1, "1"); ! break; ! case MACH_MIPS64: ! if (arch_m64 == ARCH_LP64) ! predefine("__mips64", 1, "64"); ! /* fall-through */ ! case MACH_MIPS32: ! predefine("__mips", 1, "%d", ptr_ctype.bit_size); ! predefine("_MIPS_SZINT", 1, "%d", int_ctype.bit_size); ! predefine("_MIPS_SZLONG", 1, "%d", long_ctype.bit_size); ! predefine("_MIPS_SZPTR", 1, "%d", ptr_ctype.bit_size); ! break; ! case MACH_PPC64: ! if (arch_m64 == ARCH_LP64) { ! predefine("__powerpc64__", 1, "1"); ! predefine("__ppc64__", 1, "1"); ! predefine("__PPC64__", 1, "1"); ! } ! /* fall-through */ ! case MACH_PPC32: ! predefine("__powerpc__", 1, "1"); ! predefine("__powerpc", 1, "1"); ! predefine("__ppc__", 1, "1"); ! predefine("__PPC__", 1, "1"); ! break; ! case MACH_RISCV64: ! case MACH_RISCV32: ! predefine("__riscv", 1, "1"); ! predefine("__riscv_xlen", 1, "%d", ptr_ctype.bit_size); ! break; ! case MACH_S390X: ! predefine("__zarch__", 1, "1"); ! predefine("__s390x__", 1, "1"); ! predefine("__s390__", 1, "1"); ! break; ! case MACH_SPARC64: ! if (arch_m64 == ARCH_LP64) { ! predefine("__sparc_v9__", 1, "1"); ! predefine("__sparcv9__", 1, "1"); ! predefine("__sparcv9", 1, "1"); ! predefine("__sparc64__", 1, "1"); ! predefine("__arch64__", 1, "1"); ! } ! /* fall-through */ ! case MACH_SPARC32: ! predefine("__sparc__", 1, "1"); ! predefine("__sparc", 1, "1"); ! break; ! case MACH_X86_64: ! if (arch_m64 != ARCH_LP32) { ! predefine("__x86_64__", 1, "1"); ! predefine("__x86_64", 1, "1"); ! break; ! } ! /* fall-through */ ! case MACH_I386: ! predefine("__i386__", 1, "1"); ! predefine("__i386", 1, "1"); ! predefine("i386", 1, "1"); ! break; ! } ! ! predefine("__PRAGMA_REDEFINE_EXTNAME", 1, "1"); ! ! #ifdef __sun ! predefine("__unix__", 1, "1"); ! predefine("__unix", 1, "1"); ! predefine("unix", 1, "1"); ! predefine("__sun__", 1, "1"); ! predefine("__sun", 1, "1"); ! predefine("sun", 1, "1"); ! predefine("__svr4__", 1, "1"); ! #endif } ! static void create_builtin_stream(void) { ! // Temporary hack ! add_pre_buffer("#define _Pragma(x)\n"); /* 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);
*** 1234,1294 **** /* 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"); ! add_pre_buffer("#define _Pragma(x)\n"); ! ! // gcc defines __SIZE_TYPE__ to be size_t. For linux/i86 and ! // solaris/sparc that is really "unsigned int" and for linux/x86_64 ! // it is "long unsigned int". In either case we can probably ! // get away with this. We need the #weak_define as cgcc will define ! // the right __SIZE_TYPE__. ! if (size_t_ctype == &ulong_ctype) ! 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_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"); add_pre_buffer("#define __builtin_va_arg(arg,type) ({ type __va_arg_ret = *(type *)(arg); arg += sizeof(type); __va_arg_ret; })\n"); add_pre_buffer("#define __builtin_va_alist (*(void *)0)\n"); --- 1431,1442 ---- /* 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 __has_attribute(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"); add_pre_buffer("#define __builtin_va_arg(arg,type) ({ type __va_arg_ret = *(type *)(arg); arg += sizeof(type); __va_arg_ret; })\n"); add_pre_buffer("#define __builtin_va_alist (*(void *)0)\n");
*** 1296,1324 **** add_pre_buffer("#define __builtin_va_copy(dest, src) ({ dest = src; (void)0; })\n"); add_pre_buffer("#define __builtin_ms_va_copy(dest, src) ({ dest = src; (void)0; })\n"); 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) - 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) { int builtin = token && !token->pos.stream; // Preprocess the stream token = preprocess(token); ! if (dump_macro_defs && !builtin) dump_macro_definitions(); if (preprocess_only) { while (!eof_token(token)) { int prec = 1; struct token *next = token->next; --- 1444,1468 ---- add_pre_buffer("#define __builtin_va_copy(dest, src) ({ dest = src; (void)0; })\n"); add_pre_buffer("#define __builtin_ms_va_copy(dest, src) ({ dest = src; (void)0; })\n"); 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"); } static struct symbol_list *sparse_tokenstream(struct token *token) { int builtin = token && !token->pos.stream; // Preprocess the stream token = preprocess(token); ! if (dump_macro_defs || dump_macros_only) { ! if (!builtin) dump_macro_definitions(); + if (dump_macros_only) + return NULL; + } if (preprocess_only) { while (!eof_token(token)) { int prec = 1; struct token *next = token->next;
*** 1355,1379 **** } else { fd = open(filename, O_RDONLY); if (fd < 0) die("No such file: %s", filename); } // Tokenize the input stream token = tokenize(filename, fd, NULL, includepath); store_all_tokens(token); close(fd); return sparse_tokenstream(token); } - static int endswith(const char *str, const char *suffix) - { - const char *found = strstr(str, suffix); - return (found && strcmp(found, suffix) == 0); - } - /* * This handles the "-include" directive etc: we're in global * scope, and all types/macros etc will affect all the following * files. * --- 1499,1518 ---- } else { fd = open(filename, O_RDONLY); if (fd < 0) die("No such file: %s", filename); } + base_filename = filename; // Tokenize the input stream token = tokenize(filename, fd, NULL, includepath); store_all_tokens(token); close(fd); return sparse_tokenstream(token); } /* * This handles the "-include" directive etc: we're in global * scope, and all types/macros etc will affect all the following * files. *
*** 1391,1410 **** add_pre_buffer("#argv_include \"%s\"\n", cmdline_include[i]); return sparse_tokenstream(pre_buffer_begin); } struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list **filelist) { char **args; struct symbol_list *list; // Initialize symbol stream first, so that we can add defines etc init_symbols(); init_include_path(); ! progname = argv[0]; args = argv; for (;;) { char *arg = *++args; if (!arg) --- 1530,1555 ---- add_pre_buffer("#argv_include \"%s\"\n", cmdline_include[i]); return sparse_tokenstream(pre_buffer_begin); } + static int endswith(const char *str, const char *suffix) + { + const char *found = strstr(str, suffix); + return (found && strcmp(found, suffix) == 0); + } + struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list **filelist) { char **args; struct symbol_list *list; // Initialize symbol stream first, so that we can add defines etc init_symbols(); init_include_path(); ! diag_prefix = argv[0]; args = argv; for (;;) { char *arg = *++args; if (!arg)
*** 1417,1443 **** if (endswith(arg, ".a") || endswith(arg, ".so") || endswith(arg, ".so.1") || endswith(arg, ".o")) continue; ! add_ptr_list_notag(filelist, arg); } handle_switch_W_finalize(); handle_switch_v_finalize(); ! handle_arch_finalize(); list = NULL; ! if (!ptr_list_empty(filelist)) { // Initialize type system init_ctype(); - handle_funsigned_char(); - create_builtin_stream(); predefined_macros(); ! if (!preprocess_only) ! declare_builtin_functions(); list = sparse_initial(); /* * Protect the initial token allocations, since --- 1562,1597 ---- if (endswith(arg, ".a") || endswith(arg, ".so") || endswith(arg, ".so.1") || endswith(arg, ".o")) continue; ! add_ptr_list(filelist, arg); } handle_switch_W_finalize(); handle_switch_v_finalize(); ! // Redirect stdout if needed ! if (dump_macro_defs || preprocess_only) ! do_output = 1; ! if (do_output && outfile && strcmp(outfile, "-")) { ! if (!freopen(outfile, "w", stdout)) ! die("error: cannot open %s: %s", outfile, strerror(errno)); ! } + if (fdump_ir == 0) + fdump_ir = PASS_FINAL; + list = NULL; ! if (filelist) { // Initialize type system + init_target(); + handle_arch_finalize(); init_ctype(); predefined_macros(); ! create_builtin_stream(); ! declare_builtins(); list = sparse_initial(); /* * Protect the initial token allocations, since