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

Reply via email to