[hackers] [scc] Fix namespace for previously declared nested struct identifier || Michael Forney

From: <git_AT_suckless.org>
Date: Tue, 14 Feb 2017 20:02:06 +0100 (CET)

commit a30f8e9edfde16e4d231503214333ff340f24b29
Author: Michael Forney <mforney_AT_mforney.org>
AuthorDate: Mon Feb 13 11:28:26 2017 -0800
Commit: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
CommitDate: Tue Feb 14 20:01:08 2017 +0100

    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.

diff --git a/cc1/decl.c b/cc1/decl.c
index 85bd150..f56a981 100644
--- a/cc1/decl.c
+++ b/cc1/decl.c
_AT_@ -467,11 +467,13 @@ static Symbol *
 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:
_AT_@ -479,7 +481,6 @@ newtag(void)
                 sym = yylval.sym;
                 if ((sym->flags & SDECLARED) == 0)
                         install(NS_TAG, yylval.sym);
- namespace = NS_IDEN;
                 next();
                 break;
         default:
_AT_@ -489,10 +490,10 @@ newtag(void)
         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",
_AT_@ -514,15 +515,14 @@ structdcl(void)
         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);
diff --git a/tests/execute/0109-struct.c b/tests/execute/0109-struct.c
new file mode 100644
index 0000000..3bc0296
--- /dev/null
+++ b/tests/execute/0109-struct.c
_AT_@ -0,0 +1,10 @@
+struct S1 { int x; };
+struct S2 { struct S1 s1; };
+
+int
+main()
+{
+ struct S2 s2;
+ s2.s1.x = 1;
+ return 0;
+}
diff --git a/tests/execute/scc-tests.lst b/tests/execute/scc-tests.lst
index 641ebf4..d13529c 100644
--- a/tests/execute/scc-tests.lst
+++ b/tests/execute/scc-tests.lst
_AT_@ -99,3 +99,4 @@
 0106-ppcast.c
 0107-bnot.c
 0108-bug.c
+0109-struct.c
Received on Tue Feb 14 2017 - 20:02:06 CET

This archive was generated by hypermail 2.3.0 : Tue Feb 14 2017 - 20:12:18 CET