Browse Source

Fix double evaluation bug with selector call expressions `x->y(z)`

gingerBill 4 years ago
parent
commit
dbdc4471c2
1 changed files with 27 additions and 4 deletions
  1. 27 4
      src/check_expr.cpp

+ 27 - 4
src/check_expr.cpp

@@ -4331,16 +4331,29 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
 		}
 		}
 		if (error_code != 0) {
 		if (error_code != 0) {
 			err = CallArgumentError_TooManyArguments;
 			err = CallArgumentError_TooManyArguments;
-			char const *err_fmt = "Too many arguments for '%s', expected %td arguments";
+			char const *err_fmt = "Too many arguments for '%s', expected %td arguments, got %td";
 			if (error_code < 0) {
 			if (error_code < 0) {
 				err = CallArgumentError_TooFewArguments;
 				err = CallArgumentError_TooFewArguments;
-				err_fmt = "Too few arguments for '%s', expected %td arguments";
+				err_fmt = "Too few arguments for '%s', expected %td arguments, got %td";
 			}
 			}
 
 
 			if (show_error) {
 			if (show_error) {
 				gbString proc_str = expr_to_string(ce->proc);
 				gbString proc_str = expr_to_string(ce->proc);
-				error(call, err_fmt, proc_str, param_count_excluding_defaults);
-				gb_string_free(proc_str);
+				defer (gb_string_free(proc_str));
+				error(call, err_fmt, proc_str, param_count_excluding_defaults, operands.count);
+
+				#if 0
+				error_line("\t");
+				for_array(i, operands) {
+					if (i > 0) {
+						error_line(", ");
+					}
+					gbString s = expr_to_string(operands[i].expr);
+					error_line("%s", s);
+					gb_string_free(s);
+				}
+				error_line("\n");
+				#endif
 			}
 			}
 		} else {
 		} else {
 			// NOTE(bill): Generate the procedure type for this generic instance
 			// NOTE(bill): Generate the procedure type for this generic instance
@@ -7564,6 +7577,16 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 		//
 		//
 		// NOTE(bill, 2020-05-22): I'm going to regret this decision, ain't I?
 		// NOTE(bill, 2020-05-22): I'm going to regret this decision, ain't I?
 
 
+
+		if (se->modified_call) {
+			// Prevent double evaluation
+			o->expr  = node;
+			o->type  = node->tav.type;
+			o->value = node->tav.value;
+			o->mode  = node->tav.mode;
+			return Expr_Expr;
+		}
+
 		bool allow_arrow_right_selector_expr;
 		bool allow_arrow_right_selector_expr;
 		allow_arrow_right_selector_expr = c->allow_arrow_right_selector_expr;
 		allow_arrow_right_selector_expr = c->allow_arrow_right_selector_expr;
 		c->allow_arrow_right_selector_expr = true;
 		c->allow_arrow_right_selector_expr = true;