From f1a7178cd569383cbce3aba22bd7b1d5950e7c20 Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Thu, 24 Jan 2008 23:42:08 +0000 Subject: [PATCH] #1920: when considering a block starting by "while 0", the compiler optimized the whole construct away, even when an 'else' clause is present:: while 0: print("no") else: print("yes") did not generate any code at all. Now the compiler emits the 'else' block, like it already does for 'if' statements. Backport of r60265. --- Lib/test/test_grammar.py | 9 +++++++++ Misc/NEWS | 5 +++++ Python/compile.c | 5 ++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 76483f676a0..89e9e678950 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -511,6 +511,15 @@ while 0: pass while 0: pass else: pass +# Issue1920: "while 0" is optimized away, +# ensure that the "else" clause is still present. +x = 0 +while 0: + x = 1 +else: + x = 2 +assert x == 2 + print 'for_stmt' # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] for i in 1, 2, 3: pass for i, j, k in (): pass diff --git a/Misc/NEWS b/Misc/NEWS index 8b0084aad96..4913c79bcb7 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,11 @@ What's New in Python 2.5.2c1? Core and builtins ----------------- +- Issue #1920: "while 0" statements were completely removed by the compiler, + even in the presence of an "else" clause, which is supposed to be run when + the condition is false. Now the compiler correctly emits bytecode for the + "else" suite. + - A few crashers fixed: weakref_in_del.py (issue #1377858); loosing_dict_ref.py (issue #1303614, test67.py); borrowed_ref_[34].py (not in tracker). diff --git a/Python/compile.c b/Python/compile.c index 0e824caabdb..8e96ddfa62c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -2256,8 +2256,11 @@ compiler_while(struct compiler *c, stmt_ty s) basicblock *loop, *orelse, *end, *anchor = NULL; int constant = expr_constant(s->v.While.test); - if (constant == 0) + if (constant == 0) { + if (s->v.While.orelse) + VISIT_SEQ(c, stmt, s->v.While.orelse); return 1; + } loop = compiler_new_block(c); end = compiler_new_block(c); if (constant == -1) {