~lbnz/xr0

1e5138a23284630cea649a7f7ffd28c1b0c161da — Xr0 Team 2 months ago b841240 fix/nested-branching
partial fix
M include/util.h => include/util.h +12 -0
@@ 112,6 112,18 @@ error_to_undecideable_cond(struct error *);
struct ast_expr *
error_get_undecideable_cond(struct error *);

struct error *
error_pushframe();

bool
error_ispushframe(struct error *);

struct error *
error_popframe();

bool
error_ispopframe(struct error *);

char *
error_str(struct error *);


M src/ast/gram.y => src/ast/gram.y +3 -2
@@ 781,8 781,9 @@ jump_statement
	/*: GOTO IDENTIFIER ';'*/
	/*| CONTINUE ';'*/
	/*| BREAK ';'*/
	/*| RETURN ';'*/
	: RETURN expression ';'
	: RETURN ';'
		{ $$ = ast_stmt_create_jump(lexloc(), JUMP_RETURN, NULL); }
	| RETURN expression ';'
		{ $$ = ast_stmt_create_jump(lexloc(), JUMP_RETURN, $2); }
	;


M src/ast/stmt/stmt.c => src/ast/stmt/stmt.c +20 -10
@@ 189,6 189,15 @@ ast_stmt_create_jump(struct lexememarker *loc, enum ast_jump_kind kind,
struct ast_expr *
ast_stmt_jump_rv(struct ast_stmt *stmt)
{
	assert(stmt->kind == STMT_JUMP);
	assert(stmt->u.jump.rv);
	return stmt->u.jump.rv;
}

bool
ast_stmt_jump_hasrv(struct ast_stmt *stmt)
{
	assert(stmt->kind == STMT_JUMP);
	return stmt->u.jump.rv;
}



@@ 426,15 435,13 @@ static void
ast_stmt_jump_sprint(struct ast_stmt *stmt, struct strbuilder *b)
{
	assert(stmt->kind == STMT_JUMP);
	char *rv = ast_expr_str(stmt->u.jump.rv);

	strbuilder_printf(
		b,
		"return %s;\n",
		rv
	);

	free(rv);
	strbuilder_printf(b, "return");
	if (stmt->u.jump.rv) {
		char *rv = ast_expr_str(stmt->u.jump.rv);
		strbuilder_printf(b, "%s", rv);
		free(rv);
	}
	strbuilder_printf(b, ";");
}

static struct ast_expr *


@@ 651,7 658,10 @@ ast_stmt_getfuncs(struct ast_stmt *stmt)
	case STMT_ITERATION_E:
		return ast_stmt_iteration_getfuncs(stmt);
	case STMT_JUMP:
		return ast_expr_getfuncs(stmt->u.jump.rv);
		if (stmt->u.jump.rv) {
			return ast_expr_getfuncs(stmt->u.jump.rv);
		}
		return string_arr_create();
	default:
		assert(false);
	}

M src/ast/stmt/stmt.h => src/ast/stmt/stmt.h +3 -0
@@ 39,4 39,7 @@ sel_decide(struct ast_expr *control, struct state *state);
struct error *
ast_stmt_precondsinit(struct ast_stmt *, struct state *);

bool
ast_stmt_jump_hasrv(struct ast_stmt *stmt);

#endif

M src/ast/stmt/verify.c => src/ast/stmt/verify.c +1 -1
@@ 317,6 317,7 @@ ast_stmt_absprocess(struct ast_stmt *stmt, char *fname, struct state *state,
	assert(loc);
	char *m = lexememarker_str(loc);
	struct error *e = error_printf("%s:%s: %w", m, fname, err);
	free(m);
	return e;
}



@@ 436,7 437,6 @@ sel_decide(struct ast_expr *control, struct state *state)

	if (!values_comparable(zero, v)) {
		return (struct decision) {
			.decision = false,
			.err      = error_undecideable_cond(value_to_expr(v))
		};
	}

