Community
cancel
Showing results for 
Search instead for 
Did you mean: 
zer0droids
Beginner
179 Views

compilation error with ntohs/htons function with icc under linux

The following code does not compile with icc under linux (tested with a debian-testing and a fedora core 10).

#include 
#include 
#include 
#include 

int main(void)
{
        uint16_t x = 0x1234;
        uint16_t y;

        y = ntohs(x);
        printf("ntohs(%x)=%x\\n", x, y);
        return 0;
}

With gcc it compiles without warning:

$ gcc -Wall -W toto.c

With icc:

$ icc -Wall -Werror-all -w2 toto.c
toto.c(11): error #2259: non-pointer conversion from "int" to "unsigned short" may lose significant bits
        y = ntohs(x);
            ^

compilation aborted for toto.c (code 2)

$ icc -V
Intel C Intel 64 Compiler Professional for applications running on Intel 64, Version 11.1    Build 20100203 Package ID: l_cproc_p_11.1.069
Copyright (C) 1985-2010 Intel Corporation.  All rights reserved.

I tried different kind of casts without success, and I suspect that this error may be a bug. Does someone has an idea about how to solve the issue without removing the "-Wall -Werror-all -w2" options ?

Thanks !

0 Kudos
6 Replies
Om_S_Intel
Employee
179 Views

You can compile it as below:

$ icpc -Wall tstcase.cpp

tstcase.cpp(11): remark #2259: non-pointer conversion from "int" to "unsigned short" may lose significant bits

y = ntohs(x);

You are not able to compile as you are forcing all warnings to error.

zer0droids
Beginner
179 Views

Yes, but why is there a warning ? The prototype of the function is:

uint16_t ntohs(uint16_t netshort);

In my opinion there is no implicit cast in this case.

mecej4
Black Belt
179 Views

Is the prototype in one of the included files? On Suse 11.1, ntohs is defined in , not in
zer0droids
Beginner
179 Views

Yes, I checked that includes .
I also checked that an undeclared prototype triggers an error.
Judith_W_Intel
Employee
179 Views

After preprocessing the file (with -E) I see that the call has been turned into a Gnu statement expression, i.e.:

int main(void)
{
uint16_t x = 0x1234;
uint16_t y;

y = (__extension__ ({ register unsigned short int __v, __x = (x); if (__builtin_constant_p (__x)) __v = ((((__x) >> 8) & 0xff) | (((__x) & 0xff) << 8)); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); __v; }));
printf("ntohs(%x)=%x\n", x, y);
return 0;
}

It looks like ntohs is a macro that is defined as __bswap_16 in netinet/in.h and __bswap_16 is a macro that is expanded in bits/byteswap.h to the expression above. If you turn off optimization (i.e. -O0)then this doesn't happen because __OPTIMIZE__ is not defined.

The remark looks valid to me since __v is an unsigned short and x is an uint16_t. I think this is sort of a bug/problem with the Gnu headers.

Judy

zer0droids
Beginner
179 Views

Hi Judy,

Thank you for your answer. That helped me to find the root cause of the warning.

The code below is equivalent to the original code of my first message, with macros expanded. If I change the definition of __bswap_constant_16() and force the cast in unsigned short (or uint16_t, which is usually the same), there is no warning anymore. See the example below.

#include 

#ifndef FORCE_CAST
/* Swap bytes in 16 bit value.  */
#define __bswap_constant_16(x) \
      (((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
#else
/* Swap bytes in 16 bit value.  */
#define __bswap_constant_16(x) \
      ((unsigned short int)((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))
#endif

int main(void)
{
      unsigned short int x = 0x1234;
      unsigned short int y;

      y = (__extension__
           ({ register unsigned short int __v, __x = (x);
                   if (__builtin_constant_p (__x))
                           __v = __bswap_constant_16 (__x);  /* <<<<< cast warning here */
                   else
                           __asm__ ("rorw $8, %w0"
                                    : "=r" (__v)
                                    : "0" (__x)
                                    : "cc");
                   __v; }));

      printf("ntohs(%x)=%x\n", x, y);
      return 0;
}

Regards, Olivier

Reply