#!/usr/bin/perl -w
-my $Has_PH;
+my ($Has_PH, $Field);
BEGIN {
$Has_PH = $] < 5.009;
+ $Field = $Has_PH ? "pseudo-hash field" : "class field";
}
my $W;
}
use strict;
-use Test::More tests => 26;
+use Test::More tests => 28;
BEGIN { use_ok('base'); }
$obj2->{b1} = "D3";
# We should get compile time failures field name typos
-eval q(my D3 $obj3 = $obj2; $obj3->{notthere} = "");
-if( $Has_PH ) {
- like $@,
- qr/^No such pseudo-hash field "notthere" in variable \$obj3 of type D3/;
-}
-else {
- like $@,
- qr/^Attempt to access disallowed key 'notthere' in a restricted hash/;
-}
+eval q(return; my D3 $obj3 = $obj2; $obj3->{notthere} = "");
+like $@,
+ qr/^No such $Field "notthere" in variable \$obj3 of type D3/,
+ "Compile failure of undeclared fields (helem)";
# Slices
+# We should get compile time failures field name typos
+eval q(return; my D3 $obj3 = $obj2; my $k; @$obj3{$k,'notthere'} = ());
+like $@,
+ qr/^No such $Field "notthere" in variable \$obj3 of type D3/,
+ "Compile failure of undeclared fields (hslice)";
+eval q(return; my D3 $obj3 = $obj2; my $k; @{$obj3}{$k,'notthere'} = ());
+like
+ $@, qr/^No such $Field "notthere" in variable \$obj3 of type D3/,
+ "Compile failure of undeclared fields (hslice (block form))";
+
@$obj1{"_b1", "b1"} = (17, 29);
is( $obj1->{_b1}, 17 );
is( $obj1->{b1}, 29 );
break;
case OP_HELEM: {
+ UNOP *rop;
SV *lexname;
+ GV **fields;
SV **svp, *sv;
char *key = NULL;
STRLEN keylen;
SvREFCNT_dec(sv);
*svp = lexname;
}
+
+ if ((o->op_private & (OPpLVAL_INTRO)))
+ break;
+
+ rop = (UNOP*)((BINOP*)o)->op_first;
+ if (rop->op_type != OP_RV2HV || rop->op_first->op_type != OP_PADSV)
+ break;
+ lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE);
+ if (!(SvFLAGS(lexname) & SVpad_TYPED))
+ break;
+ fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE);
+ if (!fields || !GvHV(*fields))
+ break;
+ key = SvPV(*svp, keylen);
+ if (!hv_fetch(GvHV(*fields), key,
+ SvUTF8(*svp) ? -(I32)keylen : keylen, FALSE))
+ {
+ Perl_croak(aTHX_ "No such class field \"%s\" "
+ "in variable %s of type %s",
+ key, SvPV_nolen(lexname), HvNAME(SvSTASH(lexname)));
+ }
+
break;
}
+ case OP_HSLICE: {
+ UNOP *rop;
+ SV *lexname;
+ GV **fields;
+ SV **svp;
+ char *key;
+ STRLEN keylen;
+ SVOP *first_key_op, *key_op;
+
+ if ((o->op_private & (OPpLVAL_INTRO))
+ /* I bet there's always a pushmark... */
+ || ((LISTOP*)o)->op_first->op_sibling->op_type != OP_LIST)
+ /* hmmm, no optimization if list contains only one key. */
+ break;
+ rop = (UNOP*)((LISTOP*)o)->op_last;
+ if (rop->op_type != OP_RV2HV)
+ break;
+ if (rop->op_first->op_type == OP_PADSV)
+ /* @$hash{qw(keys here)} */
+ rop = (UNOP*)rop->op_first;
+ else {
+ /* @{$hash}{qw(keys here)} */
+ if (rop->op_first->op_type == OP_SCOPE
+ && cLISTOPx(rop->op_first)->op_last->op_type == OP_PADSV)
+ {
+ rop = (UNOP*)cLISTOPx(rop->op_first)->op_last;
+ }
+ else
+ break;
+ }
+
+ lexname = *av_fetch(PL_comppad_name, rop->op_targ, TRUE);
+ if (!(SvFLAGS(lexname) & SVpad_TYPED))
+ break;
+ fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE);
+ if (!fields || !GvHV(*fields))
+ break;
+ /* Again guessing that the pushmark can be jumped over.... */
+ first_key_op = (SVOP*)((LISTOP*)((LISTOP*)o)->op_first->op_sibling)
+ ->op_first->op_sibling;
+ for (key_op = first_key_op; key_op;
+ key_op = (SVOP*)key_op->op_sibling) {
+ if (key_op->op_type != OP_CONST)
+ continue;
+ svp = cSVOPx_svp(key_op);
+ key = SvPV(*svp, keylen);
+ if (!hv_fetch(GvHV(*fields), key,
+ SvUTF8(*svp) ? -(I32)keylen : keylen, FALSE))
+ {
+ Perl_croak(aTHX_ "No such class field \"%s\" "
+ "in variable %s of type %s",
+ key, SvPV_nolen(lexname), HvNAME(SvSTASH(lexname)));
+ }
+ }
+ break;
+ }
+
case OP_SORT: {
/* will point to RV2AV or PADAV op on LHS/RHS of assign */
OP *oleft, *oright;