Browse Source

Fix double calling of lhs of logical binary expressions

gingerBill 5 years ago
parent
commit
01dfb1dac8
3 changed files with 33 additions and 19 deletions
  1. 6 2
      src/check_expr.cpp
  2. 19 10
      src/check_type.cpp
  3. 8 7
      src/ir.cpp

+ 6 - 2
src/check_expr.cpp

@@ -62,7 +62,7 @@ Type *   make_optional_ok_type          (Type *value);
 void     check_type_decl                (CheckerContext *c, Entity *e, Ast *type_expr, Type *def);
 void     check_type_decl                (CheckerContext *c, Entity *e, Ast *type_expr, Type *def);
 Entity * check_selector                 (CheckerContext *c, Operand *operand, Ast *node, Type *type_hint);
 Entity * check_selector                 (CheckerContext *c, Operand *operand, Ast *node, Type *type_hint);
 Entity * check_ident                    (CheckerContext *c, Operand *o, Ast *n, Type *named_type, Type *type_hint, bool allow_import_name);
 Entity * check_ident                    (CheckerContext *c, Operand *o, Ast *n, Type *named_type, Type *type_hint, bool allow_import_name);
-Entity * find_polymorphic_record_entity (CheckerContext *c, Type *original_type, isize param_count, Array<Operand> ordered_operands);
+Entity * find_polymorphic_record_entity (CheckerContext *c, Type *original_type, isize param_count, Array<Operand> const &ordered_operands, bool *failure);
 void     check_not_tuple                (CheckerContext *c, Operand *operand);
 void     check_not_tuple                (CheckerContext *c, Operand *operand);
 void     convert_to_typed               (CheckerContext *c, Operand *operand, Type *target_type);
 void     convert_to_typed               (CheckerContext *c, Operand *operand, Type *target_type);
 gbString expr_to_string                 (Ast *expression);
 gbString expr_to_string                 (Ast *expression);
