Rationalize type compatibility checks to fix a potential problem where new dtype...
authorNick Downing <downing.nick@gmail.com>
Wed, 15 Feb 2017 13:36:39 +0000 (00:36 +1100)
committerNick Downing <downing.nick@gmail.com>
Wed, 15 Feb 2017 13:37:28 +0000 (00:37 +1100)
c01.c
c03.c

diff --git a/c01.c b/c01.c
index d82d82e..f940721 100644 (file)
--- a/c01.c
+++ b/c01.c
@@ -155,6 +155,7 @@ void build(op) int op; {
 
        case AMPER:
                if (p1->n_op==NAME || p1->n_op==STAR) {
+ /*fprintf(stderr, "amper %p type %x strp %p\n", p1, p1->n_type, p1->n_strp);*/
                        *cp++ = (struct node *)block(op,incref0(p1->n_type),p1->n_subsp,p1->n_strp,p1,(struct node *)NULL);
                        return;
                }
@@ -392,6 +393,7 @@ void structident(p1, p2) register struct node *p1; register struct nnode *p2; {
        register struct nmlist *np, *nporig;
        int vartypes = 0, namesame = 1;
 
+ /*fprintf(stderr, "structident %p op %d type %x strp %p field %s\n", p1, p1->n_op, p1->n_type, p1->n_strp, p2->nn_nmlist->nl_name);*/
        np = nporig = p2->nn_nmlist;
        for (;;) {
                if (namesame && p1->n_type==STRUCT+PTR && p1->n_strp == np->nl_sparent) {
@@ -683,6 +685,7 @@ struct nnode *nblock(ds) register struct nmlist *ds; {
                locp->locnn_nloc = ds->nl_offset;
 #undef locp
        }
+ /*fprintf(stderr, "nblock %p name %s type %x strp %p\n", p, ds->nl_name, ds->nl_type, ds->nl_strp);*/
        p->nn_op = NAME;
        p->nn_type = ds->nl_type;
        p->nn_subsp = ds->nl_subsp;
diff --git a/c03.c b/c03.c
index 4828cf9..7b8c4f1 100644 (file)
--- a/c03.c
+++ b/c03.c
@@ -280,6 +280,7 @@ int declist(sclass) int sclass; {
                if ((o = symbol()) != RBRACE)
                        goto syntax;
        }
+ /*fprintf(stderr, "stype=%p,%p\n", stype, &stype->st_S);*/
        return(/*strp*/stype);
    syntax:
        decsyn(o);
@@ -394,15 +395,6 @@ static int oldtype(dtype, dimp, strp) struct type *dtype; struct tdim *dimp; str
  /*fprintf(stderr, ")", type);*/
  return type;
 }
-static int eqtype(struct type *t0, struct type *t1) {
- while (t0->t_id == t1->t_id) {
-  if ((t0->t_id & TYPE) != REF)
-   return 1;
-  t0 = ((struct rtype *)t0)->rt_reftype;
-  t1 = ((struct rtype *)t1)->rt_reftype;
- }
- return 0;
-}
 int decl1(askw, atptr, offset, absname) int askw; struct /*nmlist*/type *atptr; int offset; struct nmlist *absname; {
        int t1, a, elsize;
        register int skw;
@@ -460,7 +452,7 @@ int decl1(askw, atptr, offset, absname) int askw; struct /*nmlist*/type *atptr;
                t1 >>= TYLEN;
        }
        type |= tptr->nl_type&TYPE;*/
-       if (/*(type&XTYPE) == FUNC*/dtype->t_id == (REF|FUNC)) {
+       if (/*(type&XTYPE) == FUNC*/dtype->t_id == (REF | FUNC)) {
                if (skw==AUTO)
                        skw = EXTERN;
                if ((skw!=EXTERN && skw!=TYPEDEF) && absname==NULL)
@@ -491,61 +483,95 @@ int decl1(askw, atptr, offset, absname) int askw; struct /*nmlist*/type *atptr;
                } else
                        defsym = dsym = pushdecl(dsym);
        }
+ /* old way */
  /*    if (dim.rank == 0)
                dsym->nl_subsp = NULL;
-       else {*/
-               /*
+       else {
+               *//*
                 * If an array is declared twice, make sure the declarations
                 * agree in dimension.  This happens typically when a .h
                 * and .c file both declare a variable.
-                */
-               if (dsym->/*nl_subsp*/nl_dtype) {
-                       for (/*a=0*/dt = dtype, /*t1 = dsym->nl_type*/dt1 = dsym->nl_dtype;
-                           /*a<dim.rank*/dt->t_id==(REF|ARRAY) && /*(t1&XTYPE)==ARRAY*/dt1->t_id==(REF|ARRAY);
-                           /*a++*/dt=((struct atype *)dt)->at_reftype, /*t1 >>= TYLEN*/dt1=((struct atype *)dt1)->at_reftype)
-#define adt ((struct atype *)dt)
-#define adt1 ((struct atype *)dt1)
-                               /*
+                *//*
+               if (dsym->nl_subsp) {
+                       for (a=0, t1 = dsym->nl_type;
+                           a<dim.rank && (t1&XTYPE)==ARRAY);
+                           a++, t1 >>= TYLEN)
+                               *//*
                                 * If we haven't seen a declaration for this
                                 * dimension yet, take what's been given now.
-                                */
-                               if (!/*dsym->nl_subsp[a]*/adt1->at_nelt)
-                                       /*dsym->nl_subsp[a]*/adt1->at_nelt = /*dim.dimens[a]*/adt->at_nelt;
-                               else if (/*dim.dimens[a]*/adt->at_nelt
-                                   && /*dim.dimens[a]*/adt->at_nelt != /*dsym->nl_subsp[a]*/adt1->at_nelt)
+                                *//*
+                               if (!dsym->nl_subsp[a])
+                                       dsym->nl_subsp[a] = dim.dimens[a];
+                               else if (dim.dimens[a]
+                                   && dim.dimens[a] != dsym->nl_subsp[a])
                                        redec();
-#undef adt
-#undef adt1
-                       if (/*a<dim.rank*/dt->t_id==(REF|ARRAY) || /*(t1&XTYPE)==ARRAY*/dt1->t_id==(REF|ARRAY))
+                       if (a<dim.rank || (t1&XTYPE)==ARRAY)
                                redec();
-               } /*else {
+               } else {
                        dp = (int *)Dblock(dim.rank*sizeof(dim.rank));
                        for (a=0; a<dim.rank; a++)
                                dp[a] = dim.dimens[a];
                        dsym->nl_subsp = dp;
                }
-       }*/
+       }
        if (!(dsym->nl_class==0
           || ((skw==ARG||skw==AREG) && dsym->nl_class==ARG1)
-          || (skw==EXTERN && dsym->nl_class==EXTERN && /*dsym->nl_type==type*/eqtype(dsym->nl_dtype, dtype)))) {
+          || (skw==EXTERN && dsym->nl_class==EXTERN && dsym->nl_type==type))) {
                redec();
                goto syntax;
        }
/*    if (dsym->nl_class && (dsym->nl_type&TYPE)==STRUCT && (type&TYPE)==STRUCT)
      if (dsym->nl_class && (dsym->nl_type&TYPE)==STRUCT && (type&TYPE)==STRUCT)
                if (dsym->nl_strp != *//*tptr->nl_strp*//*(union str *)&((struct stype *)tptr)->st_S) {
                        error0("structure redeclaration");
-               }*/
- if (dsym->nl_class) {
-  for (dt = dtype; (dt->t_id & TYPE) == REF; dt = ((struct rtype *)dt)->rt_reftype)
-   ;
-  for (dt1 = dsym->nl_dtype; (dt1->t_id & TYPE) == REF; dt1 = ((struct rtype *)dt1)->rt_reftype)
-   ;
-  if (dt->t_id == STRUCT && dt1->t_id == STRUCT && dt != dt1)
-   error0("structure redeclaration");
- }
- /*    dsym->nl_type = type;
+               }
+       dsym->nl_type = type;
        if (tptr->nl_strp)
                dsym->nl_strp = tptr->nl_strp;*/
+ /* new way */
+ if ((skw==ARG||skw==AREG) && dsym->nl_class==ARG1)
+  /* got type for previously declared K&R function argument */
+  /* just clobber the type, no type compatibility check needed */
+  dsym->nl_dtype = dtype;
+ else if (skw==EXTERN && dsym->nl_class==EXTERN) {
+  /* got redeclaration of previously declared extern symbol */
+  /* compare types, picking up any new dimension information */
+  for (
+   dt = dtype, dt1 = dsym->nl_dtype;
+   (t1 = dt->t_id) == dt1->t_id;
+   dt=((struct rtype *)dt)->rt_reftype, dt1=((struct rtype *)dt1)->rt_reftype
+  )
+   switch (t1 & TYPE) {
+   case REF | PTR:
+   case FUNC | PTR:
+    break;
+   case REF | ARRAY:
+#define adt ((struct atype *)dt)
+#define adt1 ((struct atype *)dt1)
+    if (!adt1->at_nelt)
+     adt1->at_nelt = adt->at_nelt;
+    else if (adt->at_nelt && adt->at_nelt != adt1->at_nelt)
+     redec();
+    break;
+#undef adt
+#undef adt1
+   case STRUCT:
+    if (dt != dt1)
+     error0("structure redeclaration");
+    /* fallthru */
+   default:
+    goto done;
+   }
+  redec();
+ done:
+  dtype = dsym->nl_dtype;
+ }
+ else if (dsym->nl_class) {
+  redec();
+  goto syntax;
+ }
+ else
+  dsym->nl_dtype = dtype;
+ /* XXX this is only for compatibility */
  dim.rank = 0;
  /*fprintf(stderr, "oldtype ");*/
  dsym->nl_type = oldtype(dtype, &dim, &dsym->nl_strp);
@@ -554,7 +580,7 @@ int decl1(askw, atptr, offset, absname) int askw; struct /*nmlist*/type *atptr;
   dsym->nl_subsp = (int *)Dblock(dim.rank*sizeof(dim.rank));
  for (a=0; a<dim.rank; a++)
   dsym->nl_subsp[a] = dim.dimens[a];
- dsym->nl_dtype = dtype;
+ /* XXX to here */
        if (skw==TYPEDEF) {
                dsym->nl_class = TYPEDEF;
                return(0);