shithub: scc

Download patch

ref: 1340a9b646844af4368ad3c3b275e53904019d83
parent: 6363b621d371ca732a5a63212199bd059cd507d0
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Mon Sep 23 18:00:58 EDT 2013

Add struct and unions declarators

These declarators are very diferents of the previous due to
they define a new namespace, so the thecniques used previously
cannot be applied here. We have to define a new namespace with
each new struct declared. We defined the first struct namespace
as NS_ANY+1, so we will not have any collision with the anothers
namespaces.

--- a/decl.c
+++ b/decl.c
@@ -11,6 +11,9 @@
 char parser_out_home;
 
 static struct symbol *cursym;
+static unsigned char nr_structs = NS_ANY + 1;
+static unsigned char structbuf[NR_STRUCT_LEVEL], *structp = &structbuf[0];
+
 static void declarator(struct ctype *tp, unsigned char ns);
 
 static struct symbol *
@@ -79,6 +82,9 @@
 	}
 }
 
+
+static struct ctype *struct_spec(register struct ctype *);
+
 struct ctype *
 spec(void)
 {
@@ -95,10 +101,13 @@
 		case FLOAT:    case DOUBLE: case BOOL:
 		case VOID:     case CHAR:   case SHORT:
 		case INT:      case ENUM:   case LONG:
-		case STRUCT:   case UNION:
 			tp = btype(tp, yytoken);
 			break;
-			/* TODO: ENUM, STRUCT, UNION */
+			/* TODO: ENUM */
+		case STRUCT:   case UNION:
+			tp = btype(tp, yytoken);
+			next();
+			return struct_spec(tp);
 		case IDEN:
 			if (!tp || !tp->type) {
 				struct symbol *sym;
@@ -138,6 +147,60 @@
 	}
 }
 
+static struct ctype *
+struct_dcl(unsigned char ns)
+{
+	register struct ctype *tp, *base;
+
+	if (!(base = spec())) {
+		base = newctype();
+		base->type = INT;
+		warning_error(options.implicit,
+		              "data definition has no type or storage class");
+	}
+	if (base->c_typedef  || base->c_static || base->c_auto ||
+	    base->c_register || base->c_extern) {
+		error("storage specifier in a struct/union field declaration");
+	}
+
+	do {                      /* TODO: detect unnamed structs */
+		declarator(base, ns);
+		tp = decl_type(base);
+		(cursym->ctype = tp)->refcnt++;
+	} while (accept(','));
+
+	expect(';');
+	return tp;
+}
+
+static struct ctype *
+struct_spec(register struct ctype *tp)
+{
+	if (yytoken == IDEN) {
+		(namespace(NS_STRUCT, -1)->ctype = tp)->refcnt++;
+		next();
+	}
+
+	if (nr_structs == NR_MAXSTRUCTS)
+		error("too much structs/unions defined");
+	if (structp == &structbuf[NR_STRUCT_LEVEL])
+		error("too much nested structs/unions");
+	tp->c_struct = *structp++ = nr_structs;
+
+	if (!accept('{'))
+		return tp;
+
+	if (!tp->forward)
+		error("struct/union already defined");
+
+	do
+		struct_dcl(tp->c_struct);
+	while (!accept('}'));
+	tp->forward = 0;
+
+	return tp;
+}
+
 static void
 declarator(struct ctype *tp, unsigned char ns)
 {
@@ -201,6 +264,9 @@
 		declarator(base, base->c_typedef ? NS_TYPEDEF : NS_IDEN);
 		tp = decl_type(base);
 		(cursym->ctype = tp)->refcnt++;
+		if ((tp->type == STRUCT || tp->type == UNION) && tp->forward)
+			error("declaration of variable with incomplete type");
+
 		sp = nodesym(cursym);
 		if (tp->type == FTN && yytoken == '{') {
 			np  = node2(ODEF, sp, function(cursym));
@@ -227,8 +293,18 @@
 		warning_error(options.implicit,
 		              "data definition has no type or storage class");
 	} else if (accept(';')) {
-		warning_error(options.useless,
-			      "useless type name in empty declaration");
+		register unsigned char type = tp->type;
+
+		if (type == STRUCT || type == UNION) {
+			if (tp->c_extern || tp->c_static || tp->c_auto ||
+			    tp->c_register || tp->c_const || tp->c_volatile) {
+				warning_error(options.useless,
+				              "useless storage class specifier in empty declaration");
+			}
+		} else {
+			warning_error(options.useless,
+			              "useless type name in empty declaration");
+		}
 		delctype(tp);
 		goto repeat;
 	}
--- a/sizes.h
+++ b/sizes.h
@@ -11,6 +11,10 @@
  */
 #define NR_COND   8
 /*
+ * number of defined structs/unions in one translation unit
+ */
+#define NR_MAXSTRUCTS 127
+/*
  * 12 pointer, array, and function declarators (in any combinations)
  *  modifying an arithmetic, a structure, a union, or an incomplete type
  *  in a declaration
--- a/symbol.h
+++ b/symbol.h
@@ -32,7 +32,11 @@
 	bool c_restrict : 1;
 	bool c_unsigned : 1;
 	bool c_signed : 1;
-	unsigned len;
+	bool forward : 1;
+	union {
+		unsigned len;
+		unsigned char c_struct;
+	};
 	struct ctype *base;
 	unsigned char refcnt;
 };
--- a/types.c
+++ b/types.c
@@ -17,7 +17,7 @@
 {
 	register struct ctype *tp = xcalloc(sizeof(*tp), 1);
 
-	tp->refcnt = 1;
+	tp->forward = tp->refcnt = 1;
 	return tp;
 }
 
--