shithub: mc

Download patch

ref: 1a00720e1fc60ce82d95763a031efac9b71340ce
parent: e7a0f4791ce20c45129b536d01d1ec977d696521
author: Ori Bernstein <ori@eigenstate.org>
date: Fri Feb 20 18:09:17 EST 2015

Allow unlengthed arrays within structs.

    Added type[...] syntax to tell the compiler not to check the length
    of these arrays. The size of this array is 0, as far as the compiler
    is concerned. This is only allowed within structs.

    This allows us to do 2 things:
        - First, it allows us to handle the C idiom which
          puts a zero-length array at the end of a struct
          to store extra data, as follows:
            type trailing = struct
                length : byte
                data : byte[...]
            ;;

        - And, as a side effect, we can also fake out C style unions as
          follows:

            type withunion = struct
                a : foo[...]
                b : foo[...]
                c : foo[...]
                pad : byte[NBYTES]
            ;;

          This is ugly and error prone, and perhaps should be
          deprecated.

--- a/6/simp.c
+++ b/6/simp.c
@@ -725,6 +725,8 @@
     Node *cmp, *die;
     Node *ok, *fail;
 
+    if (!len)
+        return;
     /* create expressions */
     cmp = mkexpr(idx->loc, Olt, ptrsized(s, idx), ptrsized(s, len), NULL);
     cmp->expr.type = mktype(len->loc, Tybool);
--- a/libstd/sys+linux-x64.myr
+++ b/libstd/sys+linux-x64.myr
@@ -79,7 +79,7 @@
 		off	: uint64
 		reclen	: uint16
 		etype	: byte
-		name	: byte[0]
+		name	: byte[...]	/* special case; zero length => unchecked indexing */
 	;;
 
 	type utsname = struct
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -464,6 +464,7 @@
         : functype   {$$ = $1;}
         | type Tosqbrac Tcolon Tcsqbrac {$$ = mktyslice($2->loc, $1);}
         | type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->loc, $1, $3);}
+        | type Tosqbrac Tellipsis Tcsqbrac {$$ = mktyarray($2->loc, $1, NULL);}
         | type Tderef {$$ = mktyptr($2->loc, $1);}
         | Tat Tident {$$ = mktyparam($1->loc, $2->id);}
         | name       {$$ = mktyunres($1->loc, $1, NULL, 0);}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -19,6 +19,7 @@
     int ingeneric;
     int sawret;
     int indentdepth;
+    int intype;
     Type *ret;
 
     /* bound by patterns turn into decls in the action block */
@@ -362,8 +363,10 @@
     t->resolved = 1;
     /* Walk through aggregate type members */
     if (t->type == Tystruct) {
+        st->intype++;
         for (i = 0; i < t->nmemb; i++)
             infernode(st, &t->sdecls[i], NULL, NULL);
+        st->intype--;
     } else if (t->type == Tyunion) {
         for (i = 0; i < t->nmemb; i++) {
             t->udecls[i]->utype = t;
@@ -374,6 +377,8 @@
             }
         }
     } else if (t->type == Tyarray) {
+        if (!st->intype && !t->asize)
+            lfatal(t->loc, "unsized array type outside of struct");
         infernode(st, &t->asize, NULL, NULL);
     }
 
@@ -1641,8 +1646,10 @@
         if (t->type == Tyarray) {
             typesub(st, t->asize);
         } else if (t->type == Tystruct) {
+            st->intype++;
             for (i = 0; i < t->nmemb; i++)
                 typesub(st, t->sdecls[i]);
+            st->intype--;
         } else if (t->type == Tyunion) {
             for (i = 0; i < t->nmemb; i++) {
                 if (t->udecls[i]->etype)