Description
h2ph generates code that uses unless (defined(&FOO)) { sub FOO() { ... } } in various places. This code makes no sense and produces incorrect results in some cases (see below).
Steps to Reproduce
Create try.h containing:
#ifndef FOO
#define FOO 0
#endif
#if FOO == 0
#define BAR() 1
#else
#define BAR() 2
#endif
#if BAR() >= 3
#error "we should never get here"
#endif
#undef BAR
#define BAR() 42
Note that it contains an #error directive that is unreachable because no matter what, BAR() is always defined as either 1 or 2 at this point.
Then run:
$ perl -I. -E 'require "try.ph"; say BAR()'
we should never get here at try.ph line 18.
Compilation failed in require at -e line 1.
Expected behavior
42
It fails because the generated try.ph contains:
require '_h2ph_pre.ph';
no warnings qw(redefine misc);
unless(defined(&FOO)) {
eval 'sub FOO () {0;}' unless defined(&FOO);
}
if((defined(&FOO) ? &FOO : undef) == 0) {
eval 'sub BAR () {
eval q(1);
}' unless defined(&BAR);
} else {
eval 'sub BAR () {
eval q(2);
}' unless defined(&BAR);
}
if( &BAR() >= 3) {
die("we should never get here");
}
undef(&BAR) if defined(&BAR);
unless(defined(&BAR)) {
sub BAR () {
eval q(42);
}
}
1;
In particular, the unless(defined(&BAR)) { sub BAR () { eval q(42); } } part makes no sense: sub definitions are processed at compile time (like BEGIN blocks), so this code is functionally identical to sub BAR () { eval q(42); } unless(defined(&BAR)) {}.
The unless block protects nothing, and the BAR symbol is defined before the rest of the file even starts running.
Similarly, the generated _h2ph_pre.ph file in the same directory contains code like:
unless (defined &_FILE_OFFSET_BITS) { sub _FILE_OFFSET_BITS() { 64 } }
This has the same problem, but at least it doesn't break anything because there are no conditionals or redefinitions here. Still, the unless (defined &X) { } blocks are functionally useless and should be removed.
Module: h2ph
Description h2ph generates code that uses
unless (defined(&FOO)) { sub FOO() { ... } }
in various places. This code makes no sense and produces incorrect results in some cases (see below).Steps to Reproduce Create
try.h
containing:Note that it contains an
#error
directive that is unreachable because no matter what,BAR()
is always defined as either1
or2
at this point. Then run:Result:
Expected behavior
It fails because the generated
try.ph
contains:In particular, the
unless(defined(&BAR)) { sub BAR () { eval q(42); } }
part makes no sense:sub
definitions are processed at compile time (likeBEGIN
blocks), so this code is functionally identical tosub BAR () { eval q(42); } unless(defined(&BAR)) {}
. Theunless
block protects nothing, and theBAR
symbol is defined before the rest of the file even starts running.Similarly, the generated
_h2ph_pre.ph
file in the same directory contains code like:This has the same problem, but at least it doesn't break anything because there are no conditionals or redefinitions here. Still, the
unless (defined &X) { }
blocks are functionally useless and should be removed.Perl configuration