const char *pos;
char *buf;
STRLEN len, size;
+ line_t line;
} indirect_op_info_t;
#define PTABLE_NAME ptable
/* ... op -> source position ............................................... */
-STATIC void indirect_map_store(pTHX_ const OP *o, const char *src, SV *sv) {
-#define indirect_map_store(O, S, N) indirect_map_store(aTHX_ (O), (S), (N))
+STATIC void indirect_map_store(pTHX_ const OP *o, const char *src, SV *sv, line_t line) {
+#define indirect_map_store(O, S, N, L) indirect_map_store(aTHX_ (O), (S), (N), (L))
indirect_op_info_t *oi;
const char *s;
STRLEN len;
oi->size = len;
}
Copy(s, oi->buf, len, char);
- oi->len = len;
- oi->pos = src;
+ oi->len = len;
+ oi->pos = src;
+ oi->line = line;
}
STATIC const indirect_op_info_t *indirect_map_fetch(pTHX_ const OP *o) {
if (indirect_hint()) {
SV *sv = cSVOPo_sv;
if (SvPOK(sv) && (SvTYPE(sv) >= SVt_PV)) {
- indirect_map_store(o, indirect_find(sv, PL_oldbufptr), sv);
+ const char *s = indirect_find(sv, PL_oldbufptr);
+ indirect_map_store(o, s, sv, CopLINE(&PL_compiling));
return o;
}
}
}
o = CALL_FPTR(indirect_old_ck_rv2sv)(aTHX_ o);
- indirect_map_store(o, s, sv);
+ indirect_map_store(o, s, sv, CopLINE(&PL_compiling));
return o;
}
while (s < t && isSPACE(*t)) --t;
sv = sv_2mortal(newSVpvn("$", 1));
sv_catpvn_nomg(sv, s, t - s + 1);
- indirect_map_store(o, s, sv);
+ indirect_map_store(o, s, sv, CopLINE(&PL_compiling));
return o;
}
}
OP *op = cUNOPo->op_first;
const indirect_op_info_t *oi = indirect_map_fetch(op);
const char *s = NULL;
+ line_t line;
SV *sv;
if (oi && (s = oi->pos)) {
- sv = sv_2mortal(newSVpvn(oi->buf, oi->len));
+ sv = sv_2mortal(newSVpvn(oi->buf, oi->len));
+ line = oi->line; /* Keep the old line so that we really point to the first */
} else {
sv = cSVOPx_sv(op);
if (!SvPOK(sv) || (SvTYPE(sv) < SVt_PV))
goto done;
- sv = sv_mortalcopy(sv);
- s = indirect_find(sv, PL_oldbufptr);
+ sv = sv_mortalcopy(sv);
+ s = indirect_find(sv, PL_oldbufptr);
+ line = CopLINE(&PL_compiling);
}
o = CALL_FPTR(indirect_old_ck_method)(aTHX_ o);
/* o may now be a method_named */
- indirect_map_store(o, s, sv);
+ indirect_map_store(o, s, sv, line);
return o;
}
goto done;
if (moi->pos < ooi->pos) {
- SV *file;
- line_t line;
+ SV *file;
dSP;
ENTER;
#else
file = sv_mortalcopy(CopFILESV(&PL_compiling));
#endif
- line = CopLINE(&PL_compiling);
PUSHMARK(SP);
EXTEND(SP, 4);
mPUSHp(ooi->buf, ooi->len);
mPUSHp(moi->buf, moi->len);
PUSHs(file);
- mPUSHu(line);
+ mPUSHu(moi->line);
PUTBACK;
call_sv(code, G_VOID);
--- /dev/null
+#!perl -T
+
+use strict;
+use warnings;
+
+use Test::More tests => 3 * 4;
+
+sub expect {
+ my ($pkg, $line) = @_;
+ return qr/^Indirect\s+call\s+of\s+method\s+"new"\s+on\s+object\s+"$pkg"\s+at\s+\(eval\s+\d+\)\s+line\s+$line/;
+}
+
+{
+ local $/ = "####";
+ while (<DATA>) {
+ chomp;
+ s/^\s+//;
+
+ my ($code, $lines) = split /#+/, $_, 2;
+ $lines = eval "[ sort ($lines) ]";
+ if ($@) {
+ diag "Couldn't parse line numbers: $@";
+ next;
+ }
+
+ my (@warns, @lines);
+ {
+ local $SIG{__WARN__} = sub { push @warns, "@_" };
+ eval "return; no indirect hook => sub { push \@lines, \$_[3] }; $code";
+ }
+
+ is $@, '', 'did\'t croak';
+ is_deeply \@warns, [ ], 'didn\'t warn';
+ is_deeply [ sort @lines ], $lines, 'correct line numbers';
+ }
+}
+
+__DATA__
+my $x = new X; # 1
+####
+my $x = new
+ X; # 1
+####
+my $x = new X; $x = new X; # 1, 1
+####
+my $x = new
+ X new
+ X; # 1, 2