Commits

Jeremy Hylton  committed 04afb36

Generate line number table entries for except handlers.

Re-enable all the tests in test_trace.py except one. Still not sure that these tests test what they used to test, but they pass. One failing test seems to be caused by undocumented line number table behavior in Python 2.4.

  • Participants
  • Parent commits 1f109a4
  • Branches legacy-trunk

Comments (0)

Files changed (2)

File Lib/test/test_trace.py

                 (1, 'line'),
                 (1, 'return')]
 
-# Armin Rigo's failing example:
+# Many of the tests below are tricky because they involve pass statements.
+# If there is implicit control flow around a pass statement (in an except
+# clause or else caluse) under what conditions do you set a line number
+# following that clause?
+
+
+# The entire "while 0:" statement is optimized away.  No code
+# exists for it, so the line numbers skip directly from "del x"
+# to "x = 1".
 def arigo_example():
     x = 1
     del x
 arigo_example.events = [(0, 'call'),
                         (1, 'line'),
                         (2, 'line'),
-                        (3, 'line'),
                         (5, 'line'),
                         (5, 'return')]
 
                       (2, 'return')]
 
 def no_pop_blocks():
-    while 0:
+    y = 1
+    while not y:
         bla
     x = 1
 
 no_pop_blocks.events = [(0, 'call'),
                         (1, 'line'),
-                        (3, 'line'),
-                        (3, 'return')]
+                        (2, 'line'),
+                        (4, 'line'),
+                        (4, 'return')]
 
 def called(): # line -3
     x = 1
                              (4, 'return')]
 
 # implicit return example
+# This test is interesting because of the else: pass
+# part of the code.  The code generate for the true
+# part of the if contains a jump past the else branch.
+# The compiler then generates an implicit "return None"
+# Internally, the compiler visits the pass statement
+# and stores its line number for use on the next instruction.
+# The next instruction is the implicit return None.
 def ireturn_example():
     a = 5
     b = 5
                           (2, 'line'),
                           (3, 'line'),
                           (4, 'line'),
-                          (4, 'return')]
+                          (6, 'line'),
+                          (6, 'return')]
 
 # Tight loop with while(1) example (SF #765624)
 def tightloop_example():
 
     def test_01_basic(self):
         self.run_test(basic)
-## XXX: These tests fail with the new ast compiler.  They must
-## be fixed before a release.
-##    def test_02_arigo(self):
-##        self.run_test(arigo_example)
+    def test_02_arigo(self):
+        self.run_test(arigo_example)
     def test_03_one_instr(self):
         self.run_test(one_instr_line)
-##    def test_04_no_pop_blocks(self):
-##        self.run_test(no_pop_blocks)
+    def test_04_no_pop_blocks(self):
+        self.run_test(no_pop_blocks)
 ##    def test_05_no_pop_tops(self):
 ##        self.run_test(no_pop_tops)
     def test_06_call(self):
         self.run_test2(settrace_and_return)
     def test_09_settrace_and_raise(self):
         self.run_test2(settrace_and_raise)
-##    def test_10_ireturn(self):
-##        self.run_test(ireturn_example)
+    def test_10_ireturn(self):
+        self.run_test(ireturn_example)
     def test_11_tightloop(self):
         self.run_test(tightloop_example)
     def test_12_tighterloop(self):
         self.run_test(no_jump_too_far_forwards)
     def test_09_no_jump_too_far_backwards(self):
         self.run_test(no_jump_too_far_backwards)
-# XXX: These tests cause the interpreter to crash.  The frame_setlineno()
-# function no longer works correctly because the lineno table generated by
-# the AST compiler is slightly different than with the old compiler.
-#    def test_10_no_jump_to_except_1(self):
-#        self.run_test(no_jump_to_except_1)
-#    def test_11_no_jump_to_except_2(self):
-#        self.run_test(no_jump_to_except_2)
-#    def test_12_no_jump_to_except_3(self):
-#        self.run_test(no_jump_to_except_3)
-#    def test_13_no_jump_to_except_4(self):
-#        self.run_test(no_jump_to_except_4)
+    def test_10_no_jump_to_except_1(self):
+        self.run_test(no_jump_to_except_1)
+    def test_11_no_jump_to_except_2(self):
+        self.run_test(no_jump_to_except_2)
+    def test_12_no_jump_to_except_3(self):
+        self.run_test(no_jump_to_except_3)
+    def test_13_no_jump_to_except_4(self):
+        self.run_test(no_jump_to_except_4)
     def test_14_no_jump_forwards_into_block(self):
         self.run_test(no_jump_forwards_into_block)
     def test_15_no_jump_backwards_into_block(self):

File Python/compile.c

 						s->v.TryExcept.handlers, i);
 		if (!handler->type && i < n-1)
 		    return compiler_error(c, "default 'except:' must be last");
+        c->u->u_lineno_set = false;
+        c->u->u_lineno = handler->lineno;
 		except = compiler_new_block(c);
 		if (except == NULL)
 			return 0;