ref: 135cd72730a8a7284d8408576177f397f241919e
parent: d6d544e9f02b6b2e97348fe6007009e16338b37f
author: Michael Forney <[email protected]>
date: Mon Feb 13 06:28:26 EST 2017
Fix namespace for previously declared nested struct identifier In structdcl, newtag is called which looks up the struct identifier in NS_TAG, then sets namespace to NS_IDEN and reads the next token. This is incorrect since if the struct was already declared, the next token is an identifier, which is looked up in the wrong namespace. This causes the following to be incorrectly rejected struct S1 { int x; }; struct S2 { struct S1 s1; }; struct S2 s2; s2.s1.x = 1; and this to be incorrectly accepted struct S1 { int x; }; struct S2 { struct S1 s1; }; s1.x = 1; To resolve this, make newtag preserve namespace. This also allows slight simplification of structdcl.
--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -467,11 +467,13 @@
newtag(void)
{
Symbol *sym;
- int op, tag = yylval.token;
- static unsigned ns = NS_STRUCTS;
+ int ns, op, tag = yylval.token;
+ static unsigned tpns = NS_STRUCTS;
+ ns = namespace;
namespace = NS_TAG;
next();
+ namespace = ns;
switch (yytoken) {
case IDEN:
@@ -479,7 +481,6 @@
sym = yylval.sym;
if ((sym->flags & SDECLARED) == 0)
install(NS_TAG, yylval.sym);
- namespace = NS_IDEN;
next();
break;
default:
@@ -489,10 +490,10 @@
if (!sym->type) {
Type *tp;
- if (ns == NS_STRUCTS + NR_MAXSTRUCTS)
+ if (tpns == NS_STRUCTS + NR_MAXSTRUCTS)
error("too many tags declared");
tp = mktype(NULL, tag, 0, NULL);
- tp->ns = ns++;
+ tp->ns = tpns++;
sym->type = tp;
tp->tag = sym;
DBG("declared tag '%s' with ns = %d\n",
@@ -514,15 +515,14 @@
static int nested;
int ns;
- ns = namespace;
sym = newtag();
tp = sym->type;
- namespace = tp->ns;
- if (!accept('{')) {
- namespace = ns;
+ if (!accept('{'))
return tp;
- }
+
+ ns = namespace;
+ namespace = tp->ns;
if (tp->prop & TDEFINED && sym->ctx == curctx)
error("redefinition of struct/union '%s'", sym->name);
--- /dev/null
+++ b/tests/execute/0109-struct.c
@@ -1,0 +1,10 @@
+struct S1 { int x; };
+struct S2 { struct S1 s1; };
+
+int
+main()
+{
+ struct S2 s2;
+ s2.s1.x = 1;
+ return 0;
+}
--- a/tests/execute/scc-tests.lst
+++ b/tests/execute/scc-tests.lst
@@ -99,3 +99,4 @@
0106-ppcast.c
0107-bnot.c
0108-bug.c
+0109-struct.c