commit 8be2fbd82ef16c8f846fccb46689827ed37997eb Author: jiang Date: Mon Jun 30 16:40:16 2014 +0800 Add warning diff --git a/libtcc.c b/libtcc.c index 7caa7c1..79a2d2c 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1397,8 +1397,9 @@ static const FlagDef warning_defs[] = { { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, { offsetof(TCCState, warn_write_strings), 0, "write-strings" }, { offsetof(TCCState, warn_error), 0, "error" }, - { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, - "implicit-function-declaration" }, + { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, "implicit-function-declaration" }, + { offsetof(TCCState, warn_return_type), WD_ALL, "return-type" }, + { offsetof(TCCState, warn_char_subscripts), WD_ALL, "char-subscripts" }, }; ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags, diff --git a/tcc.h b/tcc.h index c93cedf..596b22f 100644 --- a/tcc.h +++ b/tcc.h @@ -594,6 +594,8 @@ struct TCCState { int warn_error; int warn_none; int warn_implicit_function_declaration; + int warn_return_type; + int warn_char_subscripts; /* compile with debug symbol (and use them if error during execution) */ int do_debug; diff --git a/tccgen.c b/tccgen.c index 1a89d4a..227864e 100644 --- a/tccgen.c +++ b/tccgen.c @@ -2898,42 +2898,47 @@ static void struct_decl(CType *type, int u, int tdef) offset = 0; flexible = 0; while (tok != '}') { - parse_btype(&btype, &ad); + if(!parse_btype(&btype, &ad)){ + if (tok == ';'){ + skip(';'); + continue; + }else if(tok == TOK_EOF || tok == '{') + expect("specifier-qualifier-list at end of input"); + } while (1) { - if (flexible) - tcc_error("flexible array member '%s' not at the end of struct", - get_tok_str(v, NULL)); + if (flexible) + tcc_error("flexible array member '%s' not at the end of struct", get_tok_str(v, NULL)); bit_size = -1; v = 0; type1 = btype; if (tok != ':') { type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT); - if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT) - expect("identifier"); - if (type_size(&type1, &align) < 0) { - if ((a == TOK_STRUCT) && (type1.t & VT_ARRAY) && c) - flexible = 1; - else - tcc_error("field '%s' has incomplete type", - get_tok_str(v, NULL)); + if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT){ + tcc_warning("declaration does not declare anything"); + break; + }if (type_size(&type1, &align) < 0) { + if ((a == TOK_STRUCT) && (type1.t & VT_ARRAY)) + flexible = 1; + else + tcc_error("field '%s' has incomplete type", get_tok_str(v, NULL)); } if ((type1.t & VT_BTYPE) == VT_FUNC || (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE))) - tcc_error("invalid type for '%s'", - get_tok_str(v, NULL)); + tcc_error("invalid type for '%s'", get_tok_str(v, NULL)); } if (tok == ':') { next(); bit_size = expr_const(); /* XXX: handle v = 0 case for messages */ if (bit_size < 0) - tcc_error("negative width in bit-field '%s'", - get_tok_str(v, NULL)); + tcc_error("negative width in bit-field '%s'", get_tok_str(v, NULL)); if (v && bit_size == 0) - tcc_error("zero width for bit-field '%s'", - get_tok_str(v, NULL)); + tcc_error("zero width for bit-field '%s'", get_tok_str(v, NULL)); } - size = type_size(&type1, &align); + if(type1.t & VT_VLA) + size = 0, align = 1; + else + size = type_size(&type1, &align); if (ad.a.aligned) { if (align < ad.a.aligned) align = ad.a.aligned; @@ -2946,12 +2951,9 @@ static void struct_decl(CType *type, int u, int tdef) lbit_pos = 0; if (bit_size >= 0) { bt = type1.t & VT_BTYPE; - if (bt != VT_INT && - bt != VT_BYTE && - bt != VT_SHORT && - bt != VT_BOOL && - bt != VT_ENUM && - bt != VT_LLONG) + if (bt != VT_INT && bt != VT_BYTE && + bt != VT_SHORT && bt != VT_BOOL && + bt != VT_ENUM && bt != VT_LLONG) tcc_error("bitfields must have scalar type"); bsize = size * 8; if (bit_size > bsize) { @@ -3023,13 +3025,19 @@ static void struct_decl(CType *type, int u, int tdef) *ps = ss; ps = &ss->next; } - if (tok == ';' || tok == TOK_EOF) + if (tok == ';' || tok == '}') break; skip(','); } - skip(';'); + if(tok == '}'){ + tcc_warning("no ';' at end of struct or union"); + break; + }else + skip(';'); } - skip('}'); + next(); + if (!c && flexible) + tcc_error("flexible array member '%s' in otherwise empty struct", get_tok_str(v, NULL)); /* store size and alignment */ s->c = (c + maxalign - 1) & -maxalign; s->r = maxalign; @@ -4037,6 +4045,8 @@ ST_FUNC void unary(void) } else if (tok == '[') { next(); gexpr(); + if(tcc_state->warn_char_subscripts && (vtop->type.t & (VT_BTYPE|VT_DEFSIGN|VT_UNSIGNED)) == VT_BYTE) + tcc_warning("array subscript has type 'char'"); gen_op('+'); indir(); skip(']'); @@ -5510,6 +5520,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, Sym *flexible_array; flexible_array = NULL; + if (has_init && (type->t & VT_VLA)) + tcc_error("Variable length array cannot be initialized"); if ((type->t & VT_BTYPE) == VT_STRUCT) { Sym *field = type->ref->next; if (field) { @@ -5907,12 +5919,13 @@ ST_FUNC void gen_inline_functions(void) /* 'l' is VT_LOCAL or VT_CONST to define default storage type */ static int decl0(int l, int is_for_loop_init) { - int v, has_init, r; + int v, has_init, r, imp; CType type, btype; Sym *sym; AttributeDef ad; while (1) { + imp = 0; if (!parse_btype(&btype, &ad)) { if (is_for_loop_init) return 0; @@ -5922,11 +5935,13 @@ static int decl0(int l, int is_for_loop_init) next(); continue; } - if (l == VT_CONST && - (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) { + if (l == VT_CONST){ + if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3){ /* global asm block */ - asm_global_instr(); - continue; + asm_global_instr(); + continue; + } + imp = 1; } /* special test for old K&R protos without explicit int type. Only accepted when defining global data */ @@ -5934,10 +5949,15 @@ static int decl0(int l, int is_for_loop_init) break; btype.t = VT_INT; } - if (((btype.t & VT_BTYPE) == VT_ENUM || - (btype.t & VT_BTYPE) == VT_STRUCT) && - tok == ';') { + if (tok == ';') { + int bt = btype.t & VT_BTYPE; /* we accept no variable after */ + if(btype.t & (VT_CONSTANT|VT_VOLATILE)) + tcc_warning("useless type qualifier in empty declaration.'%s'before", get_tok_str(tok, NULL)); + if(bt != VT_STRUCT && bt != VT_ENUM) + tcc_warning("useless type name in empty declaration '%s'", get_tok_str(tok, NULL)); + if((bt == VT_STRUCT) && ((btype.ref->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM)) + tcc_warning("unnamed struct/union that defines no instances"); next(); continue; } @@ -6097,6 +6117,9 @@ static int decl0(int l, int is_for_loop_init) sym->a = ad.a; sym->type.t |= VT_TYPEDEF; } else { + if(imp && (type.t & VT_BTYPE) != VT_FUNC) + tcc_warning("data definition has no type or storage class: '%s'", + get_tok_str(v, NULL)); r = 0; if ((type.t & VT_BTYPE) == VT_FUNC) { /* external function definition */ @@ -6108,8 +6131,6 @@ static int decl0(int l, int is_for_loop_init) r |= lvalue_type(type.t); } has_init = (tok == '='); - if (has_init && (type.t & VT_VLA)) - tcc_error("Variable length array cannot be initialized"); if ((btype.t & VT_EXTERN) || ((type.t & VT_BTYPE) == VT_FUNC) || ((type.t & VT_ARRAY) && (type.t & VT_STATIC) && !has_init && l == VT_CONST && type.ref->c < 0)) { diff --git a/tests/tests2/46_grep.c b/tests/tests2/46_grep.c index 3123bc3..d789ee0 100644 --- a/tests/tests2/46_grep.c +++ b/tests/tests2/46_grep.c @@ -15,6 +15,7 @@ * privileges were granted by DECUS. */ #include +#include #include /* diff --git a/tests/tests2/64_macro_nesting.c b/tests/tests2/64_macro_nesting.c index 44b582f..2123a75 100644 --- a/tests/tests2/64_macro_nesting.c +++ b/tests/tests2/64_macro_nesting.c @@ -1,3 +1,4 @@ +#include #define CAT2(a,b) a##b #define CAT(a,b) CAT2(a,b) #define AB(x) CAT(x,y) diff --git a/tests/tests2/70_warn_test.c b/tests/tests2/70_warn_test.c new file mode 100644 index 0000000..5543426 --- /dev/null +++ b/tests/tests2/70_warn_test.c @@ -0,0 +1,18 @@ +#include +#define uint8_t unsigned char +const struct { + const uint8_t code +}; + +a; +b,c; + +int main(void) +{ + char c = 1; + int b[2]; + b[c] = 9; + printf("%d\n", b[c]); + printf("ok\n"); + return 0; +} diff --git a/tests/tests2/70_warn_test.expect b/tests/tests2/70_warn_test.expect new file mode 100644 index 0000000..bae7348 --- /dev/null +++ b/tests/tests2/70_warn_test.expect @@ -0,0 +1,10 @@ +70_warn_test.c:5: warning: no ';' at end of struct or union +70_warn_test.c:5: warning: useless type qualifier in empty declaration.';'before +70_warn_test.c:5: warning: unnamed struct/union that defines no instances +70_warn_test.c:7: warning: data definition has no type or storage class: 'a' +70_warn_test.c:8: warning: data definition has no type or storage class: 'b' +70_warn_test.c:8: warning: data definition has no type or storage class: 'c' +70_warn_test.c:14: warning: array subscript has type 'char' +70_warn_test.c:15: warning: array subscript has type 'char' +9 +ok diff --git a/tests/tests2/71_err_struct.c b/tests/tests2/71_err_struct.c new file mode 100644 index 0000000..276c993 --- /dev/null +++ b/tests/tests2/71_err_struct.c @@ -0,0 +1,8 @@ +typedef struct { + const uint8_t* code; +} st; + +int main(void) +{ + return 0; +} diff --git a/tests/tests2/71_err_struct.expect b/tests/tests2/71_err_struct.expect new file mode 100644 index 0000000..239c174 --- /dev/null +++ b/tests/tests2/71_err_struct.expect @@ -0,0 +1 @@ +71_err_struct.c:2: error: ',' expected (got "*") diff --git a/tests/tests2/72_err_struct.c b/tests/tests2/72_err_struct.c new file mode 100644 index 0000000..e3d7afd --- /dev/null +++ b/tests/tests2/72_err_struct.c @@ -0,0 +1,11 @@ +#include +typedef struct { + int; + int; +;{}; + +int main(void) +{ + printf("ok\n"); + return 0; +} diff --git a/tests/tests2/72_err_struct.expect b/tests/tests2/72_err_struct.expect new file mode 100644 index 0000000..7aaf45a --- /dev/null +++ b/tests/tests2/72_err_struct.expect @@ -0,0 +1,3 @@ +72_err_struct.c:3: warning: declaration does not declare anything +72_err_struct.c:4: warning: declaration does not declare anything +72_err_struct.c:5: error: specifier-qualifier-list at end of input expected diff --git a/tests/tests2/73_err_struct.c b/tests/tests2/73_err_struct.c new file mode 100644 index 0000000..6851b76 --- /dev/null +++ b/tests/tests2/73_err_struct.c @@ -0,0 +1,11 @@ +#include +typedef struct { + int a[]; + int b; +}; + +int main(void) +{ + printf("ok\n"); + return 0; +} diff --git a/tests/tests2/73_err_struct.expect b/tests/tests2/73_err_struct.expect new file mode 100644 index 0000000..d42b710 --- /dev/null +++ b/tests/tests2/73_err_struct.expect @@ -0,0 +1 @@ +73_err_struct.c:4: error: flexible array member 'a' not at the end of struct diff --git a/tests/tests2/74_err_struct.c b/tests/tests2/74_err_struct.c new file mode 100644 index 0000000..40c5fd4 --- /dev/null +++ b/tests/tests2/74_err_struct.c @@ -0,0 +1,10 @@ +#include +typedef struct { + int a[]; +}; + +int main(void) +{ + printf("ok\n"); + return 0; +} diff --git a/tests/tests2/74_err_struct.expect b/tests/tests2/74_err_struct.expect new file mode 100644 index 0000000..2338ad0 --- /dev/null +++ b/tests/tests2/74_err_struct.expect @@ -0,0 +1 @@ +74_err_struct.c:4: error: flexible array member 'a' in otherwise empty struct diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 64532a1..104d456 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -84,7 +84,12 @@ TESTS = \ 66_macro_concat_end.test \ 67_macro_concat.test \ 68_macro_concat.test \ - 69_macro_concat.test + 69_macro_concat.test \ + 70_warn_test.test \ + 71_err_struct.test \ + 72_err_struct.test \ + 73_err_struct.test \ + 74_err_struct.test # 34_array_assignment.test -- array assignment is not in C standard @@ -109,10 +114,10 @@ all test: $(filter-out $(SKIP),$(TESTS)) %.test: %.c %.expect @echo Test: $*... - @$(TCC) -run $< $(ARGS) >$*.output 2>&1 || true + @$(TCC) -Wall -run $< $(ARGS) >$*.output 2>&1 || true @diff -bu $*.expect $*.output && rm -f $*.output - @($(TCC) $< -o $*.exe && ./$*.exe $(ARGS)) >$*.output2 2>&1 || true + @($(TCC) -Wall $< -o $*.exe && ./$*.exe $(ARGS)) >$*.output2 2>&1 || true @diff -bu $*.expect $*.output2 && rm -f $*.output2 $*.exe clean: