Unified · Split
| @@ -786,7 +786,7 @@ LIBTCCAPI TCCState *tcc_new(void) · 785 unmodified lines | |||
| 786 | s->nocommon = 1; | 786 | s->nocommon = 1; |
| 787 | s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/ | 787 | s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/ |
| 788 | s->cversion = 199901; /* default unless -std=c11 is supplied */ | 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 | s->ms_extensions = 1; | 790 | s->ms_extensions = 1; |
| 791 | 791 | ||
| 792 | #ifdef CHAR_IS_UNSIGNED | 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 | return ret; | 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; | 1285 | static struct a_W_flag{ |
| 1286 | const FlagDef *p; | 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 | const char *r, *sub; | 1301 | const char *r, *sub; |
| 1288 | 1302 | ||
| 1289 | value = 1; | 1303 | mode = 1; |
| 1290 | r = optarg; | 1304 | r = optarg; |
| 1291 | if (no_flag(&r)) | 1305 | if (no_flag(&r)) |
| 1292 | value = 0; | 1306 | mode = 0; |
| 1293 | 1307 | ||
| 1294 | if ((sub = strchr(r, '=')) != NULL) { | 1308 | if ((sub = strchr(r, '=')) != NULL) { |
| 1295 | if (strncmp(r, "error", (uintptr_t)(sub - r))) | 1309 | if (strncmp(r, "error", (uintptr_t)(sub - r))) |
| 1296 | return -1; | 1310 | return -1; |
| 1297 | r = ++sub; | 1311 | r = ++sub; |
| 1298 | if (value) | 1312 | mode |= 2; |
| 1299 | value = 1 | 2; | ||
| 1300 | } | 1313 | } |
| 1301 | 1314 | ||
| 1302 | /* .offset for "all" is 0 */ | 1315 | for (ret = -1, p = opts; p < &opts[countof(opts)]; ++p) { |
| 1303 | for (ret = -1, p = flags; p->name; ++p) { | ||
| 1304 | if (ret) { | 1316 | if (ret) { |
| 1305 | if (strcmp(r, p->name)) | 1317 | if (strcmp(r, p->name)) |
| 1306 | continue; | 1318 | continue; |
| 1307 | if (sub != NULL && !(p->flags & WD_ERROR)) | 1319 | if ((mode & 2) && !(p->flags & WD_ERROR)) |
| 1308 | break; | 1320 | break; |
| 1309 | } else { | 1321 | } else { |
| 1310 | if (0 == (p->flags & WD_ALL)) | 1322 | if (0 == (p->flags & WD_ALL)) |
| 1311 | continue; | 1323 | continue; |
| 1312 | } | 1324 | } |
| 1313 | if (p->offset) { | 1325 | |
| 1314 | *((unsigned char *)s + p->offset) = value; | 1326 | if (p->wbit == WARN_ALL) { |
| 1315 | if (ret) { | 1327 | /* Start a loop over all the rest */ |
| 1316 | ret = 0; | ||
| 1317 | break; | ||
| 1318 | } | ||
| 1319 | } else { | ||
| 1320 | ret = 0; | 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 | return ret; | 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 | tcc_error("unsupported linker option '%s'", option); | 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 | tcc_warning("unsupported linker option '%s'", option); | 1541 | tcc_warning("unsupported linker option '%s'", option); |
| 1518 | 1542 | ||
| 1519 | option = skip_linker_arg(&p); | 1543 | option = skip_linker_arg(&p); |
| @@ -1658,18 +1682,6 @@ static const TCCOption tcc_options[] = { · 138 unmodified lines | |||
| 1658 | { NULL, 0, 0 }, | 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 | static const FlagDef options_f[] = { | 1685 | static const FlagDef options_f[] = { |
| 1674 | { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" }, | 1686 | { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" }, |
| 1675 | { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" }, | 1687 | { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" }, |
| @@ -1965,7 +1977,7 @@ reparse: · 289 unmodified lines | |||
| 1965 | break; | 1977 | break; |
| 1966 | case TCC_OPTION_W: | 1978 | case TCC_OPTION_W: |
| 1967 | s->warn_none = 0; | 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 | goto unsupported_option; | 1981 | goto unsupported_option; |
| 1970 | break; | 1982 | break; |
| 1971 | case TCC_OPTION_w: | 1983 | case TCC_OPTION_w: |
| @@ -2052,7 +2064,7 @@ reparse: · 80 unmodified lines | |||
| 2052 | break; | 2064 | break; |
| 2053 | default: | 2065 | default: |
| 2054 | unsupported_option: | 2066 | unsupported_option: |
| 2055 | if (NEED_WARNING(s, unsupported)) | 2067 | if (NEED_WARNING(s, UNSUPPORTED)) |
| 2056 | tcc_warning("unsupported option '%s'", r); | 2068 | tcc_warning("unsupported option '%s'", r); |
| 2057 | break; | 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 | Abort compilation if a warning is issued. | 270 | Abort compilation if a warning is issued. |
| 271 | Can be given an option to enable the specified warning | 271 | Can be given an option to enable the specified warning |
| 272 | and turn it into an error, for example @option{-Werror=unsupported}. | 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 | @item -Wall | 276 | @item -Wall |
| 276 | Activate all warnings, except @option{-Werror}, @option{-Wunsupported} and | 277 | Activate all warnings, except @option{-Werror}, @option{-Wunsupported} and |
| @@ -737,6 +737,18 @@ struct sym_attr { · 736 unmodified lines | |||
| 737 | #endif | 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 | struct TCCState { | 752 | struct TCCState { |
| 741 | unsigned char verbose; /* if true, display some information during compilation */ | 753 | unsigned char verbose; /* if true, display some information during compilation */ |
| 742 | unsigned char nostdinc; /* if true, no standard headers are added */ | 754 | unsigned char nostdinc; /* if true, no standard headers are added */ |
| @@ -767,17 +779,15 @@ struct TCCState { · 24 unmodified lines | |||
| 767 | unsigned char dollars_in_identifiers; /* allows '$' char in identifiers */ | 779 | unsigned char dollars_in_identifiers; /* allows '$' char in identifiers */ |
| 768 | unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */ | 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 | unsigned char warn_none; | 782 | unsigned char warn_none; |
| 773 | unsigned char warn_error; | 783 | unsigned char warn_error; |
| 774 | unsigned char warn_unsupported; | 784 | /* NEED_WARNING(SELF,X) used to drive W[[no-]error]=X */ |
| 775 | unsigned char warn_gcc_compat; | 785 | uint32_t warn_mask; |
| 776 | unsigned char warn_write_strings; | ||
| 777 | unsigned char warn_implicit_function_declaration; | ||
| 778 | #define NEED_WARNING(SELF,SWITCH) \ | 786 | #define NEED_WARNING(SELF,SWITCH) \ |
| 779 | ((SELF)->warn_ ## SWITCH \ | 787 | (((SELF)->warn_mask & \ |
| 780 | ? (((SELF)->warn_ ## SWITCH & 2) ? (SELF)->warn_error = 1 : 1) : 0) | 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 | /* compile with debug symbol (and use them if error during execution) */ | 792 | /* compile with debug symbol (and use them if error during execution) */ |
| 783 | unsigned char do_debug; | 793 | unsigned char do_debug; |
| @@ -775,7 +775,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 774 unmodified lines | |||
| 775 | else | 775 | else |
| 776 | pstrcat(filename, sizeof(filename), get_tok_str(tok, NULL)); | 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 | tcc_warning("ignoring .file %s", filename); | 779 | tcc_warning("ignoring .file %s", filename); |
| 780 | 780 | ||
| 781 | next(); | 781 | next(); |
| @@ -793,7 +793,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 11 unmodified lines | |||
| 793 | else | 793 | else |
| 794 | pstrcat(ident, sizeof(ident), get_tok_str(tok, NULL)); | 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 | tcc_warning("ignoring .ident %s", ident); | 797 | tcc_warning("ignoring .ident %s", ident); |
| 798 | 798 | ||
| 799 | next(); | 799 | next(); |
| @@ -810,7 +810,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 10 unmodified lines | |||
| 810 | } | 810 | } |
| 811 | 811 | ||
| 812 | /* XXX .size name,label2-label1 */ | 812 | /* XXX .size name,label2-label1 */ |
| 813 | if (NEED_WARNING(s1, unsupported)) | 813 | if (NEED_WARNING(s1, UNSUPPORTED)) |
| 814 | tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL)); | 814 | tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL)); |
| 815 | 815 | ||
| 816 | next(); | 816 | next(); |
| @@ -840,7 +840,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 23 unmodified lines | |||
| 840 | if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) { | 840 | if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) { |
| 841 | sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC; | 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 | tcc_warning("change type of '%s' from 0x%x to '%s' ignored", | 844 | tcc_warning("change type of '%s' from 0x%x to '%s' ignored", |
| 845 | get_tok_str(sym->v, NULL), sym->type.t, newtype); | 845 | get_tok_str(sym->v, NULL), sym->type.t, newtype); |
| 846 | 846 | ||
| @@ -4506,7 +4506,7 @@ redo: · 4505 unmodified lines | |||
| 4506 | ad->a.dllimport = 1; | 4506 | ad->a.dllimport = 1; |
| 4507 | break; | 4507 | break; |
| 4508 | default: | 4508 | default: |
| 4509 | if (NEED_WARNING(tcc_state, unsupported)) | 4509 | if (NEED_WARNING(tcc_state, UNSUPPORTED)) |
| 4510 | tcc_warning("'%s' attribute ignored", get_tok_str(t, NULL)); | 4510 | tcc_warning("'%s' attribute ignored", get_tok_str(t, NULL)); |
| 4511 | /* skip parameters */ | 4511 | /* skip parameters */ |
| 4512 | if (tok == '(') { | 4512 | if (tok == '(') { |
| @@ -5915,7 +5915,7 @@ ST_FUNC void unary(void) · 1402 unmodified lines | |||
| 5915 | len = strlen(funcname) + 1; | 5915 | len = strlen(funcname) + 1; |
| 5916 | /* generate char[len] type */ | 5916 | /* generate char[len] type */ |
| 5917 | type.t = VT_BYTE; | 5917 | type.t = VT_BYTE; |
| 5918 | if (NEED_WARNING(tcc_state, write_strings)) | 5918 | if (NEED_WARNING(tcc_state, WRITE_STRINGS)) |
| 5919 | type.t |= VT_CONSTANT; | 5919 | type.t |= VT_CONSTANT; |
| 5920 | mk_pointer(&type); | 5920 | mk_pointer(&type); |
| 5921 | type.t |= VT_ARRAY; | 5921 | type.t |= VT_ARRAY; |
| @@ -5942,7 +5942,7 @@ ST_FUNC void unary(void) · 20 unmodified lines | |||
| 5942 | if (tcc_state->char_is_unsigned) | 5942 | if (tcc_state->char_is_unsigned) |
| 5943 | t = VT_BYTE | VT_UNSIGNED; | 5943 | t = VT_BYTE | VT_UNSIGNED; |
| 5944 | str_init: | 5944 | str_init: |
| 5945 | if (NEED_WARNING(tcc_state, write_strings)) | 5945 | if (NEED_WARNING(tcc_state, WRITE_STRINGS)) |
| 5946 | t |= VT_CONSTANT; | 5946 | t |= VT_CONSTANT; |
| 5947 | type.t = t; | 5947 | type.t = t; |
| 5948 | mk_pointer(&type); | 5948 | mk_pointer(&type); |
| @@ -6378,7 +6378,7 @@ special_math_val: · 429 unmodified lines | |||
| 6378 | tcc_error("'%s' undeclared", name); | 6378 | tcc_error("'%s' undeclared", name); |
| 6379 | /* for simple function calls, we tolerate undeclared | 6379 | /* for simple function calls, we tolerate undeclared |
| 6380 | external reference to int() function */ | 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 | #ifdef TCC_TARGET_PE | 6382 | #ifdef TCC_TARGET_PE |
| 6383 | /* must warn about using undeclared WINAPI functions | 6383 | /* must warn about using undeclared WINAPI functions |
| 6384 | (which usually start with uppercase letter) */ | 6384 | (which usually start with uppercase letter) */ |
| @@ -1770,7 +1770,7 @@ static void pragma_parse(TCCState *s1) · 1769 unmodified lines | |||
| 1770 | tcc_free(p); | 1770 | tcc_free(p); |
| 1771 | } | 1771 | } |
| 1772 | 1772 | ||
| 1773 | } else if (NEED_WARNING(s1, unsupported)) | 1773 | } else if (NEED_WARNING(s1, UNSUPPORTED)) |
| 1774 | tcc_warning("#pragma %s is ignored", get_tok_str(tok, &tokc)); | 1774 | tcc_warning("#pragma %s is ignored", get_tok_str(tok, &tokc)); |
| 1775 | return; | 1775 | return; |
| 1776 | 1776 | ||