Skip to content

Commit 1b37187

Browse files
committed
ParseXS: allow SV* as placeholder
ExtUtils::ParseXS, up until and including perl 5.40.0, accepted unparseable XSUB parameter declarations: if the parameter couldn't be parsed, it was just silently skipped. This had the side effect that any old line noise could be used as a placeholder: no parameter would be declared, but during arg processing, the arg would be skipped. During my recent refactoring work, I instead made it an error if the parameter couldn't be parsed, but this broke some modules which were using 'SV*' as a placeholder, e.g. int foo(int a, SV*, int b) ... To partially restore backwards compatibility, this commit recognises the special case of 'SV*' being used as a placeholder. All other unparseable parameter declarations will continue to be an error. It will however now still emit an error if 'SV*' is used on a bodiless sub. It used to cause the call to the C function to be emitted as (from the example above), RETVAL = foo(a, SV*, b); which isn't legal C code. So making it an error isn't breaking backwards compatibility. The coder can still use C_ARGS, e.g. int foo(int a, SV*, int b) C_ARGS: a, b
1 parent 8ac54f3 commit 1b37187

File tree

3 files changed

+70
-3
lines changed

3 files changed

+70
-3
lines changed

dist/ExtUtils-ParseXS/lib/ExtUtils/ParseXS.pm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,7 @@ EOF
12091209

12101210
my $sig = $self->{xsub_sig};
12111211
my $args = $sig->{auto_function_sig_override}; # C_ARGS
1212-
$args = $sig->C_func_signature()
1212+
$args = $sig->C_func_signature($self)
12131213
unless defined $args;
12141214
print "$self->{xsub_func_name}($args);\n";
12151215

dist/ExtUtils-ParseXS/lib/ExtUtils/ParseXS/Node.pm

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,18 @@ sub parse {
687687
/x;
688688

689689
unless (defined $name) {
690-
$pxs->blurt("Unparseable XSUB parameter: '$_'");
690+
if (/^ SV \s* \* $/x) {
691+
# special-case SV* as a placeholder for backwards
692+
# compatibility.
693+
push @{$self->{params}},
694+
ExtUtils::ParseXS::Node::Param->new( {
695+
var => 'SV *',
696+
arg_num => ++$nargs,
697+
});
698+
}
699+
else {
700+
$pxs->blurt("Unparseable XSUB parameter: '$_'");
701+
}
691702
next;
692703
}
693704

@@ -839,6 +850,7 @@ sub usage_string {
839850

840851
sub C_func_signature {
841852
my ExtUtils::ParseXS::Node::Sig $self = shift;
853+
my ExtUtils::ParseXS $pxs = shift;
842854

843855
my @args;
844856
for my $param (@{$self->{params}}) {
@@ -853,6 +865,12 @@ sub C_func_signature {
853865
next;
854866
}
855867

868+
if ($param->{var} eq 'SV *') {
869+
#backcompat placeholder
870+
$pxs->blurt("Error: parameter 'SV *' not valid as a C argument");
871+
next;
872+
}
873+
856874
my $io = $param->{in_out};
857875
$io = '' unless defined $io;
858876

dist/ExtUtils-ParseXS/t/001-basic.t

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/perl
22

33
use strict;
4-
use Test::More tests => 460;
4+
use Test::More tests => 472;
55
use Config;
66
use DynaLoader;
77
use ExtUtils::CBuilder;
@@ -1639,6 +1639,16 @@ EOF
16391639
],
16401640
[ 0, 0, qr/"\$\$;\$"/, "" ],
16411641
],
1642+
1643+
[
1644+
"auto-generated proto with backcompat SV* placeholder",
1645+
[
1646+
'void',
1647+
'foo(int a, SV*, char *c = "")',
1648+
'C_ARGS: a, c',
1649+
],
1650+
[ 0, 0, qr/"\$\$;\$"/, "" ],
1651+
],
16421652
);
16431653

16441654
test_many($preamble, 'boot_Foo', \@test_fns);
@@ -2780,6 +2790,45 @@ EOF
27802790
[ 0, 1, qr/\b888\s*;/, "no 888 usage" ],
27812791
],
27822792
2793+
[
2794+
"placeholder: allow SV *",
2795+
[ Q(<<'EOF') ],
2796+
|int
2797+
|foo(int AAA, SV *, int CCC)
2798+
| CODE:
2799+
| XYZ;
2800+
EOF
2801+
[ 0, 0, qr/_usage\(cv,\s*\Q"AAA, SV *, CCC")/, "usage" ],
2802+
[ 0, 0, qr/\bint\s+AAA\s*=\s*.*\Q(ST(0))/, "AAA is ST(0)" ],
2803+
[ 0, 0, qr/\bint\s+CCC\s*=\s*.*\Q(ST(2))/, "CCC is ST(2)" ],
2804+
],
2805+
2806+
[
2807+
# Bodiless XSUBs can't use SV* as a placeholder ...
2808+
"placeholder: SV *, bodiless",
2809+
[ Q(<<'EOF') ],
2810+
|int
2811+
|foo(int AAA, SV *, int CCC)
2812+
EOF
2813+
[ 1, 0, qr/Error: parameter 'SV \*' not valid as a C argument/,
2814+
"got arg err" ],
2815+
],
2816+
2817+
[
2818+
# ... unless they use C_ARGS to define how the C fn should
2819+
# be called.
2820+
"placeholder: SV *, bodiless C_ARGS",
2821+
[ Q(<<'EOF') ],
2822+
|int
2823+
|foo(int AAA, SV *, int CCC)
2824+
| C_ARGS: AAA, CCC
2825+
EOF
2826+
[ 0, 0, qr/_usage\(cv,\s*\Q"AAA, SV *, CCC")/, "usage" ],
2827+
[ 0, 0, qr/\bint\s+AAA\s*=\s*.*\Q(ST(0))/, "AAA is ST(0)" ],
2828+
[ 0, 0, qr/\bint\s+CCC\s*=\s*.*\Q(ST(2))/, "CCC is ST(2)" ],
2829+
[ 0, 0, qr/\bRETVAL\s*=\s*\Qfoo(AAA, CCC);/, "autocall" ],
2830+
],
2831+
27832832
27842833
);
27852834

0 commit comments

Comments
 (0)