diff --git a/MANIFEST b/MANIFEST
index df0e398a10c6..6f0d0d4afa8a 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -5639,6 +5639,7 @@ t/lib/feature/multidimensional Tests for enabling/disabling $foo{$x, $y} => $foo
t/lib/feature/nonesuch Tests for enabling/disabling nonexistent feature
t/lib/feature/removed Tests for enabling/disabling removed feature
t/lib/feature/say Tests for enabling/disabling say feature
+t/lib/feature/stringification Tests for enabling/disabling stringification feature
t/lib/feature/switch Tests for enabling/disabling switch feature
t/lib/h2ph.h Test header file for h2ph
t/lib/h2ph.pht Generated output from h2ph.h by h2ph, for comparison
diff --git a/cop.h b/cop.h
index b5f30bd0415f..777fb3bf7f5b 100644
--- a/cop.h
+++ b/cop.h
@@ -576,6 +576,8 @@ string C
, creating the package if necessary.
#define CopHINTHASH_get(c) ((COPHH*)((c)->cop_hints_hash))
#define CopHINTHASH_set(c,h) ((c)->cop_hints_hash = (h))
+#define CopFEATURES_setfrom(c, o) ((c)->cop_features = (o)->cop_features)
+
/*
=for apidoc Am|SV *|cop_hints_fetch_pvn|const COP *cop|const char *keypv|STRLEN keylen|U32 hash|U32 flags
diff --git a/feature.h b/feature.h
index 501bc3a3b180..e7a0c0f97747 100644
--- a/feature.h
+++ b/feature.h
@@ -26,10 +26,11 @@
#define FEATURE_SAY_BIT 0x0800
#define FEATURE_SIGNATURES_BIT 0x1000
#define FEATURE_STATE_BIT 0x2000
-#define FEATURE_SWITCH_BIT 0x4000
-#define FEATURE_TRY_BIT 0x8000
-#define FEATURE_UNIEVAL_BIT 0x10000
-#define FEATURE_UNICODE_BIT 0x20000
+#define FEATURE_STRINGIFICATION_BIT 0x4000
+#define FEATURE_SWITCH_BIT 0x8000
+#define FEATURE_TRY_BIT 0x10000
+#define FEATURE_UNIEVAL_BIT 0x20000
+#define FEATURE_UNICODE_BIT 0x40000
#define FEATURE_BUNDLE_DEFAULT 0
#define FEATURE_BUNDLE_510 1
@@ -159,6 +160,13 @@
FEATURE_IS_ENABLED_MASK(FEATURE_MYREF_BIT) \
)
+#define FEATURE_STRINGIFICATION_IS_ENABLED \
+ ( \
+ CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_527 \
+ || (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
+ FEATURE_IS_ENABLED_MASK(FEATURE_STRINGIFICATION_BIT)) \
+ )
+
#define FEATURE_UNICODE_IS_ENABLED \
( \
(CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_511 && \
@@ -337,6 +345,11 @@ S_magic_sethint_feature(pTHX_ SV *keysv, const char *keypv, STRLEN keylen,
mask = FEATURE_STATE_BIT;
break;
}
+ else if (keylen == sizeof("feature_stringification")-1
+ && memcmp(subf+1, "tringification", keylen - sizeof("feature_")) == 0) {
+ mask = FEATURE_STRINGIFICATION_BIT;
+ break;
+ }
else if (keylen == sizeof("feature_switch")-1
&& memcmp(subf+1, "witch", keylen - sizeof("feature_")) == 0) {
mask = FEATURE_SWITCH_BIT;
diff --git a/lib/feature.pm b/lib/feature.pm
index a1953e292e54..8507644cc40e 100644
--- a/lib/feature.pm
+++ b/lib/feature.pm
@@ -23,19 +23,20 @@ our %feature = (
postderef_qq => 'feature_postderef_qq',
unicode_eval => 'feature_unieval',
declared_refs => 'feature_myref',
+ stringification => 'feature_stringification',
unicode_strings => 'feature_unicode',
multidimensional => 'feature_multidimensional',
bareword_filehandles => 'feature_bareword_filehandles',
);
our %feature_bundle = (
- "5.10" => [qw(bareword_filehandles indirect multidimensional say state switch)],
- "5.11" => [qw(bareword_filehandles indirect multidimensional say state switch unicode_strings)],
- "5.15" => [qw(bareword_filehandles current_sub evalbytes fc indirect multidimensional say state switch unicode_eval unicode_strings)],
- "5.23" => [qw(bareword_filehandles current_sub evalbytes fc indirect multidimensional postderef_qq say state switch unicode_eval unicode_strings)],
- "5.27" => [qw(bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional postderef_qq say state switch unicode_eval unicode_strings)],
- "all" => [qw(bareword_filehandles bitwise current_sub declared_refs evalbytes fc indirect isa multidimensional postderef_qq refaliasing say signatures state switch try unicode_eval unicode_strings)],
- "default" => [qw(bareword_filehandles indirect multidimensional)],
+ "5.10" => [qw(bareword_filehandles indirect multidimensional say state stringification switch)],
+ "5.11" => [qw(bareword_filehandles indirect multidimensional say state stringification switch unicode_strings)],
+ "5.15" => [qw(bareword_filehandles current_sub evalbytes fc indirect multidimensional say state stringification switch unicode_eval unicode_strings)],
+ "5.23" => [qw(bareword_filehandles current_sub evalbytes fc indirect multidimensional postderef_qq say state stringification switch unicode_eval unicode_strings)],
+ "5.27" => [qw(bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional postderef_qq say state stringification switch unicode_eval unicode_strings)],
+ "all" => [qw(bareword_filehandles bitwise current_sub declared_refs evalbytes fc indirect isa multidimensional postderef_qq refaliasing say signatures state stringification switch try unicode_eval unicode_strings)],
+ "default" => [qw(bareword_filehandles indirect multidimensional stringification)],
);
$feature_bundle{"5.12"} = $feature_bundle{"5.11"};
@@ -431,6 +432,17 @@ C are caught by executing the body of the C block.
For more information, see L.
+=head2 The 'stringification' feature
+
+This feature enables converting references that have no string
+overloading into strings as described in L. It is enabled by
+default, but can be turned off to disable such conversions.
+
+Disabling this feature does not prevent numeric conversions.
+
+This feature is enabled under this name from Perl 5.34 onwards. In
+previous versions it was simply on all the time.
+
=head1 FEATURE BUNDLES
It's possible to load multiple features together, using
@@ -444,64 +456,69 @@ The following feature bundles are available:
bundle features included
--------- -----------------
:default indirect multidimensional
- bareword_filehandles
+ bareword_filehandles stringification
:5.10 bareword_filehandles indirect
- multidimensional say state switch
+ multidimensional say state stringification
+ switch
:5.12 bareword_filehandles indirect
- multidimensional say state switch
- unicode_strings
+ multidimensional say state stringification
+ switch unicode_strings
:5.14 bareword_filehandles indirect
- multidimensional say state switch
- unicode_strings
+ multidimensional say state stringification
+ switch unicode_strings
:5.16 bareword_filehandles current_sub evalbytes
fc indirect multidimensional say state
- switch unicode_eval unicode_strings
+ stringification switch unicode_eval
+ unicode_strings
:5.18 bareword_filehandles current_sub evalbytes
fc indirect multidimensional say state
- switch unicode_eval unicode_strings
+ stringification switch unicode_eval
+ unicode_strings
:5.20 bareword_filehandles current_sub evalbytes
fc indirect multidimensional say state
- switch unicode_eval unicode_strings
+ stringification switch unicode_eval
+ unicode_strings
:5.22 bareword_filehandles current_sub evalbytes
fc indirect multidimensional say state
- switch unicode_eval unicode_strings
+ stringification switch unicode_eval
+ unicode_strings
:5.24 bareword_filehandles current_sub evalbytes
fc indirect multidimensional postderef_qq
- say state switch unicode_eval
- unicode_strings
+ say state stringification switch
+ unicode_eval unicode_strings
:5.26 bareword_filehandles current_sub evalbytes
fc indirect multidimensional postderef_qq
- say state switch unicode_eval
- unicode_strings
+ say state stringification switch
+ unicode_eval unicode_strings
:5.28 bareword_filehandles bitwise current_sub
evalbytes fc indirect multidimensional
- postderef_qq say state switch unicode_eval
- unicode_strings
+ postderef_qq say state stringification
+ switch unicode_eval unicode_strings
:5.30 bareword_filehandles bitwise current_sub
evalbytes fc indirect multidimensional
- postderef_qq say state switch unicode_eval
- unicode_strings
+ postderef_qq say state stringification
+ switch unicode_eval unicode_strings
:5.32 bareword_filehandles bitwise current_sub
evalbytes fc indirect multidimensional
- postderef_qq say state switch unicode_eval
- unicode_strings
+ postderef_qq say state stringification
+ switch unicode_eval unicode_strings
:5.34 bareword_filehandles bitwise current_sub
evalbytes fc indirect multidimensional
- postderef_qq say state switch unicode_eval
- unicode_strings
+ postderef_qq say state stringification
+ switch unicode_eval unicode_strings
:5.36 bareword_filehandles bitwise current_sub
evalbytes fc indirect multidimensional
diff --git a/op.c b/op.c
index 61f7eaad7513..8279896cd494 100644
--- a/op.c
+++ b/op.c
@@ -9425,6 +9425,7 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
cop->cop_seq = seq;
cop->cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings);
CopHINTHASH_set(cop, cophh_copy(CopHINTHASH_get(PL_curcop)));
+ CopFEATURES_setfrom(cop, PL_curcop);
if (label) {
Perl_cop_store_label(aTHX_ cop, label, strlen(label), utf8);
diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index 88df9485059e..a0e74f3fbcbf 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@@ -413,6 +413,11 @@ assigning through that reference. For example
$r = do {my @a; \$#a};
$$r = 503
+=item Attempt to stringify reference under no feature stringification
+
+(F) You tried to use a reference that has no string overloading in
+string context in lexical context of C
+
=item Attempt to use reference as lvalue in substr
(W substr) You supplied a reference as the first argument to substr()
diff --git a/regen/feature.pl b/regen/feature.pl
index 19af0a35ce41..36ab4b69f30d 100755
--- a/regen/feature.pl
+++ b/regen/feature.pl
@@ -41,6 +41,7 @@ BEGIN
multidimensional => 'multidimensional',
bareword_filehandles => 'bareword_filehandles',
try => 'try',
+ stringification => 'stringification',
);
# NOTE: If a feature is ever enabled in a non-contiguous range of Perl
@@ -50,7 +51,8 @@ BEGIN
# 5.odd implies the next 5.even, but an explicit 5.even can override it.
# features bundles
-use constant V5_9_5 => sort qw{say state switch indirect multidimensional bareword_filehandles};
+use constant V5_9_5 => sort qw{say state switch indirect multidimensional bareword_filehandles
+ stringification};
use constant V5_11 => sort ( +V5_9_5, qw{unicode_strings} );
use constant V5_15 => sort ( +V5_11, qw{unicode_eval evalbytes current_sub fc} );
use constant V5_23 => sort ( +V5_15, qw{postderef_qq} );
@@ -58,7 +60,7 @@ BEGIN
my %feature_bundle = (
all => [ sort keys %feature ],
- default => [ qw{indirect multidimensional bareword_filehandles} ],
+ default => [ qw{indirect multidimensional bareword_filehandles stringification} ],
# using 5.9.5 features bundle
"5.9.5" => [ +V5_9_5 ],
"5.10" => [ +V5_9_5 ],
@@ -836,6 +838,17 @@ =head2 The 'try' feature.
For more information, see L.
+=head2 The 'stringification' feature
+
+This feature enables converting references that have no string
+overloading into strings as described in L. It is enabled by
+default, but can be turned off to disable such conversions.
+
+Disabling this feature does not prevent numeric conversions.
+
+This feature is enabled under this name from Perl 5.34 onwards. In
+previous versions it was simply on all the time.
+
=head1 FEATURE BUNDLES
It's possible to load multiple features together, using
diff --git a/sv.c b/sv.c
index eec33eb5cab1..a9d25070c6f4 100644
--- a/sv.c
+++ b/sv.c
@@ -31,6 +31,7 @@
#define PERL_IN_SV_C
#include "perl.h"
#include "regcomp.h"
+#include "feature.h"
#ifdef __VMS
# include
#endif
@@ -3105,6 +3106,11 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const U32 flags)
if (lp)
*lp = len;
SAVEFREEPV(buffer);
+
+ if (!FEATURE_STRINGIFICATION_IS_ENABLED) {
+ Perl_croak(aTHX_ "Attempt to stringify reference under no feature stringification");
+ }
+
return retval;
}
}
diff --git a/t/lib/feature/stringification b/t/lib/feature/stringification
new file mode 100644
index 000000000000..320a595dd2f9
--- /dev/null
+++ b/t/lib/feature/stringification
@@ -0,0 +1,29 @@
+Test no feature stringification
+
+__END__
+# NAME simple
+# default on
+my $x = \1;
+my $y = "$x";
+# on in bundles
+use v5.10.0;
+$y = "$x";
+use v5.32.0;
+$y = "$x";
+use feature ":5.32.0"; # feature and use v end up different under the hood.
+$y = "$x";
+no feature "stringification";
+$y = "$x";
+EXPECT
+OPTIONS fatal
+Attempt to stringify reference under no feature stringification at - line 12.
+########
+# NAME overloaded
+package Foo {
+ use overload '""' => sub { "ABC" };
+};
+my $x = bless {}, "Foo";
+no feature "stringification";
+print $x, "\n";
+EXPECT
+ABC