comparison src/vim9instr.c @ 31920:f1a5e67e9a1b v9.0.1292

patch 9.0.1292: :defer may call the wrong method for an object Commit: https://github.com/vim/vim/commit/313e4724c3b4f6d7454b45b89da08f83a2a0c77e Author: Bram Moolenaar <Bram@vim.org> Date: Wed Feb 8 20:55:27 2023 +0000 patch 9.0.1292: :defer may call the wrong method for an object Problem: :defer may call the wrong method for an object. (Ernie Rael) Solution: When en object is from a class that extends or implements, figure out the method to call at runtime. (closes #11910)
author Bram Moolenaar <Bram@vim.org>
date Wed, 08 Feb 2023 22:00:06 +0100
parents b7a8611dd9fc
children e8c60d35fce3
comparison
equal deleted inserted replaced
31919:b1b8848f5bb3 31920:f1a5e67e9a1b
1326 return push_type_stack2(cctx, type, decl_type); 1326 return push_type_stack2(cctx, type, decl_type);
1327 } 1327 }
1328 1328
1329 /* 1329 /*
1330 * Generate an ISN_FUNCREF instruction. 1330 * Generate an ISN_FUNCREF instruction.
1331 * For "obj.Method" "cl" is the class of the object (can be an interface or a
1332 * base class) and "fi" the index of the method on that class.
1331 * "isnp" is set to the instruction, so that fr_dfunc_idx can be set later. 1333 * "isnp" is set to the instruction, so that fr_dfunc_idx can be set later.
1332 */ 1334 */
1333 int 1335 int
1334 generate_FUNCREF( 1336 generate_FUNCREF(
1335 cctx_T *cctx, 1337 cctx_T *cctx,
1336 ufunc_T *ufunc, 1338 ufunc_T *ufunc,
1339 class_T *cl,
1340 int fi,
1337 isn_T **isnp) 1341 isn_T **isnp)
1338 { 1342 {
1339 isn_T *isn; 1343 isn_T *isn;
1340 type_T *type; 1344 type_T *type;
1341 funcref_extra_T *extra; 1345 funcref_extra_T *extra;
1347 return FAIL; 1351 return FAIL;
1348 if (isnp != NULL) 1352 if (isnp != NULL)
1349 *isnp = isn; 1353 *isnp = isn;
1350 1354
1351 has_vars = get_loop_var_info(cctx, &loopinfo); 1355 has_vars = get_loop_var_info(cctx, &loopinfo);
1352 if (ufunc->uf_def_status == UF_NOT_COMPILED || has_vars) 1356 if (ufunc->uf_def_status == UF_NOT_COMPILED || has_vars || cl != NULL)
1353 { 1357 {
1354 extra = ALLOC_CLEAR_ONE(funcref_extra_T); 1358 extra = ALLOC_CLEAR_ONE(funcref_extra_T);
1355 if (extra == NULL) 1359 if (extra == NULL)
1356 return FAIL; 1360 return FAIL;
1357 isn->isn_arg.funcref.fr_extra = extra; 1361 isn->isn_arg.funcref.fr_extra = extra;
1358 extra->fre_loopvar_info = loopinfo; 1362 extra->fre_loopvar_info = loopinfo;
1359 } 1363 if (cl != NULL)
1360 if (ufunc->uf_def_status == UF_NOT_COMPILED) 1364 {
1365 extra->fre_class = cl;
1366 ++cl->class_refcount;
1367 extra->fre_method_idx = fi;
1368 }
1369 }
1370 if (ufunc->uf_def_status == UF_NOT_COMPILED || cl != NULL)
1361 extra->fre_func_name = vim_strsave(ufunc->uf_name); 1371 extra->fre_func_name = vim_strsave(ufunc->uf_name);
1362 else 1372 if (ufunc->uf_def_status != UF_NOT_COMPILED && cl == NULL)
1363 { 1373 {
1364 if (isnp == NULL && ufunc->uf_def_status == UF_TO_BE_COMPILED) 1374 if (isnp == NULL && ufunc->uf_def_status == UF_TO_BE_COMPILED)
1365 // compile the function now, we need the uf_dfunc_idx value 1375 // compile the function now, we need the uf_dfunc_idx value
1366 (void)compile_def_function(ufunc, FALSE, CT_NONE, NULL); 1376 (void)compile_def_function(ufunc, FALSE, CT_NONE, NULL);
1367 isn->isn_arg.funcref.fr_dfunc_idx = ufunc->uf_dfunc_idx; 1377 isn->isn_arg.funcref.fr_dfunc_idx = ufunc->uf_dfunc_idx;
2482 if (name != NULL) 2492 if (name != NULL)
2483 { 2493 {
2484 func_unref(name); 2494 func_unref(name);
2485 vim_free(name); 2495 vim_free(name);
2486 } 2496 }
2497 if (extra->fre_class != NULL)
2498 class_unref(extra->fre_class);
2487 vim_free(extra); 2499 vim_free(extra);
2488 } 2500 }
2489 } 2501 }
2490 break; 2502 break;
2491 2503