Hello Wojciech,

I'm really no gcc expert and, please, correct if I'm wrong. Maybe the
problem lies when gcc is evaluating the
 "| p[2] << 16 | p[3] << 24;"  part. As "<<" has precedence over "|", it is
evaluated before.
At that time, the evaluated expression would be "p[3] << 24" and
the left operator will be u8, which leads to the commented undefined
behavior. With undefined behavior, nothing else matters.
Maybe gcc was only expecting an unsigned 8-bit output and, that's why
it accepted to use 32 bit signed operator. Indeed,
I also believe that the compiler could be a little bit more heuristic, like
opting for unsigned operator when signed and unsigned are possible
and operators are all unsigned.

I'll try this typecast patch for my problem tomorrow.

--- linux-3.3.8/include/./linux/unaligned/le_byteshift.h.old 2013-04-28
03:09:46.220538584 -0300
+++ linux-3.3.8/include/./linux/unaligned/le_byteshift.h 2013-04-28
03:10:54.232538576 -0300
@@ -5,12 +5,12 @@

 static inline u16 __get_unaligned_le16(const u8 *p)
 {
- return p[0] | p[1] << 8;
+ return (u16)p[0] | (u16)p[1] << 8;
 }

 static inline u32 __get_unaligned_le32(const u8 *p)
 {
- return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
+ return (u32)p[0] | (u32)p[1] << 8 | (u32)p[2] << 16 | (u32)p[3] << 24;
 }

 static inline u64 __get_unaligned_le64(const u8 *p)


This might affect other archs that does not have a cpu instruction for
le-be conversion. I also changed the 16 version, as it has
the same undefined behavior problem. However, I think that this would only
trigger a bug if used on 16 processor.
I guess x86 has an cpu instruction (bswap?) and it is not affected at all.

Regards,

---
     Luiz Angelo Daros de Luca, Me.
            [email protected]


2013/4/28 Wojciech Kromer <[email protected]>

>
>  So, as left operand is 8bit, the right operant must not be over 8. Does
> a simple typecast solves it?
>
>  return (u32)((u32)p[0] | (u32)p[1] << 8 | (u32)p[2] << 16 | (u32)p[3] <<
> 24);
>
>
> return (u32)p[0] | (u32)p[1] << 8 | (u32)p[2] << 16 | (u32)p[3] << 24;
> is correct for all compilers, and this version should be used
>
> anyway
>
> return (u32)p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
>
> is fair enough, because in gcc default typecast tights to the left
> expression in maths
>
> and also in gcc this typecast SHOULD default to return type,
> but does not in some versions as we can see here
>
> best regards
>
> _______________________________________________
> openwrt-devel mailing list
> [email protected]
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel
>
>
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to