summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/attributes/attributes.pm12
-rw-r--r--ext/attributes/attributes.xs14
-rw-r--r--pod/perldiag.pod7
-rw-r--r--t/op/attrs.t24
4 files changed, 53 insertions, 4 deletions
diff --git a/ext/attributes/attributes.pm b/ext/attributes/attributes.pm
index dfd3a2594c..bac3d7be99 100644
--- a/ext/attributes/attributes.pm
+++ b/ext/attributes/attributes.pm
@@ -23,6 +23,12 @@ $deprecated{CODE} = qr/\A-?(locked)\z/;
$deprecated{ARRAY} = $deprecated{HASH} = $deprecated{SCALAR}
= qr/\A-?(unique)\z/;
+my %msg = (
+ lvalue => 'lvalue attribute applied to already-defined subroutine',
+ -lvalue => 'lvalue attribute removed from already-defined subroutine',
+ const => 'Useless use of attribute "const"',
+);
+
sub _modify_attrs_and_deprecate {
my $svtype = shift;
# Now that we've removed handling of locked from the XS code, we need to
@@ -34,13 +40,11 @@ sub _modify_attrs_and_deprecate {
require warnings;
warnings::warnif('deprecated', "Attribute \"$1\" is deprecated");
0;
- } : $svtype eq 'CODE' && /^-?lvalue\z/ ? do {
+ } : $svtype eq 'CODE' && exists $msg{$_} ? do {
require warnings;
warnings::warnif(
'misc',
- "lvalue attribute "
- . (/^-/ ? "removed from" : "applied to")
- . " already-defined subroutine"
+ $msg{$_}
);
0;
} : 1
diff --git a/ext/attributes/attributes.xs b/ext/attributes/attributes.xs
index 6b36812b13..7ba4f12613 100644
--- a/ext/attributes/attributes.xs
+++ b/ext/attributes/attributes.xs
@@ -44,6 +44,20 @@ modify_SV_attributes(pTHX_ SV *sv, SV **retlist, SV **attrlist, int numattrs)
switch (SvTYPE(sv)) {
case SVt_PVCV:
switch ((int)len) {
+ case 5:
+ if (memEQ(name, "const", 5)) {
+ if (negated)
+ CvANONCONST_off(sv);
+ else {
+ const bool warn = (!CvCLONE(sv) || CvCLONED(sv))
+ && !CvANONCONST(sv);
+ CvANONCONST_on(sv);
+ if (warn)
+ break;
+ }
+ continue;
+ }
+ break;
case 6:
switch (name[3]) {
case 'l':
diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index cc46a85d27..c9e49b6260 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@@ -6440,6 +6440,13 @@ must be written as
The <-- HERE shows whereabouts in the regular expression the problem was
discovered. See L<perlre>.
+=item Useless use of attribute "const"
+
+(W misc) The "const" attribute has no effect except
+on anonymous closure prototypes. You applied it to
+a subroutine via L<attributes.pm|attributes>. This is only useful
+inside an attribute handler for an anonymous subroutine.
+
=item Useless use of /d modifier in transliteration operator
(W misc) You have used the /d modifier where the searchlist has the
diff --git a/t/op/attrs.t b/t/op/attrs.t
index 2761d4747a..f8515fb3d0 100644
--- a/t/op/attrs.t
+++ b/t/op/attrs.t
@@ -389,4 +389,28 @@ package ProtoTest {
}
is $ProtoTest::Proto, '$', 'prototypes are visible in attr handlers';
+{
+ my $w;
+ local $SIG{__WARN__} = sub { $w = shift };
+ attributes ->import(__PACKAGE__, \&foo, "const");
+ like $w, qr/^Useless use of attribute "const" at /,
+ 'Warning for useless const via attributes.pm';
+ $w = '';
+ attributes ->import(__PACKAGE__, \&foo, "const");
+ is $w, '', 'no warning for const if already applied';
+ attributes ->import(__PACKAGE__, \&foo, "-const");
+ is $w, '', 'no warning for -const with attr already applied';
+ attributes ->import(__PACKAGE__, \&bar, "-const");
+ is $w, '', 'no warning for -const with attr not already applied';
+ package ConstTest;
+ sub MODIFY_CODE_ATTRIBUTES {
+ attributes->import(shift, shift, lc shift) if $_[2]; ()
+ }
+ $_ = 32487;
+ my $sub = sub : Const { $_ };
+ undef $_;
+ ::is &$sub, 32487,
+ 'applying const attr via attributes.pm';
+}
+
done_testing();