cposixc11implicit-declaration

Apparently erroneous implicit declaration of function warning


I am getting a warning for lstat being implicitly declared, but it should be explicitly declared in the included header.

Compiling the following:

// Standard library
#include <stdio.h>

// Feature test macro
#define _POSIX_C_SOURCE 200809L

// POSIX inclusions
#include <sys/stat.h>

// Function
int main()
{
   struct stat x;
   char* s = "/data/file";
   char* t = "/data/link";
   lstat(s,&x);
   printf( "%i\n", S_ISLNK(x.st_mode) );
   lstat(t,&x);
   printf( "%i\n", S_ISLNK(x.st_mode) );
   return 0;
   }

With the command:

clang -std=c11 test.c

Produces:

test.c:16:4: warning: implicit declaration of function 'lstat' is invalid in C99 [-Wimplicit-function-declaration]
lstat(s,&x);
^
1 warning generated.

Running the output with a regular file at "/data/file" and a link at "/data/link" gives the following output:

0
1

So lstat is obviously being seen by the compiler and used.

If I remove the "-std=c11" option, there is no warning. I get essentially the same thing in gcc, no warning with no option, similar warning with the option.

I am sure I am missing something since both gcc and clang do the same thing, so:

  1. How can I be implicitly defining a function but still accessing the full definition in sys/stat.h?

  2. What can I do to not get this warning?


Solution

  • Feature test macros should be defined before any header is included, including the standard C ones.

    So move

    #define _POSIX_C_SOURCE 200809L
    

    at the beginning of your file.


    If you misplace the feature test macro, the function may not be declared in the header at all. In C89 it is allowed to call an undeclared function. It will be implicitly declared. That is not allowed since C99, but the compilers are choosing to just give a warning about it instead of terminating compilation, and continue to declare the function implicitly.

    Without a prototype default argument promotion will be done on the call arguments to the implicitly-declared function, which for the pointers you pass means that they are passed without any conversion. So the arguments you are giving happen to coincide with the actual parameter types of lstat. So there is no problem, but this is obviously dangerous in general, so don't rely on the implicit declaration.