136 insertions(+), 226 deletions(-), less 90 lines (except tests) only one set_flag() function required * can now turn off specific errors: -Werror -Wno-error=option * new interface: tcc_warning_c(warn_option)("format", args...); * new warning: -Wdiscarded-qualifiers (on by default) * new variable 'warn_all' for conditional warnings with -Wall see also the tests
Unified · Split
| @@ -510,10 +510,6 @@ static void strcat_printf(char *buf, int buf_size, const char *fmt, ...) · 509 unmodified lines | ||
| 510 | 510 | va_end(ap); |
| 511 | 511 | } |
| 512 | 512 | |
| 513 | −#define ERROR_WARN 0 | |
| 514 | −#define ERROR_NOABORT 1 | |
| 515 | −#define ERROR_ERROR 2 | |
| 516 | − | |
| 517 | 513 | PUB_FUNC void tcc_enter_state(TCCState *s1) |
| 518 | 514 | { |
| 519 | 515 | WAIT_SEM(); |
| @@ -526,6 +522,10 @@ PUB_FUNC void tcc_exit_state(void) · 6 unmodified lines | ||
| 526 | 522 | POST_SEM(); |
| 527 | 523 | } |
| 528 | 524 | |
| 525 | +#define ERROR_WARN 0 | |
| 526 | +#define ERROR_NOABORT 1 | |
| 527 | +#define ERROR_ERROR 2 | |
| 528 | + | |
| 529 | 529 | static void error1(int mode, const char *fmt, va_list ap) |
| 530 | 530 | { |
| 531 | 531 | char buf[2048]; |
| @@ -537,15 +537,26 @@ static void error1(int mode, const char *fmt, va_list ap) · 5 unmodified lines | ||
| 537 | 537 | /* can happen only if called from tcc_malloc(): 'out of memory' */ |
| 538 | 538 | goto no_file; |
| 539 | 539 | |
| 540 | − if (s1 && !s1->error_set_jmp_enabled) | |
| 540 | + if (!s1->error_set_jmp_enabled) | |
| 541 | 541 | /* tcc_state just was set by tcc_enter_state() */ |
| 542 | 542 | tcc_exit_state(); |
| 543 | 543 | |
| 544 | 544 | if (mode == ERROR_WARN) { |
| 545 | − if (s1->warn_mask & WARN_DISABLED) | |
| 546 | − return; | |
| 547 | − if (s1->warn_mask & WARN_ERROR_MASK) /* XXX individual ignorance */ | |
| 545 | + if (s1->warn_error) | |
| 548 | 546 | mode = ERROR_ERROR; |
| 547 | + if (s1->warn_num) { | |
| 548 | + /* handle tcc_warning_c(warn_option)(fmt, ...) */ | |
| 549 | + int wopt = *(&s1->warn_none + s1->warn_num); | |
| 550 | + s1->warn_num = 0; | |
| 551 | + if (0 == (wopt & WARN_ON)) | |
| 552 | + return; | |
| 553 | + if (wopt & WARN_ERR) | |
| 554 | + mode = ERROR_ERROR; | |
| 555 | + if (wopt & WARN_NOE) | |
| 556 | + mode = ERROR_WARN; | |
| 557 | + } | |
| 558 | + if (s1->warn_none) | |
| 559 | + return; | |
| 549 | 560 | } |
| 550 | 561 | |
| 551 | 562 | f = NULL; |
| @@ -786,7 +797,8 @@ LIBTCCAPI TCCState *tcc_new(void) · 234 unmodified lines | ||
| 786 | 797 | s->nocommon = 1; |
| 787 | 798 | s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/ |
| 788 | 799 | s->cversion = 199901; /* default unless -std=c11 is supplied */ |
| 789 | − s->warn_mask |= WARN_IMPLICIT_FUNCTION_DECLARATION; | |
| 800 | + s->warn_implicit_function_declaration = 1; | |
| 801 | + s->warn_discarded_qualifiers = 1; | |
| 790 | 802 | s->ms_extensions = 1; |
| 791 | 803 | |
| 792 | 804 | #ifdef CHAR_IS_UNSIGNED |
| @@ -1230,122 +1242,8 @@ LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path) · 437 unmodified lines | ||
| 1230 | 1242 | s->tcc_lib_path = tcc_strdup(path); |
| 1231 | 1243 | } |
| 1232 | 1244 | |
| 1233 | −#define WD_ALL (1u<<0) /* warning is activated when using -Wall */ | |
| 1234 | −#define WD_ERROR (1u<<1) /* can be used with -W[no-]error=X */ | |
| 1235 | −#define FD_INVERT (1u<<2) /* invert value before storing */ | |
| 1236 | − | |
| 1237 | −typedef struct FlagDef { | |
| 1238 | − uint16_t offset; | |
| 1239 | − uint16_t flags; | |
| 1240 | − const char *name; | |
| 1241 | −} FlagDef; | |
| 1242 | − | |
| 1243 | −static int no_flag(const char **pp) | |
| 1244 | −{ | |
| 1245 | − const char *p = *pp; | |
| 1246 | − if (*p != 'n' || *++p != 'o' || *++p != '-') | |
| 1247 | − return 0; | |
| 1248 | − *pp = p + 1; | |
| 1249 | − return 1; | |
| 1250 | −} | |
| 1251 | − | |
| 1252 | −ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, const char *name) | |
| 1253 | −{ | |
| 1254 | − int value, ret; | |
| 1255 | − const FlagDef *p; | |
| 1256 | − const char *r; | |
| 1257 | − | |
| 1258 | − value = 1; | |
| 1259 | − r = name; | |
| 1260 | − if (no_flag(&r)) | |
| 1261 | − value = 0; | |
| 1262 | − | |
| 1263 | − for (ret = -1, p = flags; p->name; ++p) { | |
| 1264 | − if (ret) { | |
| 1265 | − if (strcmp(r, p->name)) | |
| 1266 | − continue; | |
| 1267 | − } else { | |
| 1268 | − if (0 == (p->flags & WD_ALL)) | |
| 1269 | − continue; | |
| 1270 | − } | |
| 1271 | − if (p->offset) { | |
| 1272 | − *((unsigned char *)s + p->offset) = | |
| 1273 | − p->flags & FD_INVERT ? !value : value; | |
| 1274 | − if (ret) | |
| 1275 | − return 0; | |
| 1276 | − } else { | |
| 1277 | − ret = 0; | |
| 1278 | − } | |
| 1279 | − } | |
| 1280 | − return ret; | |
| 1281 | −} | |
| 1282 | − | |
| 1283 | −ST_FUNC int set_W_flag(TCCState *s, const char *optarg) | |
| 1284 | −{ | |
| 1285 | − static struct a_W_flag{ | |
| 1286 | − uint32_t wbit; | |
| 1287 | − uint32_t flags; | |
| 1288 | − char const *name; | |
| 1289 | − } const opts[] = { | |
| 1290 | − {WARN_ALL, 0, "all"}, | |
| 1291 | − {WARN_ERROR | (WARN_ERROR << WARN_ERROR_SHIFT), 0, "error"}, | |
| 1292 | − {WARN_UNSUPPORTED, WD_ERROR, "unsupported"}, | |
| 1293 | − {WARN_GCC_COMPAT, WD_ERROR, "gcc-compat"}, | |
| 1294 | − {WARN_WRITE_STRINGS, WD_ERROR | WD_ALL, "write-strings"}, | |
| 1295 | − {WARN_IMPLICIT_FUNCTION_DECLARATION, WD_ERROR | WD_ALL, | |
| 1296 | − "implicit-function-declaration"} | |
| 1297 | − }, *p; | |
| 1298 | − | |
| 1299 | − int ret; | |
| 1300 | − unsigned char mode; | |
| 1301 | − const char *r, *sub; | |
| 1302 | − | |
| 1303 | − mode = 1; | |
| 1304 | − r = optarg; | |
| 1305 | − if (no_flag(&r)) | |
| 1306 | − mode = 0; | |
| 1307 | − | |
| 1308 | − if ((sub = strchr(r, '=')) != NULL) { | |
| 1309 | − if (strncmp(r, "error", (uintptr_t)(sub - r))) | |
| 1310 | − return -1; | |
| 1311 | − r = ++sub; | |
| 1312 | − mode |= 2; | |
| 1313 | − } | |
| 1314 | − | |
| 1315 | − for (ret = -1, p = opts; p < &opts[countof(opts)]; ++p) { | |
| 1316 | − if (ret) { | |
| 1317 | − if (strcmp(r, p->name)) | |
| 1318 | − continue; | |
| 1319 | − if ((mode & 2) && !(p->flags & WD_ERROR)) | |
| 1320 | − break; | |
| 1321 | − } else { | |
| 1322 | − if (0 == (p->flags & WD_ALL)) | |
| 1323 | − continue; | |
| 1324 | − } | |
| 1325 | − | |
| 1326 | − if (p->wbit == WARN_ALL) { | |
| 1327 | − /* Start a loop over all the rest */ | |
| 1328 | − ret = 0; | |
| 1329 | − continue; | |
| 1330 | − } | |
| 1331 | − | |
| 1332 | − if (mode & 1) { | |
| 1333 | − s->warn_mask |= p->wbit; | |
| 1334 | − if (mode & 2) | |
| 1335 | − s->warn_mask |= p->wbit << WARN_ERROR_SHIFT; | |
| 1336 | − } else { | |
| 1337 | − s->warn_mask &= ~(p->wbit << ((mode & 2) ? WARN_ERROR_SHIFT : 0)); | |
| 1338 | − } | |
| 1339 | − | |
| 1340 | − /* Done if not in "all" mode */ | |
| 1341 | − if (ret) { | |
| 1342 | − ret = 0; | |
| 1343 | − break; | |
| 1344 | − } | |
| 1345 | − } | |
| 1346 | − | |
| 1347 | − return ret; | |
| 1348 | −} | |
| 1245 | +/********************************************************/ | |
| 1246 | +/* options parser */ | |
| 1349 | 1247 | |
| 1350 | 1248 | static int strstart(const char *val, const char **str) |
| 1351 | 1249 | { |
| @@ -1388,7 +1286,7 @@ static int link_option(const char *str, const char *val, const char **ptr) · 36 unmodified lines | ||
| 1388 | 1286 | ret = 1; |
| 1389 | 1287 | if (q[0] == '?') { |
| 1390 | 1288 | ++q; |
| 1391 | − if (no_flag(&p)) | |
| 1289 | + if (strstart("no-", &p)) | |
| 1392 | 1290 | ret = -1; |
| 1393 | 1291 | } |
| 1394 | 1292 | |
| @@ -1536,10 +1434,8 @@ static int tcc_set_linker(TCCState *s, const char *option) · 141 unmodified lines | ||
| 1536 | 1434 | err: |
| 1537 | 1435 | tcc_error("unsupported linker option '%s'", option); |
| 1538 | 1436 | } |
| 1539 | − | |
| 1540 | − if (ignoring && NEED_WARNING(s, UNSUPPORTED)) | |
| 1541 | − tcc_warning("unsupported linker option '%s'", option); | |
| 1542 | − | |
| 1437 | + if (ignoring) | |
| 1438 | + tcc_warning_c(warn_unsupported)("unsupported linker option '%s'", option); | |
| 1543 | 1439 | option = skip_linker_arg(&p); |
| 1544 | 1440 | } |
| 1545 | 1441 | return 1; |
| @@ -1682,6 +1578,25 @@ static const TCCOption tcc_options[] = { · 136 unmodified lines | ||
| 1682 | 1578 | { NULL, 0, 0 }, |
| 1683 | 1579 | }; |
| 1684 | 1580 | |
| 1581 | +typedef struct FlagDef { | |
| 1582 | + uint16_t offset; | |
| 1583 | + uint16_t flags; | |
| 1584 | + const char *name; | |
| 1585 | +} FlagDef; | |
| 1586 | + | |
| 1587 | +#define WD_ALL 0x0001 /* warning is activated when using -Wall */ | |
| 1588 | +#define FD_INVERT 0x0002 /* invert value before storing */ | |
| 1589 | + | |
| 1590 | +static const FlagDef options_W[] = { | |
| 1591 | + { offsetof(TCCState, warn_all), WD_ALL, "all" }, | |
| 1592 | + { offsetof(TCCState, warn_error), 0, "error" }, | |
| 1593 | + { offsetof(TCCState, warn_write_strings), 0, "write-strings" }, | |
| 1594 | + { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, | |
| 1595 | + { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, "implicit-function-declaration" }, | |
| 1596 | + { offsetof(TCCState, warn_discarded_qualifiers), WD_ALL, "discarded-qualifiers" }, | |
| 1597 | + { 0, 0, NULL } | |
| 1598 | +}; | |
| 1599 | + | |
| 1685 | 1600 | static const FlagDef options_f[] = { |
| 1686 | 1601 | { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" }, |
| 1687 | 1602 | { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" }, |
| @@ -1701,6 +1616,40 @@ static const FlagDef options_m[] = { · 13 unmodified lines | ||
| 1701 | 1616 | { 0, 0, NULL } |
| 1702 | 1617 | }; |
| 1703 | 1618 | |
| 1619 | +static int set_flag(TCCState *s, const FlagDef *flags, const char *name) | |
| 1620 | +{ | |
| 1621 | + int value, mask, ret; | |
| 1622 | + const FlagDef *p; | |
| 1623 | + const char *r; | |
| 1624 | + unsigned char *f; | |
| 1625 | + | |
| 1626 | + r = name, value = !strstart("no-", &r), mask = 0; | |
| 1627 | + | |
| 1628 | + /* when called with options_W, look for -W[no-]error=<option> */ | |
| 1629 | + if ((flags->flags & WD_ALL) && strstart("error=", &r)) | |
| 1630 | + value = value ? WARN_ON|WARN_ERR : WARN_NOE, mask = WARN_ON; | |
| 1631 | + | |
| 1632 | + for (ret = -1, p = flags; p->name; ++p) { | |
| 1633 | + if (ret) { | |
| 1634 | + if (strcmp(r, p->name)) | |
| 1635 | + continue; | |
| 1636 | + } else { | |
| 1637 | + if (0 == (p->flags & WD_ALL)) | |
| 1638 | + continue; | |
| 1639 | + } | |
| 1640 | + | |
| 1641 | + f = (unsigned char *)s + p->offset; | |
| 1642 | + *f = (*f & mask) | (value ^ !!(p->flags & FD_INVERT)); | |
| 1643 | + | |
| 1644 | + if (ret) { | |
| 1645 | + ret = 0; | |
| 1646 | + if (strcmp(r, "all")) | |
| 1647 | + break; | |
| 1648 | + } | |
| 1649 | + } | |
| 1650 | + return ret; | |
| 1651 | +} | |
| 1652 | + | |
| 1704 | 1653 | static void args_parser_add_file(TCCState *s, const char* filename, int filetype) |
| 1705 | 1654 | { |
| 1706 | 1655 | struct filespec *f = tcc_malloc(sizeof *f + strlen(filename)); |
| @@ -1976,12 +1925,12 @@ reparse: · 269 unmodified lines | ||
| 1976 | 1925 | } |
| 1977 | 1926 | break; |
| 1978 | 1927 | case TCC_OPTION_W: |
| 1979 | − s->warn_mask &= ~WARN_DISABLED; | |
| 1980 | − if (optarg[0] && set_W_flag(s, optarg) < 0) | |
| 1928 | + s->warn_none = 0; | |
| 1929 | + if (optarg[0] && set_flag(s, options_W, optarg) < 0) | |
| 1981 | 1930 | goto unsupported_option; |
| 1982 | 1931 | break; |
| 1983 | 1932 | case TCC_OPTION_w: |
| 1984 | − s->warn_mask |= WARN_DISABLED; | |
| 1933 | + s->warn_none = 1; | |
| 1985 | 1934 | break; |
| 1986 | 1935 | case TCC_OPTION_rdynamic: |
| 1987 | 1936 | s->rdynamic = 1; |
| @@ -2064,8 +2013,7 @@ reparse: · 76 unmodified lines | ||
| 2064 | 2013 | break; |
| 2065 | 2014 | default: |
| 2066 | 2015 | unsupported_option: |
| 2067 | − if (NEED_WARNING(s, UNSUPPORTED)) | |
| 2068 | − tcc_warning("unsupported option '%s'", r); | |
| 2016 | + tcc_warning_c(warn_unsupported)("unsupported option '%s'", r); | |
| 2069 | 2017 | break; |
| 2070 | 2018 | } |
| 2071 | 2019 | } |
| @@ -267,15 +267,12 @@ Make string constants be of type @code{const char *} instead of @code{char · 266 unmodified lines | ||
| 267 | 267 | *}. |
| 268 | 268 | |
| 269 | 269 | @item -Werror |
| 270 | −Abort compilation if a warning is issued. | |
| 271 | −Can be given an option to enable the specified warning | |
| 272 | −and turn it into an error, for example @option{-Werror=unsupported}. | |
| 273 | −Enabling general abortion and disabling specifics is not supported. | |
| 274 | −Disabling specific abortions again does not disable the according warning. | |
| 270 | +Abort compilation if a warning is issued. Can be given an option to enable | |
| 271 | +the specified warning and turn it into an error, for example | |
| 272 | +@option{-Werror=unsupported}. | |
| 275 | 273 | |
| 276 | 274 | @item -Wall |
| 277 | −Activate all warnings, except @option{-Werror}, @option{-Wunsupported} and | |
| 278 | −@option{-Wwrite-strings}. | |
| 275 | +Activate some useful warnings. | |
| 279 | 276 | |
| 280 | 277 | @end table |
| 281 | 278 | |
| @@ -36,7 +36,7 @@ static const char help[] = · 35 unmodified lines | ||
| 36 | 36 | " -std=c99 Conform to the ISO 1999 C standard (default).\n" |
| 37 | 37 | " -std=c11 Conform to the ISO 2011 C standard.\n" |
| 38 | 38 | " -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n" |
| 39 | − " -w disable all warnings and their consequences\n" | |
| 39 | + " -w disable all warnings\n" | |
| 40 | 40 | " --version -v show version\n" |
| 41 | 41 | " -vv show search paths or loaded files\n" |
| 42 | 42 | " -h -hh show this, show more help\n" |
| @@ -103,10 +103,11 @@ static const char help2[] = · 60 unmodified lines | ||
| 103 | 103 | " --param -pedantic -pipe -s -traditional\n" |
| 104 | 104 | "-W[no-]... warnings:\n" |
| 105 | 105 | " all turn on some (*) warnings\n" |
| 106 | − " error[=(X)] error out after first warning (for X)\n" | |
| 107 | − " unsupported warn for ignored options, pragmas,.. (X)\n" | |
| 108 | − " write-strings strings are const (*,X)\n" | |
| 109 | − " implicit-function-declaration warn for missing prototype (*,X)\n" | |
| 106 | + " error[=warning] stop after warning (any or specified)\n" | |
| 107 | + " write-strings strings are const\n" | |
| 108 | + " unsupported warn about ignored options, pragmas, etc.\n" | |
| 109 | + " implicit-function-declaration warn for missing prototype (*)\n" | |
| 110 | + " discarded-qualifiers warn when const is dropped (*)\n" | |
| 110 | 111 | "-f[no-]... flags:\n" |
| 111 | 112 | " unsigned-char default char is unsigned\n" |
| 112 | 113 | " signed-char default char is signed\n" |
| @@ -317,7 +318,7 @@ redo: · 204 unmodified lines | ||
| 317 | 318 | } |
| 318 | 319 | |
| 319 | 320 | if (s->nb_files == 0) |
| 320 | − tcc_error("no input files\n"); | |
| 321 | + tcc_error("no input files"); | |
| 321 | 322 | |
| 322 | 323 | if (s->output_type == TCC_OUTPUT_PREPROCESS) { |
| 323 | 324 | if (s->outfile && 0!=strcmp("-",s->outfile)) { |
| @@ -737,24 +737,6 @@ struct sym_attr { · 736 unmodified lines | ||
| 737 | 737 | #endif |
| 738 | 738 | }; |
| 739 | 739 | |
| 740 | −/* 32-bit bit carrier, split in two halves: lower=warn, upper=error */ | |
| 741 | −enum warn_option { | |
| 742 | − WARN_NONE, | |
| 743 | − WARN_UNSUPPORTED = 1u<<0, | |
| 744 | − WARN_GCC_COMPAT = 1u<<1, | |
| 745 | − WARN_WRITE_STRINGS = 1u<<2, | |
| 746 | − WARN_IMPLICIT_FUNCTION_DECLARATION = 1u<<3, | |
| 747 | − /* _ERROR is in lower as "max", there is no warning for it */ | |
| 748 | − WARN_ERROR = 1u<<4, | |
| 749 | − WARN_ALL = WARN_ERROR - 1, | |
| 750 | − /* Is neither in lower nor upper: disables warnings and errors (-w) */ | |
| 751 | − WARN_DISABLED = WARN_ERROR << 1 | |
| 752 | −}; | |
| 753 | −enum { | |
| 754 | − WARN_ERROR_SHIFT = 16u, | |
| 755 | − WARN_ERROR_MASK = (/*WARN_ALL |*/ WARN_ERROR) << WARN_ERROR_SHIFT | |
| 756 | −}; | |
| 757 | − | |
| 758 | 740 | struct TCCState { |
| 759 | 741 | unsigned char verbose; /* if true, display some information during compilation */ |
| 760 | 742 | unsigned char nostdinc; /* if true, no standard headers are added */ |
| @@ -785,13 +767,18 @@ struct TCCState { · 24 unmodified lines | ||
| 785 | 767 | unsigned char dollars_in_identifiers; /* allows '$' char in identifiers */ |
| 786 | 768 | unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */ |
| 787 | 769 | |
| 788 | − /* NEED_WARNING(SELF,X) used to drive W[[no-]error]=X */ | |
| 789 | − uint32_t warn_mask; | |
| 790 | −#define NEED_WARNING(SELF,SWITCH) \ | |
| 791 | − (((SELF)->warn_mask & \ | |
| 792 | − (WARN_ ## SWITCH | (WARN_ ## SWITCH << WARN_ERROR_SHIFT))) \ | |
| 793 | − ? (((SELF)->warn_mask & (WARN_ ## SWITCH << WARN_ERROR_SHIFT)) \ | |
| 794 | − ? (SELF)->warn_mask |= (WARN_ERROR << WARN_ERROR_SHIFT), 1 : 1) : 0) | |
| 770 | + /* warning switches */ | |
| 771 | + unsigned char warn_none; | |
| 772 | + unsigned char warn_all; | |
| 773 | + unsigned char warn_error; | |
| 774 | + unsigned char warn_write_strings; | |
| 775 | + unsigned char warn_unsupported; | |
| 776 | + unsigned char warn_implicit_function_declaration; | |
| 777 | + unsigned char warn_discarded_qualifiers; | |
| 778 | + #define WARN_ON 1 /* warning is on (-Woption) */ | |
| 779 | + #define WARN_ERR 2 /* warning is an error (-Werror=option) */ | |
| 780 | + #define WARN_NOE 4 /* warning is not an error (-Wno-error=option) */ | |
| 781 | + unsigned char warn_num; /* temp var for tcc_warning_c() */ | |
| 795 | 782 | |
| 796 | 783 | /* compile with debug symbol (and use them if error during execution) */ |
| 797 | 784 | unsigned char do_debug; |
| @@ -1890,6 +1877,11 @@ ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename) · 1092 unmodified lines | ||
| 1890 | 1877 | PUB_FUNC void tcc_enter_state(TCCState *s1); |
| 1891 | 1878 | PUB_FUNC void tcc_exit_state(void); |
| 1892 | 1879 | |
| 1880 | +/* conditional warning depending on switch */ | |
| 1881 | +#define tcc_warning_c(sw) TCC_SET_STATE((\ | |
| 1882 | + tcc_state->warn_num = offsetof(TCCState, sw) \ | |
| 1883 | + - offsetof(TCCState, warn_none), _tcc_warning)) | |
| 1884 | + | |
| 1893 | 1885 | /********************************************************/ |
| 1894 | 1886 | #endif /* _TCC_H */ |
| 1895 | 1887 | |
| @@ -1903,6 +1895,4 @@ PUB_FUNC void tcc_exit_state(void); · 7 unmodified lines | ||
| 1903 | 1895 | #else |
| 1904 | 1896 | # define TCC_STATE_VAR(sym) s1->sym |
| 1905 | 1897 | # define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn) |
| 1906 | −/* actually we could avoid the tcc_enter_state(s1) hack by using | |
| 1907 | − __VA_ARGS__ except that some compiler doesn't support it. */ | |
| 1908 | 1898 | #endif |
| @@ -769,15 +769,11 @@ static void asm_parse_directive(TCCState *s1, int global) · 768 unmodified lines | ||
| 769 | 769 | |
| 770 | 770 | filename[0] = '\0'; |
| 771 | 771 | next(); |
| 772 | − | |
| 773 | 772 | if (tok == TOK_STR) |
| 774 | 773 | pstrcat(filename, sizeof(filename), tokc.str.data); |
| 775 | 774 | else |
| 776 | 775 | pstrcat(filename, sizeof(filename), get_tok_str(tok, NULL)); |
| 777 | − | |
| 778 | − if (NEED_WARNING(s1, UNSUPPORTED)) | |
| 779 | − tcc_warning("ignoring .file %s", filename); | |
| 780 | − | |
| 776 | + tcc_warning_c(warn_unsupported)("ignoring .file %s", filename); | |
| 781 | 777 | next(); |
| 782 | 778 | } |
| 783 | 779 | break; |
| @@ -787,15 +783,11 @@ static void asm_parse_directive(TCCState *s1, int global) · 3 unmodified lines | ||
| 787 | 783 | |
| 788 | 784 | ident[0] = '\0'; |
| 789 | 785 | next(); |
| 790 | − | |
| 791 | 786 | if (tok == TOK_STR) |
| 792 | 787 | pstrcat(ident, sizeof(ident), tokc.str.data); |
| 793 | 788 | else |
| 794 | 789 | pstrcat(ident, sizeof(ident), get_tok_str(tok, NULL)); |
| 795 | − | |
| 796 | − if (NEED_WARNING(s1, UNSUPPORTED)) | |
| 797 | − tcc_warning("ignoring .ident %s", ident); | |
| 798 | − | |
| 790 | + tcc_warning_c(warn_unsupported)("ignoring .ident %s", ident); | |
| 799 | 791 | next(); |
| 800 | 792 | } |
| 801 | 793 | break; |
| @@ -808,11 +800,8 @@ static void asm_parse_directive(TCCState *s1, int global) · 6 unmodified lines | ||
| 808 | 800 | if (!sym) { |
| 809 | 801 | tcc_error("label not found: %s", get_tok_str(tok, NULL)); |
| 810 | 802 | } |
| 811 | − | |
| 812 | 803 | /* XXX .size name,label2-label1 */ |
| 813 | − if (NEED_WARNING(s1, UNSUPPORTED)) | |
| 814 | − tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL)); | |
| 815 | − | |
| 804 | + tcc_warning_c(warn_unsupported)("ignoring .size %s,*", get_tok_str(tok, NULL)); | |
| 816 | 805 | next(); |
| 817 | 806 | skip(','); |
| 818 | 807 | while (tok != TOK_LINEFEED && tok != ';' && tok != CH_EOF) { |
| @@ -839,9 +828,8 @@ static void asm_parse_directive(TCCState *s1, int global) · 20 unmodified lines | ||
| 839 | 828 | |
| 840 | 829 | if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) { |
| 841 | 830 | sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC; |
| 842 | − } | |
| 843 | − else if (NEED_WARNING(s1, UNSUPPORTED)) | |
| 844 | − tcc_warning("change type of '%s' from 0x%x to '%s' ignored", | |
| 831 | + } else | |
| 832 | + tcc_warning_c(warn_unsupported)("change type of '%s' from 0x%x to '%s' ignored", | |
| 845 | 833 | get_tok_str(sym->v, NULL), sym->type.t, newtype); |
| 846 | 834 | |
| 847 | 835 | next(); |
| @@ -4077,7 +4077,7 @@ static void verify_assign_cast(CType *dt) · 4076 unmodified lines | ||
| 4077 | 4077 | } |
| 4078 | 4078 | } |
| 4079 | 4079 | if (qualwarn) |
| 4080 | − tcc_warning("assignment discards qualifiers from pointer target type"); | |
| 4080 | + tcc_warning_c(warn_discarded_qualifiers)("assignment discards qualifiers from pointer target type"); | |
| 4081 | 4081 | break; |
| 4082 | 4082 | case VT_BYTE: |
| 4083 | 4083 | case VT_SHORT: |
| @@ -4355,9 +4355,9 @@ redo: · 271 unmodified lines | ||
| 4355 | 4355 | skip('('); |
| 4356 | 4356 | s = sym_find(tok); |
| 4357 | 4357 | if (!s) { |
| 4358 | − tcc_warning("implicit declaration of function '%s'", | |
| 4359 | − get_tok_str(tok, &tokc)); | |
| 4360 | − s = external_global_sym(tok, &func_old_type); | |
| 4358 | + tcc_warning_c(warn_implicit_function_declaration)( | |
| 4359 | + "implicit declaration of function '%s'", get_tok_str(tok, &tokc)); | |
| 4360 | + s = external_global_sym(tok, &func_old_type); | |
| 4361 | 4361 | } else if ((s->type.t & VT_BTYPE) != VT_FUNC) |
| 4362 | 4362 | tcc_error("'%s' is not declared as function", get_tok_str(tok, &tokc)); |
| 4363 | 4363 | ad->cleanup_func = s; |
| @@ -4506,8 +4506,7 @@ redo: · 142 unmodified lines | ||
| 4506 | 4506 | ad->a.dllimport = 1; |
| 4507 | 4507 | break; |
| 4508 | 4508 | default: |
| 4509 | − if (NEED_WARNING(tcc_state, UNSUPPORTED)) | |
| 4510 | − tcc_warning("'%s' attribute ignored", get_tok_str(t, NULL)); | |
| 4509 | + tcc_warning_c(warn_unsupported)("'%s' attribute ignored", get_tok_str(t, NULL)); | |
| 4511 | 4510 | /* skip parameters */ |
| 4512 | 4511 | if (tok == '(') { |
| 4513 | 4512 | int parenthesis = 0; |
| @@ -5909,23 +5908,20 @@ ST_FUNC void unary(void) · 1395 unmodified lines | ||
| 5909 | 5908 | case TOK___FUNC__: |
| 5910 | 5909 | { |
| 5911 | 5910 | Section *sec; |
| 5912 | − void *ptr; | |
| 5913 | 5911 | int len; |
| 5914 | 5912 | /* special function name identifier */ |
| 5915 | 5913 | len = strlen(funcname) + 1; |
| 5916 | 5914 | /* generate char[len] type */ |
| 5917 | − type.t = VT_BYTE; | |
| 5918 | − if (NEED_WARNING(tcc_state, WRITE_STRINGS)) | |
| 5915 | + type.t = char_type.t; | |
| 5916 | + if (tcc_state->warn_write_strings & WARN_ON) | |
| 5919 | 5917 | type.t |= VT_CONSTANT; |
| 5920 | 5918 | mk_pointer(&type); |
| 5921 | 5919 | type.t |= VT_ARRAY; |
| 5922 | 5920 | type.ref->c = len; |
| 5923 | 5921 | sec = rodata_section; |
| 5924 | 5922 | vpush_ref(&type, sec, sec->data_offset, len); |
| 5925 | − if (!NODATA_WANTED) { | |
| 5926 | − ptr = section_ptr_add(sec, len); | |
| 5927 | − memcpy(ptr, funcname, len); | |
| 5928 | − } | |
| 5923 | + if (!NODATA_WANTED) | |
| 5924 | + memcpy(section_ptr_add(sec, len), funcname, len); | |
| 5929 | 5925 | next(); |
| 5930 | 5926 | } |
| 5931 | 5927 | break; |
| @@ -5938,11 +5934,9 @@ ST_FUNC void unary(void) · 6 unmodified lines | ||
| 5938 | 5934 | goto str_init; |
| 5939 | 5935 | case TOK_STR: |
| 5940 | 5936 | /* string parsing */ |
| 5941 | − t = VT_BYTE; | |
| 5942 | − if (tcc_state->char_is_unsigned) | |
| 5943 | − t = VT_BYTE | VT_UNSIGNED; | |
| 5937 | + t = char_type.t; | |
| 5944 | 5938 | str_init: |
| 5945 | − if (NEED_WARNING(tcc_state, WRITE_STRINGS)) | |
| 5939 | + if (tcc_state->warn_write_strings & WARN_ON) | |
| 5946 | 5940 | t |= VT_CONSTANT; |
| 5947 | 5941 | type.t = t; |
| 5948 | 5942 | mk_pointer(&type); |
| @@ -6378,14 +6372,8 @@ special_math_val: · 429 unmodified lines | ||
| 6378 | 6372 | tcc_error("'%s' undeclared", name); |
| 6379 | 6373 | /* for simple function calls, we tolerate undeclared |
| 6380 | 6374 | external reference to int() function */ |
| 6381 | − if (NEED_WARNING(tcc_state, IMPLICIT_FUNCTION_DECLARATION) | |
| 6382 | −#ifdef TCC_TARGET_PE | |
| 6383 | − /* must warn about using undeclared WINAPI functions | |
| 6384 | − (which usually start with uppercase letter) */ | |
| 6385 | − || (name[0] >= 'A' && name[0] <= 'Z') | |
| 6386 | −#endif | |
| 6387 | − ) | |
| 6388 | − tcc_warning("implicit declaration of function '%s'", name); | |
| 6375 | + tcc_warning_c(warn_implicit_function_declaration)( | |
| 6376 | + "implicit declaration of function '%s'", name); | |
| 6389 | 6377 | s = external_global_sym(t, &func_old_type); |
| 6390 | 6378 | } |
| 6391 | 6379 | |
| @@ -7650,12 +7638,10 @@ again: · 1258 unmodified lines | ||
| 7650 | 7638 | |
| 7651 | 7639 | block_after_label: |
| 7652 | 7640 | vla_restore(cur_scope->vla.loc); |
| 7653 | − /* we accept this, but it is a mistake */ | |
| 7654 | − if (tok == '}') { | |
| 7655 | − tcc_warning("deprecated use of label at end of compound statement"); | |
| 7656 | − } else { | |
| 7641 | + if (tok != '}') | |
| 7657 | 7642 | goto again; |
| 7658 | − } | |
| 7643 | + /* we accept this, but it is a mistake */ | |
| 7644 | + tcc_warning_c(warn_all)("deprecated use of label at end of compound statement"); | |
| 7659 | 7645 | |
| 7660 | 7646 | } else { |
| 7661 | 7647 | /* expression case */ |
| @@ -1435,7 +1435,7 @@ ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep) · 1434 unmodified lines | ||
| 1435 | 1435 | for(s = *ptop; s != slast; s = s1) { |
| 1436 | 1436 | s1 = s->prev; |
| 1437 | 1437 | if (s->r == LABEL_DECLARED) { |
| 1438 | − tcc_warning("label '%s' declared but not used", get_tok_str(s->v, NULL)); | |
| 1438 | + tcc_warning_c(warn_all)("label '%s' declared but not used", get_tok_str(s->v, NULL)); | |
| 1439 | 1439 | } else if (s->r == LABEL_FORWARD) { |
| 1440 | 1440 | tcc_error("label '%s' used but not defined", |
| 1441 | 1441 | get_tok_str(s->v, NULL)); |
| @@ -1770,8 +1770,8 @@ static void pragma_parse(TCCState *s1) · 328 unmodified lines | ||
| 1770 | 1770 | tcc_free(p); |
| 1771 | 1771 | } |
| 1772 | 1772 | |
| 1773 | − } else if (NEED_WARNING(s1, UNSUPPORTED)) | |
| 1774 | − tcc_warning("#pragma %s is ignored", get_tok_str(tok, &tokc)); | |
| 1773 | + } else | |
| 1774 | + tcc_warning_c(warn_unsupported)("#pragma %s ignored", get_tok_str(tok, &tokc)); | |
| 1775 | 1775 | return; |
| 1776 | 1776 | |
| 1777 | 1777 | pragma_err: |
| @@ -2293,7 +2293,7 @@ static void parse_string(const char *s, int len) · 515 unmodified lines | ||
| 2293 | 2293 | if (n < 1) |
| 2294 | 2294 | tcc_error("empty character constant"); |
| 2295 | 2295 | if (n > 1) |
| 2296 | − tcc_warning("multi-character character constant"); | |
| 2296 | + tcc_warning_c(warn_all)("multi-character character constant"); | |
| 2297 | 2297 | for (c = i = 0; i < n; ++i) { |
| 2298 | 2298 | if (is_long) |
| 2299 | 2299 | c = ((nwchar_t *)tokcstr.data)[i]; |
| @@ -399,4 +399,21 @@ int array[] = { 1, 2, 3 }; · 398 unmodified lines | ||
| 399 | 399 | void v() {} |
| 400 | 400 | int f() { return v(); } |
| 401 | 401 | |
| 402 | +#elif defined test_switch_W1 || defined test_switch_W2 \ | |
| 403 | + || defined test_switch_W3 || defined test_switch_W4 | |
| 404 | +#if defined test_switch_W1 | |
| 405 | +#pragma comment(option, "-Wall") | |
| 406 | +#elif defined test_switch_W2 | |
| 407 | +#pragma comment(option, "-Wunsupported -Wno-implicit-function-declaration -Wstuff") | |
| 408 | +#elif defined test_switch_W3 | |
| 409 | +#pragma comment(option, "-Wwrite-strings -Werror=discarded-qualifiers") | |
| 410 | +#elif defined test_switch_W4 | |
| 411 | +#pragma comment(option, "-Wunsupported -Wno-error=implicit-function-declaration -Werror") | |
| 412 | +#endif | |
| 413 | +void func() | |
| 414 | +{ | |
| 415 | + char *ccp = "123"; | |
| 416 | + fink(); | |
| 417 | +} | |
| 418 | +__attribute__((stuff)) int fink() {return 0;} | |
| 402 | 419 | #endif |
| @@ -189,3 +189,17 @@ bar : 3 ; 3 · 188 unmodified lines | ||
| 189 | 189 | |
| 190 | 190 | [test_cast_from_void] |
| 191 | 191 | 60_errors_and_warnings.c:400: error: cannot convert 'void' to 'int' |
| 192 | + | |
| 193 | +[test_switch_W1] | |
| 194 | +60_errors_and_warnings.c:416: warning: implicit declaration of function 'fink' | |
| 195 | + | |
| 196 | +[test_switch_W2] | |
| 197 | +60_errors_and_warnings.c:407: warning: unsupported option '-Wstuff' | |
| 198 | +60_errors_and_warnings.c:418: warning: 'stuff' attribute ignored | |
| 199 | + | |
| 200 | +[test_switch_W3] | |
| 201 | +60_errors_and_warnings.c:415: error: assignment discards qualifiers from pointer target type | |
| 202 | + | |
| 203 | +[test_switch_W4] | |
| 204 | +60_errors_and_warnings.c:416: warning: implicit declaration of function 'fink' | |
| 205 | +60_errors_and_warnings.c:418: error: 'stuff' attribute ignored | |