I was investigating porting some code from older C++ to a more modern C++ version (e.g. C++ 11 or higher). And then I noticed some networking code not compiling when I added the compiler flag -std=c++11
Simplest MVCE example. I'm on the latest Cygwin (literally installed today). g++ --version
indicates version 7.3.0.
Take the following source file stripped down to almost nothing, but enough to show the issue I am about to explain.
#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
int some_networking_code()
{
addrinfo* addr = NULL;
int flags = AI_NUMERICHOST;
return 0;
}
On a fresh install of Cygwin, the following command works just fine:
g++ foo.cpp -c
But now switch to compiling with C++11.
g++ foo.cpp -c -std=c++11
And the resulting compiler output is:
foo.cpp: In function ‘int some_networking_code()’:
foo.cpp:8:4: error: ‘addrinfo’ was not declared in this scope
addrinfo* addr = NULL;
^~~~~~~~
foo.cpp:8:4: note: suggested alternative: ‘addr_t’
addrinfo* addr = NULL;
^~~~~~~~
addr_t
foo.cpp:8:14: error: ‘addr’ was not declared in this scope
addrinfo* addr = NULL;
^~~~
foo.cpp:8:14: note: suggested alternative: ‘addr_t’
addrinfo* addr = NULL;
^~~~
addr_t
foo.cpp:9:16: error: ‘AI_NUMERICHOST’ was not declared in this scope
int flags = AI_NUMERICHOST;
^~~~~~~~~~~~~~
Debugging this, I take a peek at /usr/include/netdb.h
and I see that the definition for addrinfo
expects a macro called __POSIX_VISIBLE to be greater than or equal to 200112
. There definition for AI_NUMERICONLY is wrapped within a similar block.
#if __POSIX_VISIBLE >= 200112 && !defined(__INSIDE_CYGWIN_NET__)
struct addrinfo {
int ai_flags; /* input flags */
… <deleted for brevity>
#endif
Using the -dM -E
switches, we can ask the compiler for what macros it's pulling in and filter to the POSIX_VISIBLE
$ g++ foo.cpp -c -dM -E | grep POSIX_VIS
#define __POSIX_VISIBLE 200809
Ok, that looks correct for traditional C++. Let's inspect that for C++11 building:
$ g++ foo.cpp -c -std=c++11 -dM -E | grep POSIX_VIS
#define __POSIX_VISIBLE 0
__POSIX_VISIBLE
is defined to be 0. And that explains why we have the errors above.
It appears that POSIX_VISIBLE
is getting defined by the header file at /usr/include/sys/features.h
based on other defined macros. But that's where I start to get confused.
Is this a bug in the Cygwin distro or its header files? The way the compiler was built? Or something else? What's the appropriate workaround that won't impact building on Linux, Mac, BSD, and everywhere else?