Unified · Split
| @@ -1230,8 +1230,9 @@ LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path) · 1229 unmodified lines | ||
| 1230 | 1230 | s->tcc_lib_path = tcc_strdup(path); |
| 1231 | 1231 | } |
| 1232 | 1232 | |
| 1233 | −#define WD_ALL 0x0001 /* warning is activated when using -Wall */ | |
| 1234 | −#define FD_INVERT 0x0002 /* invert value before storing */ | |
| 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 */ | |
| 1235 | 1236 | |
| 1236 | 1237 | typedef struct FlagDef { |
| 1237 | 1238 | uint16_t offset; |
| @@ -1279,6 +1280,49 @@ ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, const char *name) · 41 unmodified lines | ||
| 1279 | 1280 | return ret; |
| 1280 | 1281 | } |
| 1281 | 1282 | |
| 1283 | +ST_FUNC int set_W_flag(TCCState *s, const FlagDef *flags, const char *optarg) | |
| 1284 | +{ | |
| 1285 | + int value, ret; | |
| 1286 | + const FlagDef *p; | |
| 1287 | + const char *r, *sub; | |
| 1288 | + | |
| 1289 | + value = 1; | |
| 1290 | + r = optarg; | |
| 1291 | + if (no_flag(&r)) | |
| 1292 | + value = 0; | |
| 1293 | + | |
| 1294 | + if ((sub = strchr(r, '=')) != NULL) { | |
| 1295 | + if (strncmp(r, "error", (uintptr_t)(sub - r))) | |
| 1296 | + return -1; | |
| 1297 | + r = ++sub; | |
| 1298 | + if (value) | |
| 1299 | + value = 1 | 2; | |
| 1300 | + } | |
| 1301 | + | |
| 1302 | + /* .offset for "all" is 0 */ | |
| 1303 | + for (ret = -1, p = flags; p->name; ++p) { | |
| 1304 | + if (ret) { | |
| 1305 | + if (strcmp(r, p->name)) | |
| 1306 | + continue; | |
| 1307 | + if (sub != NULL && !(p->flags & WD_ERROR)) | |
| 1308 | + break; | |
| 1309 | + } else { | |
| 1310 | + if (0 == (p->flags & WD_ALL)) | |
| 1311 | + continue; | |
| 1312 | + } | |
| 1313 | + if (p->offset) { | |
| 1314 | + *((unsigned char *)s + p->offset) = value; | |
| 1315 | + if (ret) { | |
| 1316 | + ret = 0; | |
| 1317 | + break; | |
| 1318 | + } | |
| 1319 | + } else { | |
| 1320 | + ret = 0; | |
| 1321 | + } | |
| 1322 | + } | |
| 1323 | + return ret; | |
| 1324 | +} | |
| 1325 | + | |
| 1282 | 1326 | static int strstart(const char *val, const char **str) |
| 1283 | 1327 | { |
| 1284 | 1328 | const char *p, *q; |
| @@ -1469,7 +1513,7 @@ static int tcc_set_linker(TCCState *s, const char *option) · 184 unmodified lines | ||
| 1469 | 1513 | tcc_error("unsupported linker option '%s'", option); |
| 1470 | 1514 | } |
| 1471 | 1515 | |
| 1472 | − if (ignoring && s->warn_unsupported) | |
| 1516 | + if (ignoring && NEED_WARNING(s, unsupported)) | |
| 1473 | 1517 | tcc_warning("unsupported linker option '%s'", option); |
| 1474 | 1518 | |
| 1475 | 1519 | option = skip_linker_arg(&p); |
| @@ -1616,12 +1660,13 @@ static const TCCOption tcc_options[] = { · 140 unmodified lines | ||
| 1616 | 1660 | |
| 1617 | 1661 | static const FlagDef options_W[] = { |
| 1618 | 1662 | { 0, 0, "all" }, |
| 1619 | − { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, | |
| 1620 | − { offsetof(TCCState, warn_write_strings), WD_ALL, "write-strings" }, | |
| 1621 | 1663 | { offsetof(TCCState, warn_error), 0, "error" }, |
| 1622 | − { offsetof(TCCState, warn_gcc_compat), 0, "gcc-compat" }, | |
| 1623 | − { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, | |
| 1624 | − "implicit-function-declaration" }, | |
| 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" }, | |
| 1625 | 1670 | { 0, 0, NULL } |
| 1626 | 1671 | }; |
| 1627 | 1672 | |
| @@ -1920,7 +1965,7 @@ reparse: · 292 unmodified lines | ||
| 1920 | 1965 | break; |
| 1921 | 1966 | case TCC_OPTION_W: |
| 1922 | 1967 | s->warn_none = 0; |
| 1923 | − if (optarg[0] && set_flag(s, options_W, optarg) < 0) | |
| 1968 | + if (optarg[0] && set_W_flag(s, options_W, optarg) < 0) | |
| 1924 | 1969 | goto unsupported_option; |
| 1925 | 1970 | break; |
| 1926 | 1971 | case TCC_OPTION_w: |
| @@ -2007,7 +2052,7 @@ reparse: · 80 unmodified lines | ||
| 2007 | 2052 | break; |
| 2008 | 2053 | default: |
| 2009 | 2054 | unsupported_option: |
| 2010 | − if (s->warn_unsupported) | |
| 2055 | + if (NEED_WARNING(s, unsupported)) | |
| 2011 | 2056 | tcc_warning("unsupported option '%s'", r); |
| 2012 | 2057 | break; |
| 2013 | 2058 | } |
| @@ -267,10 +267,13 @@ 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 warnings are issued. | |
| 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.) | |
| 271 | 274 | |
| 272 | 275 | @item -Wall |
| 273 | −Activate all warnings, except @option{-Werror}, @option{-Wunusupported} and | |
| 276 | +Activate all warnings, except @option{-Werror}, @option{-Wunsupported} and | |
| 274 | 277 | @option{-Wwrite-strings}. |
| 275 | 278 | |
| 276 | 279 | @end table |
| @@ -767,13 +767,17 @@ struct TCCState { · 766 unmodified lines | ||
| 767 | 767 | unsigned char dollars_in_identifiers; /* allows '$' char in identifiers */ |
| 768 | 768 | unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */ |
| 769 | 769 | |
| 770 | − /* warning switches */ | |
| 771 | − unsigned char warn_write_strings; | |
| 772 | − unsigned char warn_unsupported; | |
| 773 | − unsigned char warn_error; | |
| 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 */ | |
| 774 | 772 | unsigned char warn_none; |
| 775 | − unsigned char warn_implicit_function_declaration; | |
| 773 | + unsigned char warn_error; | |
| 774 | + unsigned char warn_unsupported; | |
| 776 | 775 | unsigned char warn_gcc_compat; |
| 776 | + unsigned char warn_write_strings; | |
| 777 | + unsigned char warn_implicit_function_declaration; | |
| 778 | +#define NEED_WARNING(SELF,SWITCH) \ | |
| 779 | + ((SELF)->warn_ ## SWITCH \ | |
| 780 | + ? (((SELF)->warn_ ## SWITCH & 2) ? (SELF)->warn_error = 1 : 1) : 0) | |
| 777 | 781 | |
| 778 | 782 | /* compile with debug symbol (and use them if error during execution) */ |
| 779 | 783 | 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 (s1->warn_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 (s1->warn_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 (s1->warn_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 (s1->warn_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 (tcc_state->warn_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 (tcc_state->warn_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 (tcc_state->warn_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,9 +6378,9 @@ 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 (tcc_state->warn_implicit_function_declaration | |
| 6381 | + if (NEED_WARNING(tcc_state, implicit_function_declaration) | |
| 6382 | 6382 | #ifdef TCC_TARGET_PE |
| 6383 | − /* people must be warned about using undeclared WINAPI functions | |
| 6383 | + /* must warn about using undeclared WINAPI functions | |
| 6384 | 6384 | (which usually start with uppercase letter) */ |
| 6385 | 6385 | || (name[0] >= 'A' && name[0] <= 'Z') |
| 6386 | 6386 | #endif |
| @@ -1770,9 +1770,8 @@ static void pragma_parse(TCCState *s1) · 1769 unmodified lines | ||
| 1770 | 1770 | tcc_free(p); |
| 1771 | 1771 | } |
| 1772 | 1772 | |
| 1773 | − } else if (s1->warn_unsupported) { | |
| 1773 | + } else if (NEED_WARNING(s1, unsupported)) | |
| 1774 | 1774 | tcc_warning("#pragma %s is ignored", get_tok_str(tok, &tokc)); |
| 1775 | − } | |
| 1776 | 1775 | return; |
| 1777 | 1776 | |
| 1778 | 1777 | pragma_err: |