defer_queue[(defer_base + ++defer_ix) % MAX_DEFERRED] = o; \
} STMT_END
+#define IS_AND_OP(o) o->op_type == OP_AND
+#define IS_ORISH_OP(o) (o->op_type == OP_OR || o->op_type == OP_DOR)
+
/* A peephole optimizer. We visit the ops in the order they're to execute.
* See the comments at the top of this file for more details about when
* peep() is called */
while (o->op_next && ( o->op_type == o->op_next->op_type
|| o->op_next->op_type == OP_NULL))
o->op_next = o->op_next->op_next;
+ /* OP_OR/OP_DOR behave the same wrt op_next */
+ if (IS_ORISH_OP(o)) {
+ while (o->op_next && ( IS_ORISH_OP(o->op_next)
+ || o->op_next->op_type == OP_NULL))
+ o->op_next = o->op_next->op_next;
+ }
+ /* if we're an OR/DOR and our next is a AND in void context, we'll
+ follow it's op_other on short circuit, same for reverse */
+ if (o->op_next &&
+ (
+ (IS_AND_OP(o) && IS_ORISH_OP(o->op_next))
+ || (IS_ORISH_OP(o) && IS_AND_OP(o->op_next))
+ )
+ && (o->op_next->op_flags & OPf_WANT) == OPf_WANT_VOID
+ ) {
+ o->op_next = ((LOGOP*)o->op_next)->op_other;
+ }
DEFER(cLOGOP->op_other);
o->op_opt = 1;
package main;
require './test.pl';
-plan( tests => 8 );
+plan( tests => 10 );
my ($a, $b, $c);
local $TODO = 'Double FETCH';
is($c, 1, ' $tied || $var');
}
+
+my $aa, $bb, $cc;
+$bb = 1;
+
+my $res = 0;
+# Well, really testing OP_DOR I guess
+unless ($aa || $bb // $cc) {
+ $res = 1;
+}
+is($res, 0, "res is 0 after mixed OR/DOR");
+
+$res = 0;
+unless ($aa // $bb || $cc) {
+ $res = 1;
+}
+is($res, 0, "res is 0 after mixed DOR/OR");
+