Struct improved algorithms and add struct warnings and other warnings.
The following can be compiled:
struct st{int a;;;;;;;};
If you do not have advice, tomorrow pushed into the mob.
jiang
commit 8be2fbd82ef16c8f846fccb46689827ed37997eb
Author: jiang <[email protected]>
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 <stdio.h>
+#include <ctype.h>
#include <stdlib.h>
/*
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 <stdio.h>
#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 <stdio.h>
+#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 <stdio.h>
+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 <stdio.h>
+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 <stdio.h>
+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:
_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel