develooper Front page | perl.perl5.changes | Postings from April 2008

Change 33726: Integrate:

From:
Nicholas Clark
Date:
April 22, 2008 08:30
Subject:
Change 33726: Integrate:
Change 33726 by nicholas@mouse-mill on 2008/04/22 15:18:16

	Integrate:
	[ 33709]
	Add "eliminate incorrect line numbers in warnings" to perltodo, and
	a pair of TODO tests for the desired behaviour.
	
	[ 33710]
	Fix the line-number-in-elsif longstanding bug.
	This patch does two things :
	- newSTATEOP now nullifies the state op it
	  just created if OPf_SPECIAL is passed to it
	  in flags
	- the parser now inserts a nullified stateop
	  in the expression block of an elsif
	
	[ 33724]
	Note that Rafael did the key elsif() line number TODO, and we're not
	certain that solving the general case is worth it.

Affected files ...

... //depot/maint-5.10/perl/op.c#7 integrate
... //depot/maint-5.10/perl/perly.act#2 integrate
... //depot/maint-5.10/perl/perly.y#2 integrate
... //depot/maint-5.10/perl/pod/perltodo.pod#6 integrate
... //depot/maint-5.10/perl/t/lib/warnings/9uninit#2 integrate

Differences ...

==== //depot/maint-5.10/perl/op.c#7 (text) ====
Index: perl/op.c
--- perl/op.c#6~33611~	2008-03-31 05:32:56.000000000 -0700
+++ perl/op.c	2008-04-22 08:18:16.000000000 -0700
@@ -4269,6 +4269,8 @@
 	}
     }
 
+    if (flags & OPf_SPECIAL)
+	op_null((OP*)cop);
     return prepend_elem(OP_LINESEQ, (OP*)cop, o);
 }
 