@@ -6336,12 +6336,16 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
 	{
 	{
 		gbAllocator a = c->allocator;
 		gbAllocator a = c->allocator;
 
 
-		Entity *found_entity = find_polymorphic_record_entity(c, original_type, param_count, ordered_operands);
+		bool failure = false;
+		Entity *found_entity = find_polymorphic_record_entity(c, original_type, param_count, ordered_operands, &failure);
 		if (found_entity) {
 		if (found_entity) {
 			operand->mode = Addressing_Type;
 			operand->mode = Addressing_Type;
 			operand->type = found_entity->type;
 			operand->type = found_entity->type;
 			return err;
 			return err;
 		}
 		}
+		if (failure) {
+			return CallArgumentError_NoneConstantParameter;
+		}
 
 
 		String generated_name = make_string_c(expr_to_string(call));
 		String generated_name = make_string_c(expr_to_string(call));
 
 

+ 19 - 10
src/check_type.cpp

@@ -248,38 +248,47 @@ bool check_custom_align(CheckerContext *ctx, Ast *node, i64 *align_) {
 }
 }
 
 
 
 
-Entity *find_polymorphic_record_entity(CheckerContext *ctx, Type *original_type, isize param_count, Array<Operand> ordered_operands) {
+Entity *find_polymorphic_record_entity(CheckerContext *ctx, Type *original_type, isize param_count, Array<Operand> const &ordered_operands, bool *failure) {
 	auto *found_gen_types = map_get(&ctx->checker->info.gen_types, hash_pointer(original_type));
 	auto *found_gen_types = map_get(&ctx->checker->info.gen_types, hash_pointer(original_type));
 	if (found_gen_types != nullptr) {
 	if (found_gen_types != nullptr) {
 		for_array(i, *found_gen_types) {
 		for_array(i, *found_gen_types) {
 			Entity *e = (*found_gen_types)[i];
 			Entity *e = (*found_gen_types)[i];
 			Type *t = base_type(e->type);
 			Type *t = base_type(e->type);
 			TypeTuple *tuple = get_record_polymorphic_params(t);
 			TypeTuple *tuple = get_record_polymorphic_params(t);
-			bool ok = true;
 			GB_ASSERT(param_count == tuple->variables.count);
 			GB_ASSERT(param_count == tuple->variables.count);
+
+			bool skip = false;
+
 			for (isize j = 0; j < param_count; j++) {
 			for (isize j = 0; j < param_count; j++) {
 				Entity *p = tuple->variables[j];
 				Entity *p = tuple->variables[j];
 				Operand o = ordered_operands[j];
 				Operand o = ordered_operands[j];
 				if (p->kind == Entity_TypeName) {
 				if (p->kind == Entity_TypeName) {
 					if (is_type_polymorphic(o.type)) {
 					if (is_type_polymorphic(o.type)) {
 						// NOTE(bill): Do not add polymorphic version to the gen_types
 						// NOTE(bill): Do not add polymorphic version to the gen_types
-						ok = false;
-					}
-					if (!are_types_identical(o.type, p->type)) {
-						ok = false;
+						skip = true;
+						break;
+					} else if (!are_types_identical(o.type, p->type)) {
+						skip = true;
+						break;
 					}
 					}
 				} else if (p->kind == Entity_Constant) {
 				} else if (p->kind == Entity_Constant) {
-					if (!are_types_identical(o.type, p->type)) {
-						ok = false;
+					if (o.mode != Addressing_Constant) {
+						if (failure) *failure = true;
+						skip = true;
+						break;
 					}
 					}
 					if (!compare_exact_values(Token_CmpEq, o.value, p->Constant.value)) {
 					if (!compare_exact_values(Token_CmpEq, o.value, p->Constant.value)) {
-						ok = false;
+						skip = true;
+						break;
+					} else if (!are_types_identical(o.type, p->type)) {
+						skip = true;
+						break;
 					}
 					}
 				} else {
 				} else {
 					GB_PANIC("Unknown entity kind");
 					GB_PANIC("Unknown entity kind");
 				}
 				}
 			}
 			}
-			if (ok) {
+			if (!skip) {
 				return e;
 				return e;
 			}
 			}
 		}
 		}

+ 8 - 7
src/ir.cpp

@@ -5647,7 +5647,8 @@ irValue *ir_emit_logical_binary_expr(irProcedure *proc, TokenKind op, Ast *left,
 	}
 	}
 
 
 	ir_start_block(proc, rhs);
 	ir_start_block(proc, rhs);
-	array_add(&edges, ir_build_expr(proc, right));
+	irValue *edge = ir_build_expr(proc, right);
+	array_add(&edges, edge);
 	ir_emit_jump(proc, done);
 	ir_emit_jump(proc, done);
 	ir_start_block(proc, done);
 	ir_start_block(proc, done);
 
 
@@ -5656,8 +5657,6 @@ irValue *ir_emit_logical_binary_expr(irProcedure *proc, TokenKind op, Ast *left,
 
 
 irValue *ir_emit_logical_binary_expr(irProcedure *proc, Ast *expr) {
 irValue *ir_emit_logical_binary_expr(irProcedure *proc, Ast *expr) {
 	ast_node(be, BinaryExpr, expr);
 	ast_node(be, BinaryExpr, expr);
-	irBlock *rhs  = ir_new_block(proc, nullptr, "logical.cmp.rhs");
-	irBlock *done = ir_new_block(proc, nullptr, "logical.cmp.done");
 
 
 	Type *type = type_of_expr(expr);
 	Type *type = type_of_expr(expr);
 	type = default_type(type);
 	type = default_type(type);
@@ -6879,9 +6878,6 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 	case_end;
 	case_end;
 
 
 	case_ast_node(be, BinaryExpr, expr);
 	case_ast_node(be, BinaryExpr, expr);
-		irValue *left = ir_build_expr(proc, be->left);
-		Type *type = default_type(tv.type);
-
 		switch (be->op.kind) {
 		switch (be->op.kind) {
 		case Token_Add:
 		case Token_Add:
 		case Token_Sub:
 		case Token_Sub:
@@ -6895,6 +6891,8 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 		case Token_AndNot:
 		case Token_AndNot:
 		case Token_Shl:
 		case Token_Shl:
 		case Token_Shr: {
 		case Token_Shr: {
+			irValue *left = ir_build_expr(proc, be->left);
+			Type *type = default_type(tv.type);
 			irValue *right = ir_build_expr(proc, be->right);
 			irValue *right = ir_build_expr(proc, be->right);
 			return ir_emit_arith(proc, be->op.kind, left, right, type);
 			return ir_emit_arith(proc, be->op.kind, left, right, type);
 		}
 		}
@@ -6906,10 +6904,11 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 		case Token_LtEq:
 		case Token_LtEq:
 		case Token_Gt:
 		case Token_Gt:
 		case Token_GtEq: {
 		case Token_GtEq: {
+			irValue *left = ir_build_expr(proc, be->left);
+			Type *type = default_type(tv.type);
 			irValue *right = ir_build_expr(proc, be->right);
 			irValue *right = ir_build_expr(proc, be->right);
 			irValue *cmp = ir_emit_comp(proc, be->op.kind, left, right);
 			irValue *cmp = ir_emit_comp(proc, be->op.kind, left, right);
 			return ir_emit_conv(proc, cmp, type);
 			return ir_emit_conv(proc, cmp, type);
-			break;
 		}
 		}
 
 
 		case Token_CmpAnd:
 		case Token_CmpAnd:
@@ -6919,6 +6918,8 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 
 
 		case Token_in:
 		case Token_in:
 		case Token_notin: {
 		case Token_notin: {
+			irValue *left = ir_build_expr(proc, be->left);
+			Type *type = default_type(tv.type);
 			irValue *right = ir_build_expr(proc, be->right);
 			irValue *right = ir_build_expr(proc, be->right);
 			Type *rt = base_type(ir_type(right));
 			Type *rt = base_type(ir_type(right));
 			switch (rt->kind) {
 			switch (rt->kind) {