shithub: scc

Download patch

ref: f73cc2f511c03315a6a4dfe6b8450b57b4fd1b49
parent: c3b98d1587e0da7811403997cabbaa5a425b1d7a
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri Feb 14 10:24:29 EST 2014

Move check of tag already defined out of aggregate

aggregate function is going to be called each time an aggregate declaration
begins, in normal declaration and in forward declarations, but the check
of 'tag already defined' must be done only in the case of normal
declaration. The place where we know if the declaration is normal or
forward is in structdcl after the aggregate() call, so the check is
moved there.

--- a/decl.c
+++ b/decl.c
@@ -65,10 +65,12 @@
 	}
 }
 
-static void
+/* TODO: Add the type to the symbol */
+static struct symbol *
 aggregate(register struct ctype *tp)
 {
 	struct symbol *sym = NULL;
+	tp->forward = 1;
 
 	if (yytoken == IDEN) {
 		register struct ctype *aux;
@@ -75,18 +77,25 @@
 
 		sym = lookup(yytext, NS_TAG);
 		if (aux = sym->ctype) {
-			if (!aux->forward)
-				error("struct/union already defined");
-			delctype(aux);
-		}
-		sym->ctype = xmalloc(sizeof(*tp));
-		next();
+			if (aux->type != tp->type) {
+				error("'%s' defined as wrong kind of tag",
+				      yytext);
+			}
+			*tp = *aux;
+		} else {
+			sym->ctype = xmalloc(sizeof(*tp));
+			tp->sym = sym;
+			tp->ns = ++nr_tags; /* FIX: It is only necessary */
+		}                           /*      in struct and union  */
+		next();                     /* This way of handling nr_tag */
+	} else {                            /* is incorrect once is incorrect*/
+		tp->ns = ++nr_tags;         /* it will be incorrect forever*/
 	}
+
 	if (nr_tags == NS_TAG + NR_MAXSTRUCTS)
 		error("too much structs/unions/enum defined");
-	tp->ns = ++nr_tags;
-	tp->forward = 1;
-	tp->sym = sym;
+
+	return sym;
 }
 
 static bool
@@ -135,12 +144,16 @@
 {
 	struct symbol *sym;
 
-	aggregate(tp);
-	if (nested_tags == NR_STRUCT_LEVEL)
-		error("too much nested structs/unions");
+	sym = aggregate(tp);
 
 	if (!accept('{'))
 		return;
+
+	if (sym && !sym->ctype->forward)
+		error("struct/union already defined");
+
+	if (nested_tags == NR_STRUCT_LEVEL)
+		error("too much nested structs/unions");
 
 	++nested_tags;
 	do
--