scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit 5be6d06570908e1574813c3f9b0f0f6d8a7cc34b
parent 1c759c3cd3d169a1c58fd40b3b95d5766747accf
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 24 Apr 2014 16:21:17 +0200

Fix stmt() when expression statements

The 'goto repeat' have to be followed only in label cases,
because in other case it is impossible to have a expression
which begins with IDEN.

Diffstat:
Mcode.c | 3++-
Mexpr.c | 3+--
Mstmt.c | 16++++++++++++----
3 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/code.c b/code.c @@ -169,7 +169,8 @@ emitsizeof(Node *np) void emitexp(Node *np) { - (*np->code)(np); + if (np) + (*np->code)(np); putchar('\n'); } diff --git a/expr.c b/expr.c @@ -56,7 +56,7 @@ typeconv(Node **p1, Node **p2) *p2 = np2; } -static Node * +Node * eval(Node *np) { if (!ISNODECMP(np)) @@ -436,7 +436,6 @@ primary(void) next(); np = expr(); expect(')'); - case ';': break; default: error("unexpected '%s'", yytext); diff --git a/stmt.c b/stmt.c @@ -8,7 +8,7 @@ Symbol *curfun; extern Node *convert(Node *np, Type *tp1, char iscast); -extern Node * iszero(Node *np); +extern Node *iszero(Node *np), *eval(Node *np); static void stmt(Symbol *lbreak, Symbol *lcont, Symbol *lswitch); static Symbol * @@ -131,9 +131,13 @@ Return(void) Type *tp = curfun->type->type; expect(RETURN); - np = expr(); + np = (yytoken == ';') ? NULL : eval(expr()); expect(';'); - if (np->type != tp) { + if (!np) { + if (tp != voidtype) + warn(1, "function returning non void returns no value"); + tp = voidtype; + } else if (np->type != tp) { if (tp == voidtype) warn(1, "function returning void returns a value"); else if ((np = convert(np, tp, 0)) == NULL) @@ -216,7 +220,11 @@ repeat: case BREAK: Break(lbreak); break; case CONTINUE: Continue(lcont); break; case GOTO: Goto(); break; - case IDEN: if (ahead() == ':') Label(); goto repeat; + case IDEN: + if (ahead() == ':') { + Label(); + goto repeat; + } default: stmtexp(); break; } }