Tuesday, December 12, 2006

Yet another C heritage


 Well, in C++ there are namespaces wich provide a better organization of the code and prevents name conflicts. When one stumbles over the first unexpected name resolution one perhaps starts to provide the full qualified identifiers. So you have something like this:

#include <netinet/in.h>

int main() 
{
    ::htons(23);
}

First everything looks fine. Then at some stage of the development process you switch on optimazation and face the following surprise:

$ g++ -O -o foo foo.c 
foo.c: In function `int main()':
foo.c:4: error: parse error before `__extension__'
foo.c:4: error: `__x' undeclared (first use this function)
foo.c:4: error: (Each undeclared identifier is reported only once for each 
   function it appears in.)
   foo.c:4: error: `__v' undeclared (first use this function)
   foo.c: At global scope:
   foo.c:4: error: parse error before `)' token

WTF? Turning on optimization leeds to parse errors? And, furthermore, where is this "__extension__" token anyway?
 
Looking at netinet/in.h shows the problem

extern uint16_t htons (uint16_t __hostshort) __THROW __attribute__ ((__const__));
#ifdef __OPTIMIZE__
# if __BYTE_ORDER == __BIG_ENDIAN
# define htons(x)   (x)
# else
#   define htons(x) __bswap_16 (x)
#endif

htons
is a macro if optimazation is turned on. And the expansion of the macro leads together with the scope operator to the parse error. The "__extension__" token somehow expands from "__bswap_16". So this is another case where well-meant C++ features suffer from the C inheritance which breakes the orthogonality of the language.
  • Not all functions may be scoped - as not everything is a function that looks like one.
  • Name conflicts are not allways avoided by namespaces. You can't name anything htons if you include the netinet/in.h file - at least as long as you don't undef the htons macro in advance....

No comments:

Post a Comment