shithub: scc

Download patch

ref: 5707eb558192a44df20f3da9dea2f81c14453572
parent: 1c925d70a8145ed26506926dc92c1afa4c92fb11
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sat Aug 8 18:51:34 EDT 2015

Accept declaration of external variables with incomplete type

This variables can be declared because the storage is not needed
for them (only a symbol is emited).

--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -140,11 +140,8 @@
 		dp = declarator0(dp, ns);
 		expect(')');
 	} else {
-		/* TODO: check type of the function */
-		/* TODO: check function is not redefined */
 		if (yytoken == IDEN || yytoken == TYPEIDEN) {
-			if ((sym = install(ns, yylval.sym)) == NULL)
-				error("redeclaration of '%s'", yytext);
+			sym = yylval.sym;
 			next();
 		} else {
 			sym = newsym(ns);
@@ -180,11 +177,12 @@
 }
 
 static Symbol *
-declarator(Type *tp, unsigned ns)
+declarator(Type *tp, unsigned ns, int sclass)
 {
 	struct dcldata data[NR_DECLARATORS+1];
 	struct dcldata *bp;
-	Symbol *sym, **pars = NULL;
+	Symbol *osym, *sym, **pars = NULL;
+	char *name;
 
 	data[0].ndcl = 0;
 	for (bp = declarator0(data, ns); bp-- > data; ) {
@@ -201,12 +199,25 @@
 		}
 	}
 
-	sym->u.pars = pars;
+	if ((name = sym->name) == NULL) {
+		sym->type = tp;
+	} else {
+		short flags;
 
-	/* TODO: deal with external array declarations of []  */
-	if (!tp->defined && sym->name)
-		error("declared variable '%s' of incomplete type", sym->name);
-	sym->type = tp;
+		if ((sym = install(ns, osym = sym)) == NULL) {
+			if (!eqtype(osym->type, tp))
+				error("conflicting types for '%s'", name);
+			sym = osym;
+		} else {
+			sym->u.pars = pars;
+			sym->type = tp;
+		}
+		if (!tp->defined && sclass != EXTERN) {
+			error("declared variable '%s' of incomplete type",
+			      name);
+		}
+	}
+
 	return sym;
 }
 
@@ -509,7 +520,7 @@
 	}
 
 	do {
-		sym = declarator(base, ns);
+		sym = declarator(base, ns, sclass);
 		tp = sym->type;
 
 		switch (sclass) {