==== //depot/maint-5.10/perl/perly.act#2 (text) ====
Index: perl/perly.act
--- perl/perly.act#1~32694~	2007-12-22 01:23:09.000000000 -0800
+++ perl/perly.act	2008-04-22 08:18:16.000000000 -0700
@@ -186,7 +186,7 @@
   case 27:
 #line 277 "perly.y"
     { PL_parser->copline = (line_t)IVAL((ps[(1) - (6)].val.i_tkval));
-			    (yyval.opval) = newCONDOP(0, (ps[(3) - (6)].val.opval), scope((ps[(5) - (6)].val.opval)), (ps[(6) - (6)].val.opval));
+			    (yyval.opval) = newCONDOP(0, newSTATEOP(OPf_SPECIAL,NULL,(ps[(3) - (6)].val.opval)), scope((ps[(5) - (6)].val.opval)), (ps[(6) - (6)].val.opval));
 			    PL_hints |= HINT_BLOCK_SCOPE;
 			  TOKEN_GETMAD((ps[(1) - (6)].val.i_tkval),(yyval.opval),'I');
 			  TOKEN_GETMAD((ps[(2) - (6)].val.i_tkval),(yyval.opval),'(');

==== //depot/maint-5.10/perl/perly.y#2 (text) ====
Index: perl/perly.y
--- perl/perly.y#1~32694~	2007-12-22 01:23:09.000000000 -0800
+++ perl/perly.y	2008-04-22 08:18:16.000000000 -0700
@@ -275,7 +275,7 @@
 			}
 	|	ELSIF '(' mexpr ')' mblock else
 			{ PL_parser->copline = (line_t)IVAL($1);
-			    $$ = newCONDOP(0, $3, scope($5), $6);
+			    $$ = newCONDOP(0, newSTATEOP(OPf_SPECIAL,NULL,$3), scope($5), $6);
 			    PL_hints |= HINT_BLOCK_SCOPE;
 			  TOKEN_GETMAD($1,$$,'I');
 			  TOKEN_GETMAD($2,$$,'(');

==== //depot/maint-5.10/perl/pod/perltodo.pod#6 (text) ====
Index: perl/pod/perltodo.pod
--- perl/pod/perltodo.pod#5~33660~	2008-04-07 11:01:38.000000000 -0700
+++ perl/pod/perltodo.pod	2008-04-22 08:18:16.000000000 -0700
@@ -884,6 +884,65 @@
 hash key scalars. Under ithreads, something is undoing this work. See
 See http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2007-09/msg00793.html
 
+=head2 eliminate incorrect line numbers in warnings
+
+This code
+
+    use warnings;
+    my $undef;
+    
+    if ($undef == 3) {
+    } elsif ($undef == 0) {
+    }
+
+used to produce this output:
+
+    Use of uninitialized value in numeric eq (==) at wrong.pl line 4.
+    Use of uninitialized value in numeric eq (==) at wrong.pl line 4.
+
+where the line of the second warning was misreported - it should be line 5.
+Rafael fixed this - the problem arose because there was no nextstate OP
+between the execution of the C<if> and the C<elsif>, hence C<PL_curcop> still
+reports that the currently executing line is line 4. The solution was to inject
+a nextstate OPs for each C<elsif>, although it turned out that the nextstate
+OP needed to be a nulled OP, rather than a live nextstate OP, else other line
+numbers became misreported. (Jenga!)
+
+The problem is more general than C<elsif> (although the C<elsif> case is the
+most common and the most confusing). Ideally this code
+
+    use warnings;
+    my $undef;
+    
+    my $a = $undef + 1;
+    my $b
+      = $undef
+      + 1;
+
+would produce this output
+
+    Use of uninitialized value $undef in addition (+) at wrong.pl line 4.
+    Use of uninitialized value $undef in addition (+) at wrong.pl line 7.
+
+(rather than lines 4 and 5), but this would seem to require every OP to carry
+(at least) line number information.
+
+What might work is to have an optional line number in memory just before the
+BASEOP structure, with a flag bit in the op to say whether it's present.
+Initially during compile every OP would carry its line number. Then add a late
+pass to the optimiser (potentially combined with L</repack the optree>) which
+looks at the two ops on every edge of the graph of the execution path. If
+the line number changes, flags the destination OP with this information.
+Once all paths are traced, replace every op with the flag with a
+nextstate-light op (that just updates C<PL_curcop>), which in turn then passes
+control on to the true op. All ops would then be replaced by variants that
+do not store the line number. (Which, logically, why it would work best in
+conjunction with L</repack the optree>, as that is already copying/reallocating
+all the OPs)
+
+(Although I should note that we're not certain that doing this for the general
+case is worth it)
+
 =head1 Big projects
 
 Tasks that will get your name mentioned in the description of the "Highlights

==== //depot/maint-5.10/perl/t/lib/warnings/9uninit#2 (text) ====
Index: perl/t/lib/warnings/9uninit
--- perl/t/lib/warnings/9uninit#1~32694~	2007-12-22 01:23:09.000000000 -0800
+++ perl/t/lib/warnings/9uninit	2008-04-22 08:18:16.000000000 -0700
@@ -1313,3 +1313,25 @@
 exit $m1;
 EXPECT
 Use of uninitialized value $m1 in exit at - line 4.
+########
+use warnings 'uninitialized';
+my $undef;
+
+if ($undef == 3) {
+} elsif ($undef == 0) {
+}
+EXPECT
+Use of uninitialized value $undef in numeric eq (==) at - line 4.
+Use of uninitialized value $undef in numeric eq (==) at - line 5.
+########
+# TODO long standing bug - more general variant of the above problem
+use warnings;
+my $undef;
+
+my $a = $undef + 1;
+my $b
+  = $undef
+  + 1;
+EXPECT
+Use of uninitialized value $undef in addition (+) at - line 4.
+Use of uninitialized value $undef in addition (+) at - line 7.
End of Patch.



Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About