Unified · Split
| @@ -786,7 +786,7 @@ LIBTCCAPI TCCState *tcc_new(void) · 785 unmodified lines | ||
| 786 | 786 | s->nocommon = 1; |
| 787 | 787 | s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/ |
| 788 | 788 | s->cversion = 199901; /* default unless -std=c11 is supplied */ |
| 789 | − s->warn_implicit_function_declaration = 1; | |
| 789 | + s->warn_mask |= WARN_IMPLICIT_FUNCTION_DECLARATION; | |
| 790 | 790 | s->ms_extensions = 1; |
| 791 | 791 | |
| 792 | 792 | #ifdef CHAR_IS_UNSIGNED |
| @@ -1280,46 +1280,70 @@ ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, const char *name) · 487 unmodified lines | ||
| 1280 | 1280 | return ret; |
| 1281 | 1281 | } |
| 1282 | 1282 | |
| 1283 | −ST_FUNC int set_W_flag(TCCState *s, const FlagDef *flags, const char *optarg) | |
| 1283 | +ST_FUNC int set_W_flag(TCCState *s, const char *optarg) | |
| 1284 | 1284 | { |
| 1285 | − int value, ret; | |
| 1286 | − const FlagDef *p; | |
| 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, 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; | |
| 1287 | 1301 | const char *r, *sub; |
| 1288 | 1302 | |
| 1289 | − value = 1; | |
| 1303 | + mode = 1; | |
| 1290 | 1304 | r = optarg; |
| 1291 | 1305 | if (no_flag(&r)) |
| 1292 | − value = 0; | |
| 1306 | + mode = 0; | |
| 1293 | 1307 | |
| 1294 | 1308 | if ((sub = strchr(r, '=')) != NULL) { |
| 1295 | 1309 | if (strncmp(r, "error", (uintptr_t)(sub - r))) |
| 1296 | 1310 | return -1; |
| 1297 | 1311 | r = ++sub; |
| 1298 | − if (value) | |
| 1299 | − value = 1 | 2; | |
| 1312 | + mode |= 2; | |
| 1300 | 1313 | } |
| 1301 | 1314 | |
| 1302 | − /* .offset for "all" is 0 */ | |
| 1303 | − for (ret = -1, p = flags; p->name; ++p) { | |
| 1315 | + for (ret = -1, p = opts; p < &opts[countof(opts)]; ++p) { | |
| 1304 | 1316 | if (ret) { |
| 1305 | 1317 | if (strcmp(r, p->name)) |
| 1306 | 1318 | continue; |
| 1307 | − if (sub != NULL && !(p->flags & WD_ERROR)) | |
| 1319 | + if ((mode & 2) && !(p->flags & WD_ERROR)) | |
| 1308 | 1320 | break; |
| 1309 | 1321 | } else { |
| 1310 | 1322 | if (0 == (p->flags & WD_ALL)) |
| 1311 | 1323 | continue; |
| 1312 | 1324 | } |
| 1313 | − if (p->offset) { | |
| 1314 | − *((unsigned char *)s + p->offset) = value; | |
| 1315 | − if (ret) { | |
| 1316 | − ret = 0; | |
| 1317 | − break; | |
| 1318 | − } | |
| 1319 | − } else { | |
| 1325 | + | |
| 1326 | + if (p->wbit == WARN_ALL) { | |
| 1327 | + /* Start a loop over all the rest */ | |
| 1320 | 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; | |
| 1321 | 1344 | } |
| 1322 | 1345 | } |
| 1346 | + | |
| 1323 | 1347 | return ret; |
| 1324 | 1348 | } |
| 1325 | 1349 | |
| @@ -1513,7 +1537,7 @@ static int tcc_set_linker(TCCState *s, const char *option) · 187 unmodified lines | ||
| 1513 | 1537 | tcc_error("unsupported linker option '%s'", option); |
| 1514 | 1538 | } |
| 1515 | 1539 | |
| 1516 | − if (ignoring && NEED_WARNING(s, unsupported)) | |
| 1540 | + if (ignoring && NEED_WARNING(s, UNSUPPORTED)) | |
| 1517 | 1541 | tcc_warning("unsupported linker option '%s'", option); |
| 1518 | 1542 | |
| 1519 | 1543 | option = skip_linker_arg(&p); |
| @@ -1658,18 +1682,6 @@ static const TCCOption tcc_options[] = { · 138 unmodified lines | ||
| 1658 | 1682 | { NULL, 0, 0 }, |
| 1659 | 1683 | }; |
| 1660 | 1684 | |
| 1661 | −static const FlagDef options_W[] = { | |
| 1662 | − { 0, 0, "all" }, | |
| 1663 | − { offsetof(TCCState, warn_error), 0, "error" }, | |
| 1664 | − { offsetof(TCCState, warn_unsupported), WD_ERROR, "unsupported" }, | |
| 1665 | − { offsetof(TCCState, warn_gcc_compat), WD_ERROR, "gcc-compat" }, | |
| 1666 | − { offsetof(TCCState, warn_write_strings), WD_ERROR | WD_ALL, | |
| 1667 | − "write-strings" }, | |
| 1668 | − { offsetof(TCCState, warn_implicit_function_declaration), | |
| 1669 | − WD_ERROR | WD_ALL, "implicit-function-declaration" }, | |
| 1670 | − { 0, 0, NULL } | |
| 1671 | −}; | |
| 1672 | − | |
| 1673 | 1685 | static const FlagDef options_f[] = { |
| 1674 | 1686 | { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" }, |
| 1675 | 1687 | { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" }, |
| @@ -1965,7 +1977,7 @@ reparse: · 289 unmodified lines | ||
| 1965 | 1977 | break; |
| 1966 | 1978 | case TCC_OPTION_W: |
| 1967 | 1979 | s->warn_none = 0; |
| 1968 | − if (optarg[0] && set_W_flag(s, options_W, optarg) < 0) | |
| 1980 | + if (optarg[0] && set_W_flag(s, optarg) < 0) | |
| 1969 | 1981 | goto unsupported_option; |
| 1970 | 1982 | break; |
| 1971 | 1983 | case TCC_OPTION_w: |
| @@ -2052,7 +2064,7 @@ reparse: · 80 unmodified lines | ||
| 2052 | 2064 | break; |
| 2053 | 2065 | default: |
| 2054 | 2066 | unsupported_option: |
| 2055 | − if (NEED_WARNING(s, unsupported)) | |
| 2067 | + if (NEED_WARNING(s, UNSUPPORTED)) | |
| 2056 | 2068 | tcc_warning("unsupported option '%s'", r); |
| 2057 | 2069 | break; |
| 2058 | 2070 | } |
| @@ -270,7 +270,8 @@ Make string constants be of type @code{const char *} instead of @code{char · 269 unmodified lines | ||
| 270 | 270 | Abort compilation if a warning is issued. |
| 271 | 271 | Can be given an option to enable the specified warning |
| 272 | 272 | and turn it into an error, for example @option{-Werror=unsupported}. |
| 273 | −(Enabling general abortion and disabling specifics is not supported.) | |
| 273 | +Enabling general abortion and disabling specifics is not supported. | |
| 274 | +Disabling specific abortions again does not disable the according warning. | |
| 274 | 275 | |
| 275 | 276 | @item -Wall |
| 276 | 277 | Activate all warnings, except @option{-Werror}, @option{-Wunsupported} and |
| @@ -737,6 +737,18 @@ 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 | + WARN_ERROR = 1u<<4, | |
| 748 | + WARN_ALL = WARN_ERROR - 1 | |
| 749 | +}; | |
| 750 | +enum {WARN_ERROR_SHIFT = 16u}; | |
| 751 | + | |
| 740 | 752 | struct TCCState { |
| 741 | 753 | unsigned char verbose; /* if true, display some information during compilation */ |
| 742 | 754 | unsigned char nostdinc; /* if true, no standard headers are added */ |
| @@ -767,17 +779,15 @@ struct TCCState { · 24 unmodified lines | ||
| 767 | 779 | unsigned char dollars_in_identifiers; /* allows '$' char in identifiers */ |
| 768 | 780 | unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */ |
| 769 | 781 | |
| 770 | − /* warning switches; but for first two, W[no-]error=X is supported */ | |
| 771 | − /* XXX TCC_IS_WARN_OR_ERR(X,Y) used to drive W[[no-]error]=X */ | |
| 772 | 782 | unsigned char warn_none; |
| 773 | 783 | unsigned char warn_error; |
| 774 | − unsigned char warn_unsupported; | |
| 775 | − unsigned char warn_gcc_compat; | |
| 776 | − unsigned char warn_write_strings; | |
| 777 | − unsigned char warn_implicit_function_declaration; | |
| 784 | + /* NEED_WARNING(SELF,X) used to drive W[[no-]error]=X */ | |
| 785 | + uint32_t warn_mask; | |
| 778 | 786 | #define NEED_WARNING(SELF,SWITCH) \ |
| 779 | − ((SELF)->warn_ ## SWITCH \ | |
| 780 | − ? (((SELF)->warn_ ## SWITCH & 2) ? (SELF)->warn_error = 1 : 1) : 0) | |
| 787 | + (((SELF)->warn_mask & \ | |
| 788 | + (WARN_ ## SWITCH | (WARN_ ## SWITCH << WARN_ERROR_SHIFT))) \ | |
| 789 | + ? (((SELF)->warn_mask & (WARN_ ## SWITCH << WARN_ERROR_SHIFT)) \ | |
| 790 | + ? (SELF)->warn_error = 1 : 1) : 0) | |
| 781 | 791 | |
| 782 | 792 | /* compile with debug symbol (and use them if error during execution) */ |
| 783 | 793 | unsigned char do_debug; |
| @@ -775,7 +775,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 774 unmodified lines | ||
| 775 | 775 | else |
| 776 | 776 | pstrcat(filename, sizeof(filename), get_tok_str(tok, NULL)); |
| 777 | 777 | |
| 778 | − if (NEED_WARNING(s1, unsupported)) | |
| 778 | + if (NEED_WARNING(s1, UNSUPPORTED)) | |
| 779 | 779 | tcc_warning("ignoring .file %s", filename); |
| 780 | 780 | |
| 781 | 781 | next(); |
| @@ -793,7 +793,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 11 unmodified lines | ||
| 793 | 793 | else |
| 794 | 794 | pstrcat(ident, sizeof(ident), get_tok_str(tok, NULL)); |
| 795 | 795 | |
| 796 | − if (NEED_WARNING(s1, unsupported)) | |
| 796 | + if (NEED_WARNING(s1, UNSUPPORTED)) | |
| 797 | 797 | tcc_warning("ignoring .ident %s", ident); |
| 798 | 798 | |
| 799 | 799 | next(); |
| @@ -810,7 +810,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 10 unmodified lines | ||
| 810 | 810 | } |
| 811 | 811 | |
| 812 | 812 | /* XXX .size name,label2-label1 */ |
| 813 | − if (NEED_WARNING(s1, unsupported)) | |
| 813 | + if (NEED_WARNING(s1, UNSUPPORTED)) | |
| 814 | 814 | tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL)); |
| 815 | 815 | |
| 816 | 816 | next(); |
| @@ -840,7 +840,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 23 unmodified lines | ||
| 840 | 840 | if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) { |
| 841 | 841 | sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC; |
| 842 | 842 | } |
| 843 | − else if (NEED_WARNING(s1, unsupported)) | |
| 843 | + else if (NEED_WARNING(s1, UNSUPPORTED)) | |
| 844 | 844 | tcc_warning("change type of '%s' from 0x%x to '%s' ignored", |
| 845 | 845 | get_tok_str(sym->v, NULL), sym->type.t, newtype); |
| 846 | 846 | |
| @@ -4506,7 +4506,7 @@ redo: · 4505 unmodified lines | ||
| 4506 | 4506 | ad->a.dllimport = 1; |
| 4507 | 4507 | break; |
| 4508 | 4508 | default: |
| 4509 | − if (NEED_WARNING(tcc_state, unsupported)) | |
| 4509 | + if (NEED_WARNING(tcc_state, UNSUPPORTED)) | |
| 4510 | 4510 | tcc_warning("'%s' attribute ignored", get_tok_str(t, NULL)); |
| 4511 | 4511 | /* skip parameters */ |
| 4512 | 4512 | if (tok == '(') { |
| @@ -5915,7 +5915,7 @@ ST_FUNC void unary(void) · 1402 unmodified lines | ||
| 5915 | 5915 | len = strlen(funcname) + 1; |
| 5916 | 5916 | /* generate char[len] type */ |
| 5917 | 5917 | type.t = VT_BYTE; |
| 5918 | − if (NEED_WARNING(tcc_state, write_strings)) | |
| 5918 | + if (NEED_WARNING(tcc_state, WRITE_STRINGS)) | |
| 5919 | 5919 | type.t |= VT_CONSTANT; |
| 5920 | 5920 | mk_pointer(&type); |
| 5921 | 5921 | type.t |= VT_ARRAY; |
| @@ -5942,7 +5942,7 @@ ST_FUNC void unary(void) · 20 unmodified lines | ||
| 5942 | 5942 | if (tcc_state->char_is_unsigned) |
| 5943 | 5943 | t = VT_BYTE | VT_UNSIGNED; |
| 5944 | 5944 | str_init: |
| 5945 | − if (NEED_WARNING(tcc_state, write_strings)) | |
| 5945 | + if (NEED_WARNING(tcc_state, WRITE_STRINGS)) | |
| 5946 | 5946 | t |= VT_CONSTANT; |
| 5947 | 5947 | type.t = t; |
| 5948 | 5948 | mk_pointer(&type); |
| @@ -6378,7 +6378,7 @@ special_math_val: · 429 unmodified lines | ||
| 6378 | 6378 | tcc_error("'%s' undeclared", name); |
| 6379 | 6379 | /* for simple function calls, we tolerate undeclared |
| 6380 | 6380 | external reference to int() function */ |
| 6381 | − if (NEED_WARNING(tcc_state, implicit_function_declaration) | |
| 6381 | + if (NEED_WARNING(tcc_state, IMPLICIT_FUNCTION_DECLARATION) | |
| 6382 | 6382 | #ifdef TCC_TARGET_PE |
| 6383 | 6383 | /* must warn about using undeclared WINAPI functions |
| 6384 | 6384 | (which usually start with uppercase letter) */ |
| @@ -1770,7 +1770,7 @@ static void pragma_parse(TCCState *s1) · 1769 unmodified lines | ||
| 1770 | 1770 | tcc_free(p); |
| 1771 | 1771 | } |
| 1772 | 1772 | |
| 1773 | − } else if (NEED_WARNING(s1, unsupported)) | |
| 1773 | + } else if (NEED_WARNING(s1, UNSUPPORTED)) | |
| 1774 | 1774 | tcc_warning("#pragma %s is ignored", get_tok_str(tok, &tokc)); |
| 1775 | 1775 | return; |
| 1776 | 1776 | |