mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-13 05:10:07 +08:00
-W[no-]error...: features by shrinkage
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
This commit is contained in:
parent
931a146591
commit
4b2c6cf3a4
218
libtcc.c
218
libtcc.c
@ -510,10 +510,6 @@ static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#define ERROR_WARN 0
|
||||
#define ERROR_NOABORT 1
|
||||
#define ERROR_ERROR 2
|
||||
|
||||
PUB_FUNC void tcc_enter_state(TCCState *s1)
|
||||
{
|
||||
WAIT_SEM();
|
||||
@ -526,6 +522,10 @@ PUB_FUNC void tcc_exit_state(void)
|
||||
POST_SEM();
|
||||
}
|
||||
|
||||
#define ERROR_WARN 0
|
||||
#define ERROR_NOABORT 1
|
||||
#define ERROR_ERROR 2
|
||||
|
||||
static void error1(int mode, const char *fmt, va_list ap)
|
||||
{
|
||||
char buf[2048];
|
||||
@ -537,15 +537,26 @@ static void error1(int mode, const char *fmt, va_list ap)
|
||||
/* can happen only if called from tcc_malloc(): 'out of memory' */
|
||||
goto no_file;
|
||||
|
||||
if (s1 && !s1->error_set_jmp_enabled)
|
||||
if (!s1->error_set_jmp_enabled)
|
||||
/* tcc_state just was set by tcc_enter_state() */
|
||||
tcc_exit_state();
|
||||
|
||||
if (mode == ERROR_WARN) {
|
||||
if (s1->warn_mask & WARN_DISABLED)
|
||||
return;
|
||||
if (s1->warn_mask & WARN_ERROR_MASK) /* XXX individual ignorance */
|
||||
if (s1->warn_error)
|
||||
mode = ERROR_ERROR;
|
||||
if (s1->warn_num) {
|
||||
/* handle tcc_warning_c(warn_option)(fmt, ...) */
|
||||
int wopt = *(&s1->warn_none + s1->warn_num);
|
||||
s1->warn_num = 0;
|
||||
if (0 == (wopt & WARN_ON))
|
||||
return;
|
||||
if (wopt & WARN_ERR)
|
||||
mode = ERROR_ERROR;
|
||||
if (wopt & WARN_NOE)
|
||||
mode = ERROR_WARN;
|
||||
}
|
||||
if (s1->warn_none)
|
||||
return;
|
||||
}
|
||||
|
||||
f = NULL;
|
||||
@ -786,7 +797,8 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
s->nocommon = 1;
|
||||
s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/
|
||||
s->cversion = 199901; /* default unless -std=c11 is supplied */
|
||||
s->warn_mask |= WARN_IMPLICIT_FUNCTION_DECLARATION;
|
||||
s->warn_implicit_function_declaration = 1;
|
||||
s->warn_discarded_qualifiers = 1;
|
||||
s->ms_extensions = 1;
|
||||
|
||||
#ifdef CHAR_IS_UNSIGNED
|
||||
@ -1230,122 +1242,8 @@ LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path)
|
||||
s->tcc_lib_path = tcc_strdup(path);
|
||||
}
|
||||
|
||||
#define WD_ALL (1u<<0) /* warning is activated when using -Wall */
|
||||
#define WD_ERROR (1u<<1) /* can be used with -W[no-]error=X */
|
||||
#define FD_INVERT (1u<<2) /* invert value before storing */
|
||||
|
||||
typedef struct FlagDef {
|
||||
uint16_t offset;
|
||||
uint16_t flags;
|
||||
const char *name;
|
||||
} FlagDef;
|
||||
|
||||
static int no_flag(const char **pp)
|
||||
{
|
||||
const char *p = *pp;
|
||||
if (*p != 'n' || *++p != 'o' || *++p != '-')
|
||||
return 0;
|
||||
*pp = p + 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, const char *name)
|
||||
{
|
||||
int value, ret;
|
||||
const FlagDef *p;
|
||||
const char *r;
|
||||
|
||||
value = 1;
|
||||
r = name;
|
||||
if (no_flag(&r))
|
||||
value = 0;
|
||||
|
||||
for (ret = -1, p = flags; p->name; ++p) {
|
||||
if (ret) {
|
||||
if (strcmp(r, p->name))
|
||||
continue;
|
||||
} else {
|
||||
if (0 == (p->flags & WD_ALL))
|
||||
continue;
|
||||
}
|
||||
if (p->offset) {
|
||||
*((unsigned char *)s + p->offset) =
|
||||
p->flags & FD_INVERT ? !value : value;
|
||||
if (ret)
|
||||
return 0;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ST_FUNC int set_W_flag(TCCState *s, const char *optarg)
|
||||
{
|
||||
static struct a_W_flag{
|
||||
uint32_t wbit;
|
||||
uint32_t flags;
|
||||
char const *name;
|
||||
} const opts[] = {
|
||||
{WARN_ALL, 0, "all"},
|
||||
{WARN_ERROR | (WARN_ERROR << WARN_ERROR_SHIFT), 0, "error"},
|
||||
{WARN_UNSUPPORTED, WD_ERROR, "unsupported"},
|
||||
{WARN_GCC_COMPAT, WD_ERROR, "gcc-compat"},
|
||||
{WARN_WRITE_STRINGS, WD_ERROR | WD_ALL, "write-strings"},
|
||||
{WARN_IMPLICIT_FUNCTION_DECLARATION, WD_ERROR | WD_ALL,
|
||||
"implicit-function-declaration"}
|
||||
}, *p;
|
||||
|
||||
int ret;
|
||||
unsigned char mode;
|
||||
const char *r, *sub;
|
||||
|
||||
mode = 1;
|
||||
r = optarg;
|
||||
if (no_flag(&r))
|
||||
mode = 0;
|
||||
|
||||
if ((sub = strchr(r, '=')) != NULL) {
|
||||
if (strncmp(r, "error", (uintptr_t)(sub - r)))
|
||||
return -1;
|
||||
r = ++sub;
|
||||
mode |= 2;
|
||||
}
|
||||
|
||||
for (ret = -1, p = opts; p < &opts[countof(opts)]; ++p) {
|
||||
if (ret) {
|
||||
if (strcmp(r, p->name))
|
||||
continue;
|
||||
if ((mode & 2) && !(p->flags & WD_ERROR))
|
||||
break;
|
||||
} else {
|
||||
if (0 == (p->flags & WD_ALL))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p->wbit == WARN_ALL) {
|
||||
/* Start a loop over all the rest */
|
||||
ret = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mode & 1) {
|
||||
s->warn_mask |= p->wbit;
|
||||
if (mode & 2)
|
||||
s->warn_mask |= p->wbit << WARN_ERROR_SHIFT;
|
||||
} else {
|
||||
s->warn_mask &= ~(p->wbit << ((mode & 2) ? WARN_ERROR_SHIFT : 0));
|
||||
}
|
||||
|
||||
/* Done if not in "all" mode */
|
||||
if (ret) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/********************************************************/
|
||||
/* options parser */
|
||||
|
||||
static int strstart(const char *val, const char **str)
|
||||
{
|
||||
@ -1388,7 +1286,7 @@ static int link_option(const char *str, const char *val, const char **ptr)
|
||||
ret = 1;
|
||||
if (q[0] == '?') {
|
||||
++q;
|
||||
if (no_flag(&p))
|
||||
if (strstart("no-", &p))
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
@ -1536,10 +1434,8 @@ static int tcc_set_linker(TCCState *s, const char *option)
|
||||
err:
|
||||
tcc_error("unsupported linker option '%s'", option);
|
||||
}
|
||||
|
||||
if (ignoring && NEED_WARNING(s, UNSUPPORTED))
|
||||
tcc_warning("unsupported linker option '%s'", option);
|
||||
|
||||
if (ignoring)
|
||||
tcc_warning_c(warn_unsupported)("unsupported linker option '%s'", option);
|
||||
option = skip_linker_arg(&p);
|
||||
}
|
||||
return 1;
|
||||
@ -1682,6 +1578,25 @@ static const TCCOption tcc_options[] = {
|
||||
{ NULL, 0, 0 },
|
||||
};
|
||||
|
||||
typedef struct FlagDef {
|
||||
uint16_t offset;
|
||||
uint16_t flags;
|
||||
const char *name;
|
||||
} FlagDef;
|
||||
|
||||
#define WD_ALL 0x0001 /* warning is activated when using -Wall */
|
||||
#define FD_INVERT 0x0002 /* invert value before storing */
|
||||
|
||||
static const FlagDef options_W[] = {
|
||||
{ offsetof(TCCState, warn_all), WD_ALL, "all" },
|
||||
{ offsetof(TCCState, warn_error), 0, "error" },
|
||||
{ offsetof(TCCState, warn_write_strings), 0, "write-strings" },
|
||||
{ offsetof(TCCState, warn_unsupported), 0, "unsupported" },
|
||||
{ offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, "implicit-function-declaration" },
|
||||
{ offsetof(TCCState, warn_discarded_qualifiers), WD_ALL, "discarded-qualifiers" },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static const FlagDef options_f[] = {
|
||||
{ offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
|
||||
{ offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
|
||||
@ -1701,6 +1616,40 @@ static const FlagDef options_m[] = {
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static int set_flag(TCCState *s, const FlagDef *flags, const char *name)
|
||||
{
|
||||
int value, mask, ret;
|
||||
const FlagDef *p;
|
||||
const char *r;
|
||||
unsigned char *f;
|
||||
|
||||
r = name, value = !strstart("no-", &r), mask = 0;
|
||||
|
||||
/* when called with options_W, look for -W[no-]error=<option> */
|
||||
if ((flags->flags & WD_ALL) && strstart("error=", &r))
|
||||
value = value ? WARN_ON|WARN_ERR : WARN_NOE, mask = WARN_ON;
|
||||
|
||||
for (ret = -1, p = flags; p->name; ++p) {
|
||||
if (ret) {
|
||||
if (strcmp(r, p->name))
|
||||
continue;
|
||||
} else {
|
||||
if (0 == (p->flags & WD_ALL))
|
||||
continue;
|
||||
}
|
||||
|
||||
f = (unsigned char *)s + p->offset;
|
||||
*f = (*f & mask) | (value ^ !!(p->flags & FD_INVERT));
|
||||
|
||||
if (ret) {
|
||||
ret = 0;
|
||||
if (strcmp(r, "all"))
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void args_parser_add_file(TCCState *s, const char* filename, int filetype)
|
||||
{
|
||||
struct filespec *f = tcc_malloc(sizeof *f + strlen(filename));
|
||||
@ -1976,12 +1925,12 @@ reparse:
|
||||
}
|
||||
break;
|
||||
case TCC_OPTION_W:
|
||||
s->warn_mask &= ~WARN_DISABLED;
|
||||
if (optarg[0] && set_W_flag(s, optarg) < 0)
|
||||
s->warn_none = 0;
|
||||
if (optarg[0] && set_flag(s, options_W, optarg) < 0)
|
||||
goto unsupported_option;
|
||||
break;
|
||||
case TCC_OPTION_w:
|
||||
s->warn_mask |= WARN_DISABLED;
|
||||
s->warn_none = 1;
|
||||
break;
|
||||
case TCC_OPTION_rdynamic:
|
||||
s->rdynamic = 1;
|
||||
@ -2064,8 +2013,7 @@ reparse:
|
||||
break;
|
||||
default:
|
||||
unsupported_option:
|
||||
if (NEED_WARNING(s, UNSUPPORTED))
|
||||
tcc_warning("unsupported option '%s'", r);
|
||||
tcc_warning_c(warn_unsupported)("unsupported option '%s'", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
11
tcc-doc.texi
11
tcc-doc.texi
@ -267,15 +267,12 @@ Make string constants be of type @code{const char *} instead of @code{char
|
||||
*}.
|
||||
|
||||
@item -Werror
|
||||
Abort compilation if a warning is issued.
|
||||
Can be given an option to enable the specified warning
|
||||
and turn it into an error, for example @option{-Werror=unsupported}.
|
||||
Enabling general abortion and disabling specifics is not supported.
|
||||
Disabling specific abortions again does not disable the according warning.
|
||||
Abort compilation if a warning is issued. Can be given an option to enable
|
||||
the specified warning and turn it into an error, for example
|
||||
@option{-Werror=unsupported}.
|
||||
|
||||
@item -Wall
|
||||
Activate all warnings, except @option{-Werror}, @option{-Wunsupported} and
|
||||
@option{-Wwrite-strings}.
|
||||
Activate some useful warnings.
|
||||
|
||||
@end table
|
||||
|
||||
|
13
tcc.c
13
tcc.c
@ -36,7 +36,7 @@ static const char help[] =
|
||||
" -std=c99 Conform to the ISO 1999 C standard (default).\n"
|
||||
" -std=c11 Conform to the ISO 2011 C standard.\n"
|
||||
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
|
||||
" -w disable all warnings and their consequences\n"
|
||||
" -w disable all warnings\n"
|
||||
" --version -v show version\n"
|
||||
" -vv show search paths or loaded files\n"
|
||||
" -h -hh show this, show more help\n"
|
||||
@ -103,10 +103,11 @@ static const char help2[] =
|
||||
" --param -pedantic -pipe -s -traditional\n"
|
||||
"-W[no-]... warnings:\n"
|
||||
" all turn on some (*) warnings\n"
|
||||
" error[=(X)] error out after first warning (for X)\n"
|
||||
" unsupported warn for ignored options, pragmas,.. (X)\n"
|
||||
" write-strings strings are const (*,X)\n"
|
||||
" implicit-function-declaration warn for missing prototype (*,X)\n"
|
||||
" error[=warning] stop after warning (any or specified)\n"
|
||||
" write-strings strings are const\n"
|
||||
" unsupported warn about ignored options, pragmas, etc.\n"
|
||||
" implicit-function-declaration warn for missing prototype (*)\n"
|
||||
" discarded-qualifiers warn when const is dropped (*)\n"
|
||||
"-f[no-]... flags:\n"
|
||||
" unsigned-char default char is unsigned\n"
|
||||
" signed-char default char is signed\n"
|
||||
@ -317,7 +318,7 @@ redo:
|
||||
}
|
||||
|
||||
if (s->nb_files == 0)
|
||||
tcc_error("no input files\n");
|
||||
tcc_error("no input files");
|
||||
|
||||
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
if (s->outfile && 0!=strcmp("-",s->outfile)) {
|
||||
|
44
tcc.h
44
tcc.h
@ -737,24 +737,6 @@ struct sym_attr {
|
||||
#endif
|
||||
};
|
||||
|
||||
/* 32-bit bit carrier, split in two halves: lower=warn, upper=error */
|
||||
enum warn_option {
|
||||
WARN_NONE,
|
||||
WARN_UNSUPPORTED = 1u<<0,
|
||||
WARN_GCC_COMPAT = 1u<<1,
|
||||
WARN_WRITE_STRINGS = 1u<<2,
|
||||
WARN_IMPLICIT_FUNCTION_DECLARATION = 1u<<3,
|
||||
/* _ERROR is in lower as "max", there is no warning for it */
|
||||
WARN_ERROR = 1u<<4,
|
||||
WARN_ALL = WARN_ERROR - 1,
|
||||
/* Is neither in lower nor upper: disables warnings and errors (-w) */
|
||||
WARN_DISABLED = WARN_ERROR << 1
|
||||
};
|
||||
enum {
|
||||
WARN_ERROR_SHIFT = 16u,
|
||||
WARN_ERROR_MASK = (/*WARN_ALL |*/ WARN_ERROR) << WARN_ERROR_SHIFT
|
||||
};
|
||||
|
||||
struct TCCState {
|
||||
unsigned char verbose; /* if true, display some information during compilation */
|
||||
unsigned char nostdinc; /* if true, no standard headers are added */
|
||||
@ -785,13 +767,18 @@ struct TCCState {
|
||||
unsigned char dollars_in_identifiers; /* allows '$' char in identifiers */
|
||||
unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */
|
||||
|
||||
/* NEED_WARNING(SELF,X) used to drive W[[no-]error]=X */
|
||||
uint32_t warn_mask;
|
||||
#define NEED_WARNING(SELF,SWITCH) \
|
||||
(((SELF)->warn_mask & \
|
||||
(WARN_ ## SWITCH | (WARN_ ## SWITCH << WARN_ERROR_SHIFT))) \
|
||||
? (((SELF)->warn_mask & (WARN_ ## SWITCH << WARN_ERROR_SHIFT)) \
|
||||
? (SELF)->warn_mask |= (WARN_ERROR << WARN_ERROR_SHIFT), 1 : 1) : 0)
|
||||
/* warning switches */
|
||||
unsigned char warn_none;
|
||||
unsigned char warn_all;
|
||||
unsigned char warn_error;
|
||||
unsigned char warn_write_strings;
|
||||
unsigned char warn_unsupported;
|
||||
unsigned char warn_implicit_function_declaration;
|
||||
unsigned char warn_discarded_qualifiers;
|
||||
#define WARN_ON 1 /* warning is on (-Woption) */
|
||||
#define WARN_ERR 2 /* warning is an error (-Werror=option) */
|
||||
#define WARN_NOE 4 /* warning is not an error (-Wno-error=option) */
|
||||
unsigned char warn_num; /* temp var for tcc_warning_c() */
|
||||
|
||||
/* compile with debug symbol (and use them if error during execution) */
|
||||
unsigned char do_debug;
|
||||
@ -1890,6 +1877,11 @@ ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename)
|
||||
PUB_FUNC void tcc_enter_state(TCCState *s1);
|
||||
PUB_FUNC void tcc_exit_state(void);
|
||||
|
||||
/* conditional warning depending on switch */
|
||||
#define tcc_warning_c(sw) TCC_SET_STATE((\
|
||||
tcc_state->warn_num = offsetof(TCCState, sw) \
|
||||
- offsetof(TCCState, warn_none), _tcc_warning))
|
||||
|
||||
/********************************************************/
|
||||
#endif /* _TCC_H */
|
||||
|
||||
@ -1903,6 +1895,4 @@ PUB_FUNC void tcc_exit_state(void);
|
||||
#else
|
||||
# define TCC_STATE_VAR(sym) s1->sym
|
||||
# define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn)
|
||||
/* actually we could avoid the tcc_enter_state(s1) hack by using
|
||||
__VA_ARGS__ except that some compiler doesn't support it. */
|
||||
#endif
|
||||
|
22
tccasm.c
22
tccasm.c
@ -769,15 +769,11 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
|
||||
filename[0] = '\0';
|
||||
next();
|
||||
|
||||
if (tok == TOK_STR)
|
||||
pstrcat(filename, sizeof(filename), tokc.str.data);
|
||||
else
|
||||
pstrcat(filename, sizeof(filename), get_tok_str(tok, NULL));
|
||||
|
||||
if (NEED_WARNING(s1, UNSUPPORTED))
|
||||
tcc_warning("ignoring .file %s", filename);
|
||||
|
||||
tcc_warning_c(warn_unsupported)("ignoring .file %s", filename);
|
||||
next();
|
||||
}
|
||||
break;
|
||||
@ -787,15 +783,11 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
|
||||
ident[0] = '\0';
|
||||
next();
|
||||
|
||||
if (tok == TOK_STR)
|
||||
pstrcat(ident, sizeof(ident), tokc.str.data);
|
||||
else
|
||||
pstrcat(ident, sizeof(ident), get_tok_str(tok, NULL));
|
||||
|
||||
if (NEED_WARNING(s1, UNSUPPORTED))
|
||||
tcc_warning("ignoring .ident %s", ident);
|
||||
|
||||
tcc_warning_c(warn_unsupported)("ignoring .ident %s", ident);
|
||||
next();
|
||||
}
|
||||
break;
|
||||
@ -808,11 +800,8 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
if (!sym) {
|
||||
tcc_error("label not found: %s", get_tok_str(tok, NULL));
|
||||
}
|
||||
|
||||
/* XXX .size name,label2-label1 */
|
||||
if (NEED_WARNING(s1, UNSUPPORTED))
|
||||
tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL));
|
||||
|
||||
tcc_warning_c(warn_unsupported)("ignoring .size %s,*", get_tok_str(tok, NULL));
|
||||
next();
|
||||
skip(',');
|
||||
while (tok != TOK_LINEFEED && tok != ';' && tok != CH_EOF) {
|
||||
@ -839,9 +828,8 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
|
||||
if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
|
||||
sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC;
|
||||
}
|
||||
else if (NEED_WARNING(s1, UNSUPPORTED))
|
||||
tcc_warning("change type of '%s' from 0x%x to '%s' ignored",
|
||||
} else
|
||||
tcc_warning_c(warn_unsupported)("change type of '%s' from 0x%x to '%s' ignored",
|
||||
get_tok_str(sym->v, NULL), sym->type.t, newtype);
|
||||
|
||||
next();
|
||||
|
46
tccgen.c
46
tccgen.c
@ -4077,7 +4077,7 @@ static void verify_assign_cast(CType *dt)
|
||||
}
|
||||
}
|
||||
if (qualwarn)
|
||||
tcc_warning("assignment discards qualifiers from pointer target type");
|
||||
tcc_warning_c(warn_discarded_qualifiers)("assignment discards qualifiers from pointer target type");
|
||||
break;
|
||||
case VT_BYTE:
|
||||
case VT_SHORT:
|
||||
@ -4355,9 +4355,9 @@ redo:
|
||||
skip('(');
|
||||
s = sym_find(tok);
|
||||
if (!s) {
|
||||
tcc_warning("implicit declaration of function '%s'",
|
||||
get_tok_str(tok, &tokc));
|
||||
s = external_global_sym(tok, &func_old_type);
|
||||
tcc_warning_c(warn_implicit_function_declaration)(
|
||||
"implicit declaration of function '%s'", get_tok_str(tok, &tokc));
|
||||
s = external_global_sym(tok, &func_old_type);
|
||||
} else if ((s->type.t & VT_BTYPE) != VT_FUNC)
|
||||
tcc_error("'%s' is not declared as function", get_tok_str(tok, &tokc));
|
||||
ad->cleanup_func = s;
|
||||
@ -4506,8 +4506,7 @@ redo:
|
||||
ad->a.dllimport = 1;
|
||||
break;
|
||||
default:
|
||||
if (NEED_WARNING(tcc_state, UNSUPPORTED))
|
||||
tcc_warning("'%s' attribute ignored", get_tok_str(t, NULL));
|
||||
tcc_warning_c(warn_unsupported)("'%s' attribute ignored", get_tok_str(t, NULL));
|
||||
/* skip parameters */
|
||||
if (tok == '(') {
|
||||
int parenthesis = 0;
|
||||
@ -5909,23 +5908,20 @@ ST_FUNC void unary(void)
|
||||
case TOK___FUNC__:
|
||||
{
|
||||
Section *sec;
|
||||
void *ptr;
|
||||
int len;
|
||||
/* special function name identifier */
|
||||
len = strlen(funcname) + 1;
|
||||
/* generate char[len] type */
|
||||
type.t = VT_BYTE;
|
||||
if (NEED_WARNING(tcc_state, WRITE_STRINGS))
|
||||
type.t = char_type.t;
|
||||
if (tcc_state->warn_write_strings & WARN_ON)
|
||||
type.t |= VT_CONSTANT;
|
||||
mk_pointer(&type);
|
||||
type.t |= VT_ARRAY;
|
||||
type.ref->c = len;
|
||||
sec = rodata_section;
|
||||
vpush_ref(&type, sec, sec->data_offset, len);
|
||||
if (!NODATA_WANTED) {
|
||||
ptr = section_ptr_add(sec, len);
|
||||
memcpy(ptr, funcname, len);
|
||||
}
|
||||
if (!NODATA_WANTED)
|
||||
memcpy(section_ptr_add(sec, len), funcname, len);
|
||||
next();
|
||||
}
|
||||
break;
|
||||
@ -5938,11 +5934,9 @@ ST_FUNC void unary(void)
|
||||
goto str_init;
|
||||
case TOK_STR:
|
||||
/* string parsing */
|
||||
t = VT_BYTE;
|
||||
if (tcc_state->char_is_unsigned)
|
||||
t = VT_BYTE | VT_UNSIGNED;
|
||||
t = char_type.t;
|
||||
str_init:
|
||||
if (NEED_WARNING(tcc_state, WRITE_STRINGS))
|
||||
if (tcc_state->warn_write_strings & WARN_ON)
|
||||
t |= VT_CONSTANT;
|
||||
type.t = t;
|
||||
mk_pointer(&type);
|
||||
@ -6378,14 +6372,8 @@ special_math_val:
|
||||
tcc_error("'%s' undeclared", name);
|
||||
/* for simple function calls, we tolerate undeclared
|
||||
external reference to int() function */
|
||||
if (NEED_WARNING(tcc_state, IMPLICIT_FUNCTION_DECLARATION)
|
||||
#ifdef TCC_TARGET_PE
|
||||
/* must warn about using undeclared WINAPI functions
|
||||
(which usually start with uppercase letter) */
|
||||
|| (name[0] >= 'A' && name[0] <= 'Z')
|
||||
#endif
|
||||
)
|
||||
tcc_warning("implicit declaration of function '%s'", name);
|
||||
tcc_warning_c(warn_implicit_function_declaration)(
|
||||
"implicit declaration of function '%s'", name);
|
||||
s = external_global_sym(t, &func_old_type);
|
||||
}
|
||||
|
||||
@ -7650,12 +7638,10 @@ again:
|
||||
|
||||
block_after_label:
|
||||
vla_restore(cur_scope->vla.loc);
|
||||
/* we accept this, but it is a mistake */
|
||||
if (tok == '}') {
|
||||
tcc_warning("deprecated use of label at end of compound statement");
|
||||
} else {
|
||||
if (tok != '}')
|
||||
goto again;
|
||||
}
|
||||
/* we accept this, but it is a mistake */
|
||||
tcc_warning_c(warn_all)("deprecated use of label at end of compound statement");
|
||||
|
||||
} else {
|
||||
/* expression case */
|
||||
|
8
tccpp.c
8
tccpp.c
@ -1435,7 +1435,7 @@ ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep)
|
||||
for(s = *ptop; s != slast; s = s1) {
|
||||
s1 = s->prev;
|
||||
if (s->r == LABEL_DECLARED) {
|
||||
tcc_warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
|
||||
tcc_warning_c(warn_all)("label '%s' declared but not used", get_tok_str(s->v, NULL));
|
||||
} else if (s->r == LABEL_FORWARD) {
|
||||
tcc_error("label '%s' used but not defined",
|
||||
get_tok_str(s->v, NULL));
|
||||
@ -1770,8 +1770,8 @@ static void pragma_parse(TCCState *s1)
|
||||
tcc_free(p);
|
||||
}
|
||||
|
||||
} else if (NEED_WARNING(s1, UNSUPPORTED))
|
||||
tcc_warning("#pragma %s is ignored", get_tok_str(tok, &tokc));
|
||||
} else
|
||||
tcc_warning_c(warn_unsupported)("#pragma %s ignored", get_tok_str(tok, &tokc));
|
||||
return;
|
||||
|
||||
pragma_err:
|
||||
@ -2293,7 +2293,7 @@ static void parse_string(const char *s, int len)
|
||||
if (n < 1)
|
||||
tcc_error("empty character constant");
|
||||
if (n > 1)
|
||||
tcc_warning("multi-character character constant");
|
||||
tcc_warning_c(warn_all)("multi-character character constant");
|
||||
for (c = i = 0; i < n; ++i) {
|
||||
if (is_long)
|
||||
c = ((nwchar_t *)tokcstr.data)[i];
|
||||
|
@ -399,4 +399,21 @@ int array[] = { 1, 2, 3 };
|
||||
void v() {}
|
||||
int f() { return v(); }
|
||||
|
||||
#elif defined test_switch_W1 || defined test_switch_W2 \
|
||||
|| defined test_switch_W3 || defined test_switch_W4
|
||||
#if defined test_switch_W1
|
||||
#pragma comment(option, "-Wall")
|
||||
#elif defined test_switch_W2
|
||||
#pragma comment(option, "-Wunsupported -Wno-implicit-function-declaration -Wstuff")
|
||||
#elif defined test_switch_W3
|
||||
#pragma comment(option, "-Wwrite-strings -Werror=discarded-qualifiers")
|
||||
#elif defined test_switch_W4
|
||||
#pragma comment(option, "-Wunsupported -Wno-error=implicit-function-declaration -Werror")
|
||||
#endif
|
||||
void func()
|
||||
{
|
||||
char *ccp = "123";
|
||||
fink();
|
||||
}
|
||||
__attribute__((stuff)) int fink() {return 0;}
|
||||
#endif
|
||||
|
@ -189,3 +189,17 @@ bar : 3 ; 3
|
||||
|
||||
[test_cast_from_void]
|
||||
60_errors_and_warnings.c:400: error: cannot convert 'void' to 'int'
|
||||
|
||||
[test_switch_W1]
|
||||
60_errors_and_warnings.c:416: warning: implicit declaration of function 'fink'
|
||||
|
||||
[test_switch_W2]
|
||||
60_errors_and_warnings.c:407: warning: unsupported option '-Wstuff'
|
||||
60_errors_and_warnings.c:418: warning: 'stuff' attribute ignored
|
||||
|
||||
[test_switch_W3]
|
||||
60_errors_and_warnings.c:415: error: assignment discards qualifiers from pointer target type
|
||||
|
||||
[test_switch_W4]
|
||||
60_errors_and_warnings.c:416: warning: implicit declaration of function 'fink'
|
||||
60_errors_and_warnings.c:418: error: 'stuff' attribute ignored
|
||||
|
Loading…
Reference in New Issue
Block a user