Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent proto warnings #11438

p5pRT opened this issue Jun 13, 2011 · 5 comments

Inconsistent proto warnings #11438

p5pRT opened this issue Jun 13, 2011 · 5 comments


Copy link

p5pRT commented Jun 13, 2011

Migrated from (status was 'rejected')

Searchable as RT92704$

Copy link

p5pRT commented Jun 13, 2011

From @cpansprout

The ‘%s() called too early to check prototype’ does not appear after a require. This inconsistency seems a little strange​:

$ perl -we 'require attributes; attributes​::get(\$_)'

$ perl -we 'attributes​::get(\$_); use attributes'
attributes​::get() called too early to check prototype at -e line 1.

In both cases, the module is loaded after the call has been compiled.

This can cause action at a distance. A script like this happens to work​:

#!perl -w
eval ' my $foo : bar '; # loads, but at run-time
attributes​::get(\$_); # no warning
# ... more code ...

And then the following is added, 200 lines further down​:

my $foo : bar;

Then it starts to warn about the attributes​::get() call. This can be very confusing. I’ve triggered a warning this way with almost every test I’ve added to t/op/attrs.t, only to have to correct it with a subsequent commit.

Is it for backward compatibilty’s sake that ‘require attributes; attributes​::get(\$_)’ doesn’t warn about the prototype?


Site configuration information for perl 5.14.0​:

Configured by sprout at Wed May 11 13​:45​:58 PDT 2011.

Summary of my perl5 (revision 5 version 14 subversion 0) configuration​:
  Snapshot of​: eb70bb4
  osname=darwin, osvers=10.5.0, archname=darwin-thread-multi-2level
  uname='darwin pint.local 10.5.0 darwin kernel version 10.5.0​: fri nov 5 23​:20​:39 pdt 2010; root​:xnu-1504.9.17~1release_i386 i386 '
  config_args='-Dusedevel -de -Duseithreads -Doptimize=-g'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=define, usemultiplicity=define
  useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
  use64bitint=undef, use64bitall=undef, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  cc='cc', ccflags ='-fno-common -DPERL_DARWIN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include',
  cppflags='-fno-common -DPERL_DARWIN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
  ccversion='', gccversion='4.2.1 (Apple Inc. build 5664)', gccosandvers=''
  intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
  ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -fstack-protector -L/usr/local/lib'
  libpth=/usr/local/lib /usr/lib
  libs=-ldbm -ldl -lm -lutil -lc
  perllibs=-ldl -lm -lutil -lc
  libc=/usr/lib/libc.dylib, so=dylib, useshrplib=false, libperl=libperl.a
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
  cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup -L/usr/local/lib -fstack-protector'

Locally applied patches​:

@​INC for perl 5.14.0​:

Environment for perl 5.14.0​:
  LANGUAGE (unset)
  LOGDIR (unset)
  PERL_BADLANG (unset)

Copy link

p5pRT commented Jun 13, 2011


Father Chrysostomos wrote​:

Is it for backward compatibilty'?s sake that "require attributes;
attributes​::get(\$_)" doesn't warn about the prototype?

No, it's an implementation artifact. The mechanism is that during optree
building (actually as part of op checking), if a call is encountered to
a gv op where the GV's CV slot is empty, the gv op gets the OPpEARLY_CV
flag set. Then later in compilation, at peep time, if that flag is
set and the GV now contains a CV that has a prototype, the warning
is generated. So the warning is only generated if the prototype was
declared before completion of compilation of the subroutine/file scope
that includes the dodgy call.

With "require", the module is loaded, and therefore the prototype
declared, at runtime, so it's too late to generate the warning. You can
actually lose the warning even if it is declared at compile time, if it
comes too late. Compare these​:

$ perl -lwe 'foo(1); sub foo($) {} print "run"'
main​::foo() called too early to check prototype at -e line 1.
$ perl -lwe 'sub bar { foo(1); } sub foo($) {} print "run"'

In order to get the warning in all cases, you'd need to mark the GV rather
than the op. Writing to the GV's CV slot would have to trigger a check
of whether there is now a prototype where the GV has previously been used
to compile a sub call that would have used a prototype but didn't have
one available. To get the warning to point at the location of the call,
as it currently does, the GV would have to store a list of such locations.
This is starting to sound expensive.

I'm inclined to class this as "won't fix". I have plans to implement
a stricture pragma that would (within lexical scope) warn or die on
compilation of any call to an undeclared sub. This pragma would catch
all situations that warrant the "too early to check" warning, whether
currently warned about or not. I think this stricture would be a better
approach to the issue than trying to make the existing warning complete.


Copy link

p5pRT commented Jun 13, 2011

The RT System itself - Status changed from 'new' to 'open'

Copy link

p5pRT commented Nov 14, 2017


I wrote​:

I'm inclined to class this as "won't fix". I have plans to implement
a stricture pragma that would (within lexical scope) warn or die on
compilation of any call to an undeclared sub.

I released that stricture pragma a couple of weeks after that, as
Sub​::StrictDecl. Since there's been no opposition to the view that I
expressed, this ticket should now be closed.


Copy link

p5pRT commented Nov 16, 2017

@xsawyerx - Status changed from 'open' to 'rejected'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet

No branches or pull requests

1 participant