Skip to content

Commit 2ac0488

Browse files
committed
[MERGE] ParseXS: notype param and SV* placeholders
These two commits: - add tests for the existing behaviour of allowing an XSUB parameter which doesn't have a type to act as a placeholder; - and as a special case, restores the recently changed behaviour of also allowing 'SV*' to denote a placeholder, and adds tests
2 parents aec2cdc + 1b37187 commit 2ac0488

File tree

3 files changed

+188
-4
lines changed

3 files changed

+188
-4
lines changed

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

+1-1
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

+19-1
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

+168-2
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 => 435;
4+
use Test::More tests => 472;
55
use Config;
66
use DynaLoader;
77
use ExtUtils::CBuilder;
@@ -1631,14 +1631,24 @@ EOF
16311631
],
16321632

16331633
[
1634-
# shady but legal
1634+
# shady but legal - placeholder
16351635
"auto-generated proto with no type",
16361636
[
16371637
'void',
16381638
'foo(a, b, c = 0)',
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);
@@ -2668,3 +2678,159 @@ EOF
26682678
26692679
test_many($preamble, 'XS_Foo_', \@test_fns);
26702680
}
2681+
2682+
{
2683+
# Test placeholders - various semi-official ways to to mark an
2684+
# argument as 'unused'.
2685+
2686+
my $preamble = Q(<<'EOF');
2687+
|MODULE = Foo PACKAGE = Foo
2688+
|
2689+
|PROTOTYPES: DISABLE
2690+
|
2691+
EOF
2692+
2693+
my @test_fns = (
2694+
2695+
[
2696+
"placeholder: typeless param with CODE",
2697+
[ Q(<<'EOF') ],
2698+
|int
2699+
|foo(int AAA, BBB, int CCC)
2700+
| CODE:
2701+
| XYZ;
2702+
EOF
2703+
[ 0, 0, qr/_usage\(cv,\s*"AAA, BBB, CCC"\)/, "usage" ],
2704+
[ 0, 0, qr/\bint\s+AAA\s*=\s*.*\Q(ST(0))/, "AAA is ST(0)" ],
2705+
[ 0, 0, qr/\bint\s+CCC\s*=\s*.*\Q(ST(2))/, "CCC is ST(2)" ],
2706+
[ 0, 1, qr/\bBBB;/, "no BBB decl" ],
2707+
],
2708+
2709+
[
2710+
"placeholder: typeless param bodiless",
2711+
[ Q(<<'EOF') ],
2712+
|int
2713+
|foo(int AAA, BBB, int CCC)
2714+
EOF
2715+
[ 0, 0, qr/_usage\(cv,\s*"AAA, BBB, CCC"\)/, "usage" ],
2716+
# Note that autocall uses the BBB var even though it isn't
2717+
# declared. It would be up to the coder to use C_ARGS, or add
2718+
# such a var via PREINIT.
2719+
[ 0, 0, qr/\bRETVAL\s*=\s*\Qfoo(AAA, BBB, CCC);/, "autocall" ],
2720+
[ 0, 0, qr/\bint\s+AAA\s*=\s*.*\Q(ST(0))/, "AAA is ST(0)" ],
2721+
[ 0, 0, qr/\bint\s+CCC\s*=\s*.*\Q(ST(2))/, "CCC is ST(2)" ],
2722+
[ 0, 1, qr/\bBBB;/, "no BBB decl" ],
2723+
],
2724+
2725+
[
2726+
# this is the only IN/OUT etc one which works, since IN is the
2727+
# default.
2728+
"placeholder: typeless IN param with CODE",
2729+
[ Q(<<'EOF') ],
2730+
|int
2731+
|foo(int AAA, IN BBB, int CCC)
2732+
| CODE:
2733+
| XYZ;
2734+
EOF
2735+
[ 0, 0, qr/_usage\(cv,\s*"AAA, BBB, CCC"\)/, "usage" ],
2736+
[ 0, 0, qr/\bint\s+AAA\s*=\s*.*\Q(ST(0))/, "AAA is ST(0)" ],
2737+
[ 0, 0, qr/\bint\s+CCC\s*=\s*.*\Q(ST(2))/, "CCC is ST(2)" ],
2738+
[ 0, 1, qr/\bBBB;/, "no BBB decl" ],
2739+
],
2740+
2741+
2742+
[
2743+
"placeholder: typeless OUT param with CODE",
2744+
[ Q(<<'EOF') ],
2745+
|int
2746+
|foo(int AAA, OUT BBB, int CCC)
2747+
| CODE:
2748+
| XYZ;
2749+
EOF
2750+
[ 1, 0, qr/Can't determine output type for 'BBB'/, "got type err" ],
2751+
],
2752+
2753+
[
2754+
"placeholder: typeless IN_OUT param with CODE",
2755+
[ Q(<<'EOF') ],
2756+
|int
2757+
|foo(int AAA, IN_OUT BBB, int CCC)
2758+
| CODE:
2759+
| XYZ;
2760+
EOF
2761+
[ 1, 0, qr/Can't determine output type for 'BBB'/, "got type err" ],
2762+
],
2763+
2764+
[
2765+
"placeholder: typeless OUTLIST param with CODE",
2766+
[ Q(<<'EOF') ],
2767+
|int
2768+
|foo(int AAA, OUTLIST BBB, int CCC)
2769+
| CODE:
2770+
| XYZ;
2771+
EOF
2772+
[ 1, 0, qr/Can't determine output type for 'BBB'/, "got type err" ],
2773+
],
2774+
2775+
[
2776+
# a placeholder with a default value may not seem to make much
2777+
# sense, but it allows an argument to still be passed (or
2778+
# not), even if it;s no longer used.
2779+
"placeholder: typeless default param with CODE",
2780+
[ Q(<<'EOF') ],
2781+
|int
2782+
|foo(int AAA, BBB = 888, int CCC = 999)
2783+
| CODE:
2784+
| XYZ;
2785+
EOF
2786+
[ 0, 0, qr/_usage\(cv,\s*"AAA, BBB = 888, CCC\s*= 999"\)/,"usage" ],
2787+
[ 0, 0, qr/\bint\s+AAA\s*=\s*.*\Q(ST(0))/, "AAA is ST(0)" ],
2788+
[ 0, 0, qr/\bCCC\s*=\s*.*\Q(ST(2))/, "CCC is ST(2)" ],
2789+
[ 0, 1, qr/\bBBB;/, "no BBB decl" ],
2790+
[ 0, 1, qr/\b888\s*;/, "no 888 usage" ],
2791+
],
2792+
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+
2832+
2833+
);
2834+
2835+
test_many($preamble, 'XS_Foo_', \@test_fns);
2836+
}

0 commit comments

Comments
 (0)