diff options
Diffstat (limited to 'src/parse.cff')
| -rw-r--r-- | src/parse.cff | 95 |
1 files changed, 52 insertions, 43 deletions
diff --git a/src/parse.cff b/src/parse.cff index 3be70cf..aad88d1 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -584,9 +584,9 @@ fn lexexpects(P *Parser, t TokT, what *const u8) Tok { let tok = Tok {}; if !lexmatch(P, &tok, t) { if what { - fatal(P, tok.loc, "expected %s (near %qT)", what, tok); + fatal(P, tok.loc, "expected %s (near %qT)", what, &tok); } else { - fatal(P, tok.loc, "expected %qk (near %qT)", t, tok); + fatal(P, tok.loc, "expected %qk (near %qT)", t, &tok); } } return tok; @@ -626,7 +626,7 @@ fn putdecl(P *Parser, eloc Loc, decl Decl) *Decl { let d0 *const Decl; let d = envput(P.curenv, decl, &d0); if d == #null { - fatal(P, eloc, "attempt to redefine `%s' (previously defined at %l)", decl.name, d0.loc); + fatal(P, eloc, "attempt to redefine `%s' (previously defined at %l)", decl.name, &d0.loc); } return d; } @@ -638,7 +638,7 @@ fn putdecl_alloc(P *Parser, alloc *Allocator, eloc Loc, decl Decl) *Decl { let d0 *const Decl; let d = envput_alloc(P.curenv, alloc, decl, &d0); if d == #null { - fatal(P, eloc, "attempt to redefine `%s' (previously defined at %l)", decl.name, d0.loc); + fatal(P, eloc, "attempt to redefine `%s' (previously defined at %l)", decl.name, &d0.loc); } return d; } @@ -1160,7 +1160,7 @@ fn parsetype(P *Parser) *const Type { return parsebitfield(P, #{name} #null); case else; - fatal(P, tok.loc, "expected type (near %qT)", tok); + fatal(P, tok.loc, "expected type (near %qT)", &tok); } } @@ -1185,7 +1185,7 @@ fn parseaggini(P *Parser, loc Loc, ty *const Type) Expr { fld = findaggfield(ty, (tok = lexexpects(P, :ident, "field name")).u.ident); lexexpect(P, ':'); if fld == #null { - fatal(P, tok.loc, "%t has no such field %qT", ty, tok); + fatal(P, tok.loc, "%t has no such field %qT", ty, &tok); } iota = (fld - ty.u.Agg.flds.#ptr) + 1; } else { @@ -1384,7 +1384,7 @@ fn pexprimary(P *Parser) Expr { fn resolvedecl(P *Parser, tok Tok, decl *Decl, ex *Expr) void { let fakedecl Decl #?; if decl == #null { - fatal(P, tok.loc, "%qT is not defined", tok); + fatal(P, tok.loc, "%qT is not defined", &tok); } while #t { switch decl.u { @@ -1409,7 +1409,7 @@ fn pexprimary(P *Parser) Expr { let name = (tok = lexexpect(P, :ident)).u.ident; decl = envfind_noparent(ty.u.Agg.decls, name); if decl == #null { - fatal(P, tok.loc, "%t has no such decl %qT", ty, tok); + fatal(P, tok.loc, "%t has no such decl %qT", ty, &tok); } continue; } else if !ty->is(:Agg) and !ty->is(:Enum) { @@ -1502,7 +1502,7 @@ fn pexprimary(P *Parser) Expr { let name = (tok = lexexpect(P, :ident)).u.ident; let fld = findaggfield(ty, name); if fld == #null { - fatal(P, tok.loc, "%t has no such field %qT", ty, tok); + fatal(P, tok.loc, "%t has no such field %qT", ty, &tok); } off += fld.off; ty = fld.ty; @@ -1545,27 +1545,27 @@ fn pexprimary(P *Parser) Expr { break #'search; } } - fatal(P, tok.loc, "%t has no such variant %qT", ty, tok); + fatal(P, tok.loc, "%t has no such variant %qT", ty, &tok); } while #f; ex = { tok.loc, ty, :EnumIni(i) }; } else if ty->is(:Agg) and ty.u.Agg.kind == :EUnion { let name = (tok = lexexpects(P, :ident, "variant name")).u.ident; let fld = findaggfield(ty, name); if fld == #null { - fatal(P, tok.loc, "%t has no such variant %qT", ty, tok); + fatal(P, tok.loc, "%t has no such variant %qT", ty, &tok); } let iex *Expr = #null; if lexpeek(P).t == '(' or lexpeek(P).t == '{' { P.targty = fld.ty; iex = exprdup(P.alloc, parseexpr(P)); if fld.ty == #null { - fatal(P, iex.loc, "%t variant %qT is empty", ty, tok); + fatal(P, iex.loc, "%t variant %qT is empty", ty, &tok); } if !typematchestarg(fld.ty, iex.ty) { fatal(P, iex.loc, "bad enum union initializer (%t, expected %t)", iex.ty, fld.ty); } } else if fld.ty { - fatal(P, tok.loc, "%t variant %qT must be initialized", ty, tok); + fatal(P, tok.loc, "%t variant %qT must be initialized", ty, &tok); } ex = { tok.loc, ty, :EUnionIni { fld, iex }}; } else { @@ -1590,7 +1590,7 @@ fn pexprimary(P *Parser) Expr { } } case else; - fatal(P, tok.loc, "expected expression (near %qT)", tok); + fatal(P, tok.loc, "expected expression (near %qT)", &tok); } P.targty = #null; return ex; @@ -1614,10 +1614,13 @@ fn pexpostfix(P *Parser) Expr { while !lexmatch(P, #null, ')') { P.targty = args.len + 1 <= params.#len ? *param : #null; let ex = parseexpr(P); - args->push(ex); if args.len > params.#len and !Fn.variadic { fatal(P, ex.loc, "too many args (%z, expected %z)", args.len, params.#len); } + if args.len >= params.#len and (ex.ty->is(:Agg) or ex.ty->is(:Slice) or ex.ty->is(:VaList)) { + err(P, ex.loc, "cannot pass aggregate value as variadic argument"); + } + args->push(ex); if args.len <= params.#len and !typematchestarg(*param, ex.ty) { err(P, ex.loc, "function call argument type mismatch (%t, expected %t)", ex.ty, *param); @@ -1663,13 +1666,13 @@ fn pexpostfix(P *Parser) Expr { } case lexmatch(P, &tok, '++') or lexmatch(P, &tok, '--'); if !isnumtype(ex.ty) and !ex.ty->is(:Ptr) { - fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty); + fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty); } if !islvalue(&ex) { - err(P, ex.loc, "left operand to prefix %qT operator is not lvalue", tok); + err(P, ex.loc, "left operand to prefix %qT operator is not lvalue", &tok); } if ex.ty.konst { - err(P, ex.loc, "left operand to prefix %qT operator is const", tok); + err(P, ex.loc, "left operand to prefix %qT operator is const", &tok); } ex = { tok.loc, ex.ty, .u: :UnOp { @@ -1694,8 +1697,8 @@ fn pexpostfix(P *Parser) Expr { break; } } - if fld == #null { fatal(P, tok.loc, "%t has no such field %qT", ty, tok); } - if fld.ty == #null { fatal(P, tok.loc, "field %qT has no type", tok); } + if fld == #null { fatal(P, tok.loc, "%t has no such field %qT", ty, &tok); } + if fld.ty == #null { fatal(P, tok.loc, "field %qT has no type", &tok); } ex = { tok.loc, konst ? constify(fld.ty) : fld.ty, :Dot { exprdup(P.alloc, ex), fld }}; case BitF *bitf; let fld *BitFField = #null; @@ -1705,7 +1708,7 @@ fn pexpostfix(P *Parser) Expr { break; } } - if fld == #null { fatal(P, tok.loc, "%t has no such field %qT", ty, tok); } + if fld == #null { fatal(P, tok.loc, "%t has no such field %qT", ty, &tok); } ex = { tok.loc, konst ? constify(fld.ty) : fld.ty, :BitDot { exprdup(P.alloc, ex), fld }}; case else fatal(P, tok.loc, "left-hand-side is not an aggregate (%t)", ty); @@ -1774,7 +1777,7 @@ fn pexpostfix(P *Parser) Expr { case Agg *agg; let decl *Decl = agg.decls ? envfind_noparent(agg.decls, name) : #null; if decl == #null { - fatal(P, tok.loc, "%t has no such method %qT", ty, tok); + fatal(P, tok.loc, "%t has no such method %qT", ty, &tok); } lexexpect(P, '('); switch decl.u { @@ -1859,6 +1862,9 @@ fn pexpostfix(P *Parser) Expr { let type = parsetype(P); lexmatch(P, #null, ','); lexexpect(P, ')'); + if type->is(:Agg) { + err(P, tok.loc, "unsupported use of variadic arg of aggregate type"); + } ex = { tok.loc, type, :VaArg(exprdup(P.alloc, ex)) }; case streq(name, "end"); @@ -1889,10 +1895,10 @@ fn pexprefix(P *Parser) Expr { let ex = pexprefix(P); let ty = typeof2(ex.ty, ty_int); if ty == #null { - fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty); + fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty); } if !ty->is(:Int) and tok.t == '~' { - fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty); + fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty); } return { tok.loc, ty, .u: :UnOp { @@ -1902,13 +1908,13 @@ fn pexprefix(P *Parser) Expr { case lexmatch(P, &tok, '++') or lexmatch(P, &tok, '--'); let ex = pexprefix(P); if !isnumtype(ex.ty) and !ex.ty->is(:Ptr) { - fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty); + fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty); } if !islvalue(&ex) { - err(P, ex.loc, "left operand to prefix %qT operator is not lvalue", tok); + err(P, ex.loc, "left operand to prefix %qT operator is not lvalue", &tok); } if ex.ty.konst { - err(P, ex.loc, "left operand to prefix %qT operator is const", tok); + err(P, ex.loc, "left operand to prefix %qT operator is const", &tok); } return { tok.loc, ex.ty, .u: :UnOp { @@ -1918,7 +1924,7 @@ fn pexprefix(P *Parser) Expr { case lexmatch(P, &tok, '!'); let ex = pexprefix(P); if !ex.ty->is(:Bool) { - err(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty); + err(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty); } return { tok.loc, ty_bool, .u: :UnOp { :not, exprdup(P.alloc, ex) }}; @@ -2043,13 +2049,13 @@ fn pexcmp(P *Parser) Expr { P.targty = #null; if typeof2(ex.ty, rhs.ty) == #null { fatal(P, tok.loc, "incompatible operands %t and %t to binary operator %qT", - ex.ty, rhs.ty, tok); + ex.ty, rhs.ty, &tok); } let ty = typeof2(ex.ty, rhs.ty); if tok.t != '==' and tok.t != '!=' { if !isnumtype(ty) and !ty->is(:Ptr) { fatal(P, tok.loc, "invalid non-numeric operands %t and %t to relational operator %qT", - ex.ty, rhs.ty, tok); + ex.ty, rhs.ty, &tok); } fn ispositiveintlit(ex Expr) bool { return ex.u.#tag == :IntLit and ex.u.IntLit.i >- 0; @@ -2167,14 +2173,14 @@ fn pexassign(P *Parser) Expr { and !((ex.ty->is(:Ptr) and rhs.ty->is(:Int) and (tok.t == '+=' or tok.t == '-='))); err(P, tok.loc, "invalid operands %t and %t for assignment operator %qT", - ex.ty, rhs.ty, tok); + ex.ty, rhs.ty, &tok); case okind == :IntFlo and (!isnumtype(ex.ty) or !isnumtype(rhs.ty)); err(P, tok.loc, "invalid operands %t and %t for assignment operator %qT", - ex.ty, rhs.ty, tok); + ex.ty, rhs.ty, &tok); case okind == :Int and (!ex.ty->is(:Int) or !rhs.ty->is(:Int)); err(P, tok.loc, "invalid operands %t and %t for assignment operator %qT", - ex.ty, rhs.ty, tok); + ex.ty, rhs.ty, &tok); case ex.ty.konst; err(P, ex.loc, "left operand to assignment is const"); } @@ -2380,7 +2386,7 @@ fn pstiswitch(P *Parser, loc Loc, ex Expr) Stmt { err(P, e.loc, "bad case expression (%t, expected %t)", e.ty, ex.ty); } if seen->get(e.u.IntLit.i) { - err(P, e.loc, "duplicate case expression (previously seen at %l)", *seen->get(e.u.IntLit.i)); + err(P, e.loc, "duplicate case expression (previously seen at %l)", seen->get(e.u.IntLit.i)); } seen->put(e.u.IntLit.i, e.loc); es->push(e); @@ -2421,12 +2427,12 @@ fn psteuswitch(P *Parser, loc Loc, test Expr) Stmt { let vname = (tok = lexexpect(P, :ident)).u.ident; c.fld = findaggfield(test.ty, vname); if c.fld == #null { - fatal(P, tok.loc, "%t has no such variant %qT", test.ty, tok); + fatal(P, tok.loc, "%t has no such variant %qT", test.ty, &tok); } c.variant = c.fld - test.ty.u.Agg.flds.#ptr; if seen->get(c.variant) { - err(P, tok.loc, "duplicate case expression (previously seen at %l)", *seen->get(c.variant)); + err(P, tok.loc, "duplicate case expression (previously seen at %l)", seen->get(c.variant)); } seen->put(c.variant, tok.loc); @@ -2558,7 +2564,7 @@ fn parsestmts(P *Parser, yield StmtYielder, yarg *void) void { if lexmatch(P, &tok2, :label) { let decl = finddecl(P, tok2.u.ident); if decl == #null { - fatal(P, tok2.loc, "no such label %qT", tok2); + fatal(P, tok2.loc, "no such label %qT", &tok2); } assert(decl.u.#tag == :Label, "label?"); loop = decl.u.Label; @@ -2700,7 +2706,7 @@ fn parsevardecl(P *Parser, toplevel bool, externp bool, letp bool, yield DeclYie } let decll *Decl #?; yield(decll = putdecl(P, tok.loc, decl), yarg); - if !letp and !fwd { + if !letp and !fwd and !P.error { llvm_genstatic(decl.externp, decl.name, &decl.u.Static); } @@ -2765,7 +2771,9 @@ fn parsefn(P *Parser, loc Loc, toplevel bool, externp bool, name *const u8) *Dec P.curblock = block; popenv(P); // ir_genfn(P.irctx, Fn); - llvm_genfn(externp, name, Fn); + if !P.error { + llvm_genfn(externp, name, Fn); + } (as(*Arena)P.alloc.a)->destroy(); } } @@ -2994,7 +3002,7 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool) if streq(a, "lax") { attr |= ATTR_LAX; } else { - err(P, tok.loc, "unknown attribute %qT", tok); + err(P, tok.loc, "unknown attribute %qT", &tok); } } } @@ -3145,7 +3153,7 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool) return parsedecls(P, tok.loc, yield, yarg, toplevel); } } - fatal(P, tok.loc, "expected declaration (near %qT)", tok); + fatal(P, tok.loc, "expected declaration (near %qT)", &tok); } if yield != #null and decl != #null { @@ -3176,7 +3184,6 @@ extern fn parse(P *Parser) [#]Decl { let alloc = Allocator { &aralloc, &Arena:allocf, #null }; let decls Vec<Decl> = {}; P.alloc = (P.tlalloc = &alloc); - P.irctx = mkirctx(P.alloc); P.curenv = mkenv(#null, P.alloc); if primenv == #null { primenv = mkenv(#null, P.alloc); @@ -3194,7 +3201,9 @@ extern fn parse(P *Parser) [#]Decl { } } - llvm_fini(); + if !P.error { + llvm_fini(); + } envfree(P.curenv); aralloc->destroy(); return decls.dat[0::decls.len]; |