diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-10-24 12:51:44 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-10-24 12:51:44 -0200 |
commit | 6819c2a98adebaea1a8d1b065364f3b3748072aa (patch) | |
tree | 21ba2505f848d54b55544ada131c315e41c5e686 /lparser.c | |
parent | 1dd8af67b6b1f1c970967b96b2f1b2edabe551c4 (diff) | |
download | lua-6819c2a98adebaea1a8d1b065364f3b3748072aa.tar.gz lua-6819c2a98adebaea1a8d1b065364f3b3748072aa.tar.bz2 lua-6819c2a98adebaea1a8d1b065364f3b3748072aa.zip |
silly bug in 5.2 beta: assignment conflict code did not test to check
whether variable was a table element
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 37 |
1 files changed, 20 insertions, 17 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.119 2011/09/14 17:40:26 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.120 2011/09/30 12:44:45 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -1106,31 +1106,34 @@ struct LHS_assign { | |||
1106 | 1106 | ||
1107 | 1107 | ||
1108 | /* | 1108 | /* |
1109 | ** check whether, in an assignment to a local variable, the local variable | 1109 | ** check whether, in an assignment to an upvalue/local variable, the |
1110 | ** is needed in a previous assignment (to a table). If so, save original | 1110 | ** upvalue/local variable is begin used in a previous assignment to a |
1111 | ** local value in a safe place and use this safe copy in the previous | 1111 | ** table. If so, save original upvalue/local value in a safe place and |
1112 | ** assignment. | 1112 | ** use this safe copy in the previous assignment. |
1113 | */ | 1113 | */ |
1114 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | 1114 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { |
1115 | FuncState *fs = ls->fs; | 1115 | FuncState *fs = ls->fs; |
1116 | int extra = fs->freereg; /* eventual position to save local variable */ | 1116 | int extra = fs->freereg; /* eventual position to save local variable */ |
1117 | int conflict = 0; | 1117 | int conflict = 0; |
1118 | for (; lh; lh = lh->prev) { | 1118 | for (; lh; lh = lh->prev) { /* check all previous assignments */ |
1119 | /* conflict in table 't'? */ | 1119 | if (lh->v.k == VINDEXED) { /* assigning to a table? */ |
1120 | if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { | 1120 | /* table is the upvalue/local being assigned now? */ |
1121 | conflict = 1; | 1121 | if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { |
1122 | lh->v.u.ind.vt = VLOCAL; | 1122 | conflict = 1; |
1123 | lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ | 1123 | lh->v.u.ind.vt = VLOCAL; |
1124 | } | 1124 | lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ |
1125 | /* conflict in index 'idx'? */ | 1125 | } |
1126 | if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { | 1126 | /* index is the local being assigned? (index cannot be upvalue) */ |
1127 | conflict = 1; | 1127 | if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { |
1128 | lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ | 1128 | conflict = 1; |
1129 | lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ | ||
1130 | } | ||
1129 | } | 1131 | } |
1130 | } | 1132 | } |
1131 | if (conflict) { | 1133 | if (conflict) { |
1134 | /* copy upvalue/local value to a temporary (in position 'extra') */ | ||
1132 | OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; | 1135 | OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; |
1133 | luaK_codeABC(fs, op, fs->freereg, v->u.info, 0); /* make copy */ | 1136 | luaK_codeABC(fs, op, extra, v->u.info, 0); |
1134 | luaK_reserveregs(fs, 1); | 1137 | luaK_reserveregs(fs, 1); |
1135 | } | 1138 | } |
1136 | } | 1139 | } |