On 2017-07-23, at 4:14 PM, John David Anglin wrote: > Perl_custom_op_get_field (my_perl=0x1e3008, o=0x5aee38, field=XOPe_xop_peep) > at op.c:14853 > 14853 if (!he && PL_custom_op_names && > (gdb) > 14879 if(field == XOPe_xop_ptr) { > (gdb) > 14902 switch(field) { > (gdb) > 14884 switch(field) {
Gcc optimizes the two switch statements in Perl_custom_op_get_field() into one. It appears the address of xop gets lost when xop points to xop_null. The attached patch seems to work around the problem compiling op.c. This would appear to be a generic gcc bug. I also removed the hppa optimization hack for compiling op.c. It no longer seems to work as the last -O option is -O2. Adrian's optimization work around changed the last optimization to -O0. Maybe the patch will also fix the sh build. Dave -- John David Anglin dave.ang...@bell.net
Index: perl-5.26.0/op.c =================================================================== --- perl-5.26.0.orig/op.c +++ perl-5.26.0/op.c @@ -14832,6 +14832,7 @@ Perl_custom_op_get_field(pTHX_ const OP SV *keysv; HE *he = NULL; XOP *xop; + XOPRETANY any; static const XOP xop_null = { 0, 0, 0, 0, 0 }; @@ -14874,58 +14875,37 @@ Perl_custom_op_get_field(pTHX_ const OP else xop = INT2PTR(XOP *, SvIV(HeVAL(he))); } - { - XOPRETANY any; - if(field == XOPe_xop_ptr) { - any.xop_ptr = xop; - } else { - const U32 flags = XopFLAGS(xop); - if(flags & field) { - switch(field) { - case XOPe_xop_name: - any.xop_name = xop->xop_name; - break; - case XOPe_xop_desc: - any.xop_desc = xop->xop_desc; - break; - case XOPe_xop_class: - any.xop_class = xop->xop_class; - break; - case XOPe_xop_peep: - any.xop_peep = xop->xop_peep; - break; - default: - NOT_REACHED; /* NOTREACHED */ - break; - } - } else { - switch(field) { - case XOPe_xop_name: - any.xop_name = XOPd_xop_name; - break; - case XOPe_xop_desc: - any.xop_desc = XOPd_xop_desc; - break; - case XOPe_xop_class: - any.xop_class = XOPd_xop_class; - break; - case XOPe_xop_peep: - any.xop_peep = XOPd_xop_peep; - break; - default: - NOT_REACHED; /* NOTREACHED */ - break; - } - } + + if(field == XOPe_xop_ptr) { + any.xop_ptr = xop; + } else { + const U32 flags = XopFLAGS(xop); + switch(field) { + case XOPe_xop_name: + any.xop_name = (flags & field) ? xop->xop_name : XOPd_xop_name; + break; + case XOPe_xop_desc: + any.xop_desc = (flags & field) ? xop->xop_desc : XOPd_xop_desc; + break; + case XOPe_xop_class: + any.xop_class = (flags & field) ? xop->xop_class : XOPd_xop_class; + break; + case XOPe_xop_peep: + any.xop_peep = (flags & field) ? xop->xop_peep : XOPd_xop_peep; + break; + default: + NOT_REACHED; /* NOTREACHED */ + break; } - /* On some platforms (HP-UX, IA64) gcc emits a warning for this function: - * op.c: In function 'Perl_custom_op_get_field': - * op.c:...: warning: 'any.xop_name' may be used uninitialized in this function [-Wmaybe-uninitialized] - * This is because on those platforms (with -DEBUGGING) NOT_REACHED - * expands to assert(0), which expands to ((0) ? (void)0 : - * __assert(...)), and gcc doesn't know that __assert can never return. */ - return any; } + + /* On some platforms (HP-UX, IA64) gcc emits a warning for this function: + * op.c: In function 'Perl_custom_op_get_field': + * op.c:...: warning: 'any.xop_name' may be used uninitialized in this function [-Wmaybe-uninitialized] + * This is because on those platforms (with -DEBUGGING) NOT_REACHED + * expands to assert(0), which expands to ((0) ? (void)0 : + * __assert(...)), and gcc doesn't know that __assert can never return. */ + return any; } /*