From: Anthony Baxter Date: Wed, 21 Nov 2001 06:21:18 +0000 (+0000) Subject: backport of jeremy's 2.227: X-Git-Tag: v2.1.2c1~72 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=55aa02bb43b9d4ccce62f673057a4d461e2248a6;p=thirdparty%2FPython%2Fcpython.git backport of jeremy's 2.227: Fix for SF bug [ #471928 ] global made w/nested list comprehensions . Initially I was going to just rip out the bits of this that fixed this bug, but the rest of the code looks (after a fair amount of staring at it) like it's ok - variable renames, that sort of thing. flames and "hey, no way!" to me, or to python-dev. It felt safer to just go with the full patch, rather than butchering it. --- diff --git a/Python/compile.c b/Python/compile.c index 7af843376d5c..088b76606946 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -4823,7 +4823,7 @@ symtable_add_def_o(struct symtable *st, PyObject *dict, static void symtable_node(struct symtable *st, node *n) { - int i, start = 0; + int i; loop: switch (TYPE(n)) { @@ -4929,36 +4929,62 @@ symtable_node(struct symtable *st, node *n) } } goto loop; - /* watchout for fall-through logic below */ + case list_iter: + n = CHILD(n, 0); + if (TYPE(n) == list_for) { + st->st_tmpname++; + symtable_list_comprehension(st, n); + st->st_tmpname--; + } else { + REQ(n, list_if); + symtable_node(st, CHILD(n, 1)); + if (NCH(n) == 3) { + n = CHILD(n, 2); + goto loop; + } + } + break; + case for_stmt: + symtable_assign(st, CHILD(n, 1), 0); + for (i = 3; i < NCH(n); ++i) + if (TYPE(CHILD(n, i)) >= single_input) + symtable_node(st, CHILD(n, i)); + break; + /* The remaining cases fall through to default except in + special circumstances. This requires the individual cases + to be coded with great care, even though they look like + rather innocuous. Each case must double-check TYPE(n). + */ case argument: - if (NCH(n) == 3) { + if (TYPE(n) == argument && NCH(n) == 3) { n = CHILD(n, 2); goto loop; } + /* fall through */ case listmaker: if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == list_for) { st->st_tmpname++; symtable_list_comprehension(st, CHILD(n, 1)); symtable_node(st, CHILD(n, 0)); st->st_tmpname--; - return; + break; } + /* fall through */ case atom: if (TYPE(n) == atom && TYPE(CHILD(n, 0)) == NAME) { symtable_add_use(st, STR(CHILD(n, 0))); break; } - case for_stmt: - if (TYPE(n) == for_stmt) { - symtable_assign(st, CHILD(n, 1), 0); - start = 3; - } + /* fall through */ default: + /* Walk over every non-token child with a special case + for one child. + */ if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } - for (i = start; i < NCH(n); ++i) + for (i = 0; i < NCH(n); ++i) if (TYPE(CHILD(n, i)) >= single_input) symtable_node(st, CHILD(n, i)); } @@ -5189,8 +5215,14 @@ symtable_import(struct symtable *st, node *n) } } +/* The third argument to symatble_assign() is a flag to be passed to + symtable_add_def() if it is eventually called. The flag is useful + to specify the particular type of assignment that should be + recorded, e.g. an assignment caused by import. + */ + static void -symtable_assign(struct symtable *st, node *n, int flag) +symtable_assign(struct symtable *st, node *n, int def_flag) { node *tmp; int i; @@ -5222,7 +5254,7 @@ symtable_assign(struct symtable *st, node *n, int flag) return; } else { for (i = 0; i < NCH(n); i += 2) - symtable_assign(st, CHILD(n, i), flag); + symtable_assign(st, CHILD(n, i), def_flag); } return; case exprlist: @@ -5234,7 +5266,7 @@ symtable_assign(struct symtable *st, node *n, int flag) else { int i; for (i = 0; i < NCH(n); i += 2) - symtable_assign(st, CHILD(n, i), flag); + symtable_assign(st, CHILD(n, i), def_flag); return; } goto loop; @@ -5246,24 +5278,24 @@ symtable_assign(struct symtable *st, node *n, int flag) } else if (TYPE(tmp) == NAME) { if (strcmp(STR(tmp), "__debug__") == 0) symtable_warn(st, ASSIGN_DEBUG); - symtable_add_def(st, STR(tmp), DEF_LOCAL | flag); + symtable_add_def(st, STR(tmp), DEF_LOCAL | def_flag); } return; case dotted_as_name: if (NCH(n) == 3) symtable_add_def(st, STR(CHILD(n, 2)), - DEF_LOCAL | flag); + DEF_LOCAL | def_flag); else symtable_add_def(st, STR(CHILD(CHILD(n, 0), 0)), - DEF_LOCAL | flag); + DEF_LOCAL | def_flag); return; case dotted_name: - symtable_add_def(st, STR(CHILD(n, 0)), DEF_LOCAL | flag); + symtable_add_def(st, STR(CHILD(n, 0)), DEF_LOCAL | def_flag); return; case NAME: - symtable_add_def(st, STR(n), DEF_LOCAL | flag); + symtable_add_def(st, STR(n), DEF_LOCAL | def_flag); return; default: if (NCH(n) == 0) @@ -5276,6 +5308,6 @@ symtable_assign(struct symtable *st, node *n, int flag) which will be caught in the next pass. */ for (i = 0; i < NCH(n); ++i) if (TYPE(CHILD(n, i)) >= single_input) - symtable_assign(st, CHILD(n, i), flag); + symtable_assign(st, CHILD(n, i), def_flag); } }