7e86df
From 390fe0c0d09aadc66f644e9eee4aa1245221188c Mon Sep 17 00:00:00 2001
7e86df
From: David Mitchell <davem@iabyn.com>
7e86df
Date: Tue, 25 Aug 2020 13:15:25 +0100
7e86df
Subject: [PATCH] sort { return foo() } ...
7e86df
MIME-Version: 1.0
7e86df
Content-Type: text/plain; charset=UTF-8
7e86df
Content-Transfer-Encoding: 8bit
7e86df
7e86df
GH #18081
7e86df
7e86df
A sub call via return in a sort block was called in void rather than
7e86df
scalar context, causing the comparison result to be discarded.
7e86df
7e86df
This because when a sort block is called it is not a real function
7e86df
call, even though a sort block can be returned from. Instead, a
7e86df
CXt_NULL is pushed on the context stack. Because this isn't a sub-ish
7e86df
context type (unlike CXt_SUB, CXt_EVAL etc) there is no 'caller sub'
7e86df
on the context stack to be found to retrieve the caller's context
7e86df
(i.e. cx->cx_gimme).
7e86df
7e86df
This commit fixes it by special-casing Perl_gimme_V().
7e86df
7e86df
Ideally at some future point, a new context type, CXt_SORT, should be
7e86df
added. This would be used instead of CXt_NULL when a sort BLOCK is
7e86df
called. Like other sub-ish context types, it would have an old_cxsubix
7e86df
field and PL_curstackinfo->si_cxsubix would point to it. This would
7e86df
eliminate needing special-case handling in places like Perl_gimme_V().
7e86df
7e86df
Signed-off-by: Petr Písař <ppisar@redhat.com>
7e86df
---
7e86df
 inline.h    |  2 +-
7e86df
 t/op/sort.t | 12 +++++++++++-
7e86df
 2 files changed, 12 insertions(+), 2 deletions(-)
7e86df
7e86df
diff --git a/inline.h b/inline.h
7e86df
index a8240efb9c..6fbd5abfea 100644
7e86df
--- a/inline.h
7e86df
+++ b/inline.h
7e86df
@@ -2086,7 +2086,7 @@ Perl_gimme_V(pTHX)
7e86df
         return gimme;
7e86df
     cxix = PL_curstackinfo->si_cxsubix;
7e86df
     if (cxix < 0)
7e86df
-        return G_VOID;
7e86df
+        return PL_curstackinfo->si_type == PERLSI_SORT ? G_SCALAR: G_VOID;
7e86df
     assert(cxstack[cxix].blk_gimme & G_WANT);
7e86df
     return (cxstack[cxix].blk_gimme & G_WANT);
7e86df
 }
7e86df
diff --git a/t/op/sort.t b/t/op/sort.t
7e86df
index f2e139dff0..8e387fb90d 100644
7e86df
--- a/t/op/sort.t
7e86df
+++ b/t/op/sort.t
7e86df
@@ -7,7 +7,7 @@ BEGIN {
7e86df
     set_up_inc('../lib');
7e86df
 }
7e86df
 use warnings;
7e86df
-plan(tests => 203);
7e86df
+plan(tests => 204);
7e86df
 use Tie::Array; # we need to test sorting tied arrays
7e86df
 
7e86df
 # these shouldn't hang
7e86df
@@ -1202,3 +1202,13 @@ SKIP:
7e86df
     $fillb = undef;
7e86df
     is $act, "01[sortb]2[fillb]";
7e86df
 }
7e86df
+
7e86df
+# GH #18081
7e86df
+# sub call via return in sort block was called in void rather than scalar
7e86df
+# context
7e86df
+
7e86df
+{
7e86df
+    sub sort18081 { $a + 1 <=> $b + 1 }
7e86df
+    my @a = sort { return &sort18081 } 6,1,2;
7e86df
+    is "@a", "1 2 6", "GH #18081";
7e86df
+}
7e86df
-- 
7e86df
2.25.4
7e86df