diff --git a/tccgen.c b/tccgen.c
index 6c3f0c70..1fb65e0d 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -93,7 +93,7 @@ static int parse_btype(CType *type, AttributeDef *ad);
 static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
 static void parse_expr_type(CType *type);
 static void init_putv(CType *type, Section *sec, unsigned long c);
-static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only);
+static void decl_initializer(CType *type, Section *sec, unsigned long c, int flags);
 static void block(int *bsym, int *csym, int is_expr);
 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);
 static void decl(int l);
@@ -6596,14 +6596,18 @@ static void init_putz(Section *sec, unsigned long c, int size)
     }
 }
 
+#define DIF_FIRST     1
+#define DIF_SIZE_ONLY 2
+#define DIF_HAVE_ELEM 4
+
 /* t is the array or struct type. c is the array or struct
    address. cur_field is the pointer to the current
    field, for arrays the 'c' member contains the current start
-   index.  'size_only' is true if only size info is needed (only used
-   in arrays).  al contains the already initialized length of the
+   index.  'flags' is as in decl_initializer.
+   'al' contains the already initialized length of the
    current container (starting at c).  This returns the new length of that.  */
 static int decl_designator(CType *type, Section *sec, unsigned long c,
-                           Sym **cur_field, int size_only, int al)
+                           Sym **cur_field, int flags, int al)
 {
     Sym *s, *f;
     int index, index_last, align, l, nb_elems, elem_size;
@@ -6611,6 +6615,8 @@ static int decl_designator(CType *type, Section *sec, unsigned long c,
 
     elem_size = 0;
     nb_elems = 1;
+    if (flags & DIF_HAVE_ELEM)
+        goto no_designator;
     if (gnu_ext && (l = is_label()) != 0)
         goto struct_field;
     /* NOTE: we only support ranges for last designator */
@@ -6659,6 +6665,7 @@ static int decl_designator(CType *type, Section *sec, unsigned long c,
 	    expect("=");
         }
     } else {
+    no_designator:
         if (type->t & VT_ARRAY) {
 	    index = (*cur_field)->c;
 	    if (type->ref->c >= 0 && index >= type->ref->c)
@@ -6677,12 +6684,12 @@ static int decl_designator(CType *type, Section *sec, unsigned long c,
     }
     /* must put zero in holes (note that doing it that way
        ensures that it even works with designators) */
-    if (!size_only && c - corig > al)
+    if (!(flags & DIF_SIZE_ONLY) && c - corig > al)
 	init_putz(sec, corig + al, c - corig - al);
-    decl_initializer(type, sec, c, 0, size_only);
+    decl_initializer(type, sec, c, flags & ~DIF_FIRST);
 
     /* XXX: make it more general */
-    if (!size_only && nb_elems > 1) {
+    if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) {
         unsigned long c_end;
         uint8_t *src, *dst;
         int i;
@@ -6905,33 +6912,29 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
 
 /* 't' contains the type and storage info. 'c' is the offset of the
    object in section 'sec'. If 'sec' is NULL, it means stack based
-   allocation. 'first' is true if array '{' must be read (multi
-   dimension implicit array init handling). 'size_only' is true if
+   allocation. 'flags & DIF_FIRST' is true if array '{' must be read (multi
+   dimension implicit array init handling). 'flags & DIF_SIZE_ONLY' is true if
    size only evaluation is wanted (only for arrays). */
 static void decl_initializer(CType *type, Section *sec, unsigned long c, 
-                             int first, int size_only)
+                             int flags)
 {
     int len, n, no_oblock, nb, i;
     int size1, align1;
-    int have_elem;
     Sym *s, *f;
     Sym indexsym;
     CType *t1;
 
-    /* If we currently are at an '}' or ',' we have read an initializer
-       element in one of our callers, and not yet consumed it.  */
-    have_elem = tok == '}' || tok == ',';
-    if (!have_elem && tok != '{' &&
+    if (!(flags & DIF_HAVE_ELEM) && tok != '{' &&
 	/* In case of strings we have special handling for arrays, so
 	   don't consume them as initializer value (which would commit them
 	   to some anonymous symbol).  */
 	tok != TOK_LSTR && tok != TOK_STR &&
-	!size_only) {
+	!(flags & DIF_SIZE_ONLY)) {
 	parse_init_elem(!sec ? EXPR_ANY : EXPR_CONST);
-	have_elem = 1;
+        flags |= DIF_HAVE_ELEM;
     }
 
-    if (have_elem &&
+    if ((flags & DIF_HAVE_ELEM) &&
 	!(type->t & VT_ARRAY) &&
 	/* Use i_c_parameter_t, to strip toplevel qualifiers.
 	   The source type might have VT_CONSTANT set, which is
@@ -6945,15 +6948,13 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
         size1 = type_size(t1, &align1);
 
         no_oblock = 1;
-        if ((first && tok != TOK_LSTR && tok != TOK_STR) || 
+        if (((flags & DIF_FIRST) && tok != TOK_LSTR && tok != TOK_STR) ||
             tok == '{') {
             if (tok != '{')
                 tcc_error("character array initializer must be a literal,"
                     " optionally enclosed in braces");
             skip('{');
             no_oblock = 0;
-	    if (tok == ',')
-		tcc_error("unexpected ','");
         }
 
         /* only parse strings here if correct type (otherwise: handle
@@ -6978,7 +6979,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
                 nb = cstr_len;
                 if (n >= 0 && nb > (n - len))
                     nb = n - len;
-                if (!size_only) {
+                if (!(flags & DIF_SIZE_ONLY)) {
                     if (cstr_len > nb)
                         tcc_warning("initializer-string for array is too long");
                     /* in order to go faster for common case (char
@@ -7004,7 +7005,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
             /* only add trailing zero if enough storage (no
                warning in this case since it is standard) */
             if (n < 0 || len < n) {
-                if (!size_only) {
+                if (!(flags & DIF_SIZE_ONLY)) {
 		    vpushi(0);
                     init_putv(t1, sec, c + (len * size1));
                 }
@@ -7017,9 +7018,9 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
 
           do_init_list:
 	    len = 0;
-	    while (tok != '}' || have_elem) {
-		len = decl_designator(type, sec, c, &f, size_only, len);
-		have_elem = 0;
+	    while (tok != '}' || (flags & DIF_HAVE_ELEM)) {
+		len = decl_designator(type, sec, c, &f, flags, len);
+		flags &= ~DIF_HAVE_ELEM;
 		if (type->t & VT_ARRAY) {
 		    ++indexsym.c;
 		    /* special test for multi dimensional arrays (may not
@@ -7042,7 +7043,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
 	    }
         }
         /* put zeros at the end */
-	if (!size_only && len < n*size1)
+	if (!(flags & DIF_SIZE_ONLY) && len < n*size1)
 	    init_putz(sec, c + len, n*size1 - len);
         if (!no_oblock)
             skip('}');
@@ -7052,7 +7053,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
     } else if ((type->t & VT_BTYPE) == VT_STRUCT) {
 	size1 = 1;
         no_oblock = 1;
-        if (first || tok == '{') {
+        if ((flags & DIF_FIRST) || tok == '{') {
             skip('{');
             no_oblock = 0;
         }
@@ -7061,20 +7062,22 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
         n = s->c;
 	goto do_init_list;
     } else if (tok == '{') {
+        if (flags & DIF_HAVE_ELEM)
+          skip(';');
         next();
-        decl_initializer(type, sec, c, first, size_only);
+        decl_initializer(type, sec, c, flags & ~DIF_HAVE_ELEM);
         skip('}');
-    } else if (size_only) {
+    } else if ((flags & DIF_SIZE_ONLY)) {
 	/* If we supported only ISO C we wouldn't have to accept calling
-	   this on anything than an array size_only==1 (and even then
+	   this on anything than an array if DIF_SIZE_ONLY (and even then
 	   only on the outermost level, so no recursion would be needed),
 	   because initializing a flex array member isn't supported.
 	   But GNU C supports it, so we need to recurse even into
-	   subfields of structs and arrays when size_only is set.  */
+	   subfields of structs and arrays when DIF_SIZE_ONLY is set.  */
         /* just skip expression */
         skip_or_save_block(NULL);
     } else {
-	if (!have_elem) {
+	if (!(flags & DIF_HAVE_ELEM)) {
 	    /* This should happen only when we haven't parsed
 	       the init element above for fear of committing a
 	       string constant to memory too early.  */
@@ -7154,7 +7157,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
         /* compute size */
         begin_macro(init_str, 1);
         next();
-        decl_initializer(type, NULL, 0, 1, 1);
+        decl_initializer(type, NULL, 0, DIF_FIRST | DIF_SIZE_ONLY);
         /* prepare second initializer parsing */
         macro_ptr = init_str->str;
         next();
@@ -7321,7 +7324,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
 	size_t oldreloc_offset = 0;
 	if (sec && sec->reloc)
 	  oldreloc_offset = sec->reloc->data_offset;
-        decl_initializer(type, sec, addr, 1, 0);
+        decl_initializer(type, sec, addr, DIF_FIRST);
 	if (sec && sec->reloc)
 	  squeeze_multi_relocs(sec, oldreloc_offset);
         /* patch flexible array member size back to -1, */
diff --git a/tests/tests2/60_errors_and_warnings.c b/tests/tests2/60_errors_and_warnings.c
index fa891af5..97f48bc7 100644
--- a/tests/tests2/60_errors_and_warnings.c
+++ b/tests/tests2/60_errors_and_warnings.c
@@ -140,5 +140,15 @@ int bar (const char *(*g)()) // should match this 'g' argument
 int foo(int ())              // abstract decl is wrong in definitions
 {
   return 0;
+#elif defined test_invalid_1
+void f(char*);
+void g(void) {
+  f((char[]){1, ,});
 }
+#elif defined test_invalid_2
+int ga = 0.42 { 2 };
+#elif defined test_invalid_3
+struct S { int a, b; };
+struct T { struct S x; };
+struct T gt = { 42 a: 1, 43 };
 #endif
diff --git a/tests/tests2/60_errors_and_warnings.expect b/tests/tests2/60_errors_and_warnings.expect
index 8fa6e998..fd4a70e5 100644
--- a/tests/tests2/60_errors_and_warnings.expect
+++ b/tests/tests2/60_errors_and_warnings.expect
@@ -62,3 +62,12 @@
 
 [test_abstract_decls]
 60_errors_and_warnings.c:141: error: identifier expected
+
+[test_invalid_1]
+60_errors_and_warnings.c:146: error: identifier expected
+
+[test_invalid_2]
+60_errors_and_warnings.c:149: error: ';' expected (got "{")
+
+[test_invalid_3]
+60_errors_and_warnings.c:153: error: ',' expected (got "a")