aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'bootstrap/parse.c')
-rw-r--r--bootstrap/parse.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index 7b2e007..99560d8 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -539,20 +539,22 @@ popenv(struct parser *P) {
static struct decl *
putdecl(struct parser *P, struct span espan, const struct decl *decl) {
struct decl *ret;
- if (envfind(P->primenv, decl->name))
+ if (envfind(P->primenv, INT_MAX, decl->name))
fatal(P, espan, "cannot shadow primitive `%s'", decl->name);
if (!(ret = envput(P->curenv, decl)))
fatal(P, decl->span,
"cannot shadow earlier incompatible declaration of `%s'", decl->name);
+ if (!P->save_envage)
+ P->envage = MAX(P->envage, ret->age);
return ret;
}
static const struct decl *
finddecl(struct parser *P, const char *name) {
const struct decl *decl;
- if ((decl = envfind(P->primenv, name)))
+ if ((decl = envfind(P->primenv, INT_MAX, name)))
return decl;
- return envfind(P->curenv, name);
+ return envfind(P->curenv, P->envage, name);
}
static struct expr parseexpr(struct parser *P);
@@ -684,6 +686,7 @@ parseexpandtepl(struct parser *P, struct tepl *tepl) {
}
struct env env = { tepl->env };
+
WITH_TMPCHANGE(struct env *, P->curenv, &env) {
struct decl *decl;
expan.args.d = args;
@@ -691,8 +694,11 @@ parseexpandtepl(struct parser *P, struct tepl *tepl) {
expan.toks = tepl->toks;
++P->expanno;
P->curexpan = memcpy(xmalloc(sizeof expan), &expan, sizeof expan);
- ty = parseagg(P, tepl->name, tepl->tkind, &decl);
+ WITH_TMPCHANGE(int, P->envage, tepl->envage)
+ WITH_TMPCHANGE(int, P->save_envage, 1)
+ ty = parseagg(P, tepl->name, tepl->tkind, &decl);
}
+ free(env.decls);
memcpy(&((struct type *)ty)->agg.tpargs, &tpargs, sizeof tpargs);
cache = xcalloc(sizeof *cache, 1);
cache->next = tepl->cache;
@@ -2443,7 +2449,7 @@ parseagg(struct parser *P, const char *name, int kind, struct decl **retdecl) {
int iid;
struct env env_noparent = *P->curenv;
env_noparent.parent = NULL;
- struct decl *decl = (struct decl *)envfind(&env_noparent, name);
+ struct decl *decl = (struct decl *)envfind(&env_noparent, P->envage, name);
if (decl && decl->ty->t == kind)
iid = decl->ty->agg.id;
else
@@ -2586,6 +2592,7 @@ parseaggtepl(struct parser *P, int kind, const char *name) {
}
tepl.env = P->curenv;
+ tepl.envage = P->envage;
vec_slice_cpy(&tepl.params, &params);
vec_slice_cpy(&tepl.toks, &toks);
return tepl;
@@ -2705,6 +2712,8 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) {
decl.t = Dtype;
decl.ty = parseagg(P, decl.name, kind, &decl2);
} else {
+ if (!toplevel)
+ fatal(P, tok.span, "template definition inside function");
decl.t = Dtepl;
decl.tepl = parseaggtepl(P, kind, decl.name);
}