M src/props/props.c => src/props/props.c +3 -3
@@ 78,9 78,9 @@ bool
props_get(struct props *p, struct ast_expr *e)
{
	/* XXX: hack for shallow not conditions, fix in TODO */
	if (ast_expr_isnot(e)) {
		return !props_contradicts(p, e);
	}
	/*if (ast_expr_isnot(e)) {*/
		/*return !props_contradicts(p, e);*/
	/*}*/
	for (int i = 0; i < p->n; i++) {
		/* TODO: logical comparison */
		if (ast_expr_equal(e, p->prop[i])) {

M src/util/util.c => src/util/util.c +35 -1
@@ 296,6 296,8 @@ struct error {
	enum error_type {
		ERROR_PRINTF,
		ERROR_UNDECIDEABLE_COND,
		ERROR_PUSHFRAME,
		ERROR_POPFRAME,
	} type;
	union error_contents {
		char *printf;


@@ 388,6 390,34 @@ findnextfmt(char **p)
}

struct error *
error_pushframe()
{
	struct error *err = calloc(1, sizeof(struct error));
	err->type = ERROR_PUSHFRAME;
	return err;
}

bool
error_ispushframe(struct error *err)
{
	return error_to(err, ERROR_PUSHFRAME);
}

struct error *
error_popframe()
{
	struct error *err = calloc(1, sizeof(struct error));
	err->type = ERROR_POPFRAME;
	return err;
}

bool
error_ispopframe(struct error *err)
{
	return error_to(err, ERROR_POPFRAME);
}

struct error *
error_undecideable_cond(struct ast_expr *cond)
{
	assert(cond);


@@ 415,13 445,17 @@ char *
error_str(struct error *err)
{
	char *error_type_str[] = {
		[ERROR_UNDECIDEABLE_COND] = "undecideable condition"
		[ERROR_UNDECIDEABLE_COND]	= "undecideable condition",
		[ERROR_PUSHFRAME]		= "pushed frame",
		[ERROR_POPFRAME]		= "popped frame",
	};

	switch (err->type) {
	case ERROR_PRINTF:
		return dynamic_str(err->contents.printf);
	case ERROR_UNDECIDEABLE_COND:
	case ERROR_PUSHFRAME:
	case ERROR_POPFRAME:
		return dynamic_str(error_type_str[err->type]);
	default:
		assert(false);

A tests/1-branches/1100-FAIL-branch-double-free.x => tests/1-branches/1100-FAIL-branch-double-free.x +14 -0
@@ 0,0 1,14 @@
#include <stdlib.h>

void
foo(int a, int b)
{
	int *p;
	p = malloc(1);
	if (a) {
		free(p);
	}
	if (b) {
		free(p);
	}
}

A tests/1-branches/1100-FAIL-branch-double-free.x.EXPECTED => tests/1-branches/1100-FAIL-branch-double-free.x.EXPECTED +2 -0
@@ 0,0 1,2 @@
1-branches/1100-FAIL-branch-double-free.x:14:1:foo | $0 | $1: 
	stdlib.h:10:31:free: double free

A tests/1-branches/1200-nested-branch.x => tests/1-branches/1200-nested-branch.x +21 -0
@@ 0,0 1,21 @@
#include <stdlib.h>

void
foo(int a, int b)
{
	int *p;
	p = malloc(1);
	if (a) {
		if (!b) {
			free(p);
		}
	}
	if (b) {
		free(p);
	}
	if (!a) {
		if (!b) {
			free(p);
		}
	}
}

A tests/1-branches/1300-nested-branch-return.x => tests/1-branches/1300-nested-branch-return.x +22 -0
@@ 0,0 1,22 @@
#include <stdlib.h>

void
foo(int a, int b)
{
	int *p;
	p = malloc(1);
	if (a) {
		free(p);
		if (b) {
			return;
		}
	}
	if (b) {
		free(p);
	}
	if (!a) {
		if (!b) {
			free(p);
		}
	}
}