aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-10-24 12:51:44 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-10-24 12:51:44 -0200
commit6819c2a98adebaea1a8d1b065364f3b3748072aa (patch)
tree21ba2505f848d54b55544ada131c315e41c5e686 /lparser.c
parent1dd8af67b6b1f1c970967b96b2f1b2edabe551c4 (diff)
downloadlua-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.c37
1 files changed, 20 insertions, 17 deletions
diff --git a/lparser.c b/lparser.c
index 26b397ca..5370145b 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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*/
1114static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { 1114static 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}