pike.git/
src/
las.cmod
Branch:
Tag:
Non-build tags
All tags
No tags
2020-07-07
2020-07-07 11:39:37 by Henrik Grubbström (Grubba) <grubba@grubba.org>
57abdbc847dce987e562c05c7075bb23aad9cfd0 (
150
lines) (+
150
/-
0
)
[
Show
|
Annotate
]
Branch:
master
Compiler: Added type checking for operator-assignment.
Fixes most of bug
#10033
.
3675:
} break;
+
case F_AND_EQ:
+
case F_OR_EQ:
+
case F_XOR_EQ:
+
case F_LSH_EQ:
+
case F_RSH_EQ:
+
case F_ADD_EQ:
+
case F_SUB_EQ:
+
case F_MULT_EQ:
+
case F_POW_EQ:
+
case F_MOD_EQ:
+
case F_DIV_EQ:
+
/* <lval> <op>= <rval> */
+
{
+
const char *efun_name = NULL;
+
struct pike_string *efun_string = NULL;
+
int orig_flags;
+
node *efun_node = NULL;
+
struct pike_type *f;
+
enum Pike_opcodes opcode = n->token;
+
INT32 args = 0;
+
+
switch(opcode) {
+
case F_AND_EQ:
+
efun_name = "`&";
+
break;
+
case F_OR_EQ:
+
efun_name = "`|";
+
break;
+
case F_XOR_EQ:
+
efun_name = "`^";
+
break;
+
case F_LSH_EQ:
+
efun_name = "`<<";
+
break;
+
case F_RSH_EQ:
+
efun_name = "`>>";
+
break;
+
case F_ADD_EQ:
+
efun_name = "`+";
+
break;
+
case F_SUB_EQ:
+
efun_name = "`-";
+
break;
+
case F_MULT_EQ:
+
efun_name = "`*";
+
break;
+
case F_POW_EQ:
+
efun_name = "`**";
+
break;
+
case F_MOD_EQ:
+
efun_name = "`%";
+
break;
+
case F_DIV_EQ:
+
efun_name = "`/";
+
break;
+
default: /* Keep compiler warnings away. */
+
break;
+
}
+
+
if (efun_name) {
+
efun_string = findstring(efun_name);
+
}
+
+
SET_FORCE_RESOLVE(orig_flags);
+
+
if (!efun_string ||
+
!(efun_node = find_module_identifier(efun_string, 0))) {
+
UNSET_FORCE_RESOLVE(orig_flags);
+
my_yyerror("Efun implementing opcode %s undefined.",
+
low_get_f_name(n->token, NULL));
+
copy_pike_type(n->type, mixed_type_string);
+
break;
+
}
+
+
UNSET_FORCE_RESOLVE(orig_flags);
+
+
fix_type_field(efun_node); /* Just in case. */
+
+
/* NOTE: new_check_call() steals a reference from f! */
+
copy_pike_type(f, efun_node->type);
+
+
free_node(efun_node);
+
+
/* NOTE: Temporarily convert the node into an argument list node
+
* for new_check_call(),
+
*/
+
n->token = F_ARG_LIST;
+
f = debug_malloc_pass(new_check_call(efun_string, f, n, &args, 0));
+
n->token = opcode;
+
if (f) {
+
struct pike_type *ret = new_get_return_type(f, 0);
+
free_type(f);
+
f = ret;
+
}
+
+
if (f) {
+
/* Check that the returned type is compatible with the
+
* variable type.
+
*/
+
if (!pike_types_le(f, CAR(n)->type)) {
+
/* a["b"]+=c and a->b+=c can be valid when a is an array.
+
*
+
* FIXME: Exactly what case is the problem?
+
* /grubba 2005-02-15
+
*
+
* Example:
+
* array tmp = ({([]),([])});
+
* tmp->foo += 7; // Multi-assign.
+
* /grubba 2007-04-27
+
*/
+
if (((CAR(n)->token != F_INDEX && CAR(n)->token != F_ARROW) ||
+
!(match_types(array_type_string, CAAR(n)->type))) &&
+
!match_types(CAR(n)->type, f)) {
+
yytype_report(REPORT_ERROR, NULL, 0, CAR(n)->type,
+
NULL, 0, f,
+
0, "Bad type in assignment.");
+
} else {
+
if (c->lex.pragmas & ID_STRICT_TYPES) {
+
struct pike_string *t1 = describe_type(f);
+
struct pike_string *t2 = describe_type(CAR(n)->type);
+
#ifdef PIKE_DEBUG
+
if (l_flag > 0) {
+
fputs("Warning: Invalid assignment: ", stderr);
+
print_tree(n);
+
}
+
#endif /* PIKE_DEBUG */
+
yywarning("An expression of type %S cannot be assigned to "
+
"a variable of type %S.", t1, t2);
+
free_string(t2);
+
free_string(t1);
+
}
+
#if 0
+
if (runtime_options & RUNTIME_CHECK_TYPES) {
+
/* The following is NOT correct code! */
+
_CDR(n) = mksoftcastnode(CAR(n)->type,
+
mkcastnode(mixed_type_string, CDR(n)));
+
}
+
#endif /* 0 */
+
}
+
}
+
n->type = and_pike_types(f, CAR(n)->type);
+
+
free_type(f);
+
} else {
+
copy_pike_type(n->type, mixed_type_string);
+
}
+
}
+
break;
+
case F_ARRAY_LVALUE: { node *lval_list;