summaryrefslogtreecommitdiff
path: root/parse
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-02-20 23:09:17 -0800
committerOri Bernstein <ori@eigenstate.org>2015-02-20 23:09:17 -0800
commit01414e72c048b8d3512568603281f0c190ecf571 (patch)
tree8c009eddf3d298b457721fc33e988ad58bcca676 /parse
parentbbaf863b646bd1e964514321650d34498435b767 (diff)
downloadmc-01414e72c048b8d3512568603281f0c190ecf571.tar.gz
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.
Diffstat (limited to 'parse')
-rw-r--r--parse/gram.y1
-rw-r--r--parse/infer.c7
2 files changed, 8 insertions, 0 deletions
diff --git a/parse/gram.y b/parse/gram.y
index 9d7111f..63f87c6 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -464,6 +464,7 @@ compoundtype
: 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);}
diff --git a/parse/infer.c b/parse/infer.c
index fb0d0c2..458b283 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -19,6 +19,7 @@ struct Inferstate {
int ingeneric;
int sawret;
int indentdepth;
+ int intype;
Type *ret;
/* bound by patterns turn into decls in the action block */
@@ -362,8 +363,10 @@ static void tyresolve(Inferstate *st, Type *t)
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 @@ static void tyresolve(Inferstate *st, Type *t)
}
}
} 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 @@ static Type *tyfix(Inferstate *st, Node *ctx, Type *orig)
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)