https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67386

--- Comment #2 from Martin Sebor <msebor at gcc dot gnu.org> ---
Thanks.  I think I may have misinterpreted the C90 rules that describe implicit
function declarations.  The C90 text says:

If the expression that precedes the parenthesized argument list in a function
call consists solely of an identifier, and if no declaration is visible for
this identifier, the identifier is implicitly declared exactly as if, in the
innermost block containing the function call, the declaration

extern int identifier();

appeared.

My reading was that the implicit declaration is intended to be in effect only
for the call to the otherwise undeclared function, but GCC and the other
compilers I've tried let it persist (at least) until the end of the scope and
use it for references to the undeclared function that aren't calls (such as
assigning its address to a pointer).

While trying to better understand both the rule and the implementation (since
it affects the fix for pr66516), I created the following test case and tried it
with GCC and the other compilers.  GCC's output for the test case is below (the
errors are the same with c98, gnu98, c99, gnu99, c11, and gnu11 as arguments to
-std=, and with or without -pedantic).  Clang, however, doesn't issue any
errors, and neither does IBM xlc.  The EDG front end behaves the same as GCC.

I think Clang and IBM xlc are both wrong since the reference to abs on line 8
should clearly be diagnosed.  The C90 words aren't completely clear about where
in the innermost block the extern int identifier(); declaration is supposed to
appear but it stands to reason that it should appear where all other
declarations must appear in C90: before any executable code.  So diagnosing the
reference to abs on line 11 is incorrect because the call to abs(0) on the
following line should introduce an implicit declaration of the function just
before line 11 where its address is taken.

Unless you disagree, I'll close this as NOTABUG and open a new bug for the
incorrect diagnostic on line 11.

$ cat -n t.c && ~/bin/gcc-5.1.0/bin/gcc -c t.c
     1  int (*p)(int);
     2  int i;
     3  
     4  void f0 (void) {
     5      i = abs (0);   // okay, abs implicitly declared in this scope
     6  }
     7  void f1 (void) {
     8      p = abs;       // error, no implicitly declaration in scope
     9  }
    10  void f2 (void) {
    11      p = abs;       // GCC bug?
    12      i = abs (0);   // injects an implicit declaration into the
enclosing block
    13  }
    14  void f3 (void) {
    15      i = abs (0);   // introduces an implicit declaration into scope
    16      p = abs;       // okay, abs implicitly declared above
    17  }
    18  
t.c: In function ‘f0’:
t.c:5:9: warning: implicit declaration of function ‘abs’
[-Wimplicit-function-declaration]
     i = abs (0);
         ^
t.c: In function ‘f1’:
t.c:8:9: error: ‘abs’ undeclared (first use in this function)
     p = abs;
         ^
t.c:8:9: note: each undeclared identifier is reported only once for each
function it appears in
t.c: In function ‘f2’:
t.c:11:9: error: ‘abs’ undeclared (first use in this function)
     p = abs;
         ^

Reply via email to