This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: Infinite loop in dcraw with current GCC versions
- From: dcoffin at shell dot cybercom dot net
- To: Manuel López-Ibáñez <lopezibanez at gmail dot com>
- Cc: "gcc-help at gcc dot gnu dot org" <gcc-help at gcc dot gnu dot org>, Conchúr Navid <conchur at web dot de>, Sven Eckelmann <sven at narfation dot org>, René Rebe ExactCODE <rene at exactcode dot com>
- Date: Sun, 1 Mar 2015 15:03:20 -0500
- Subject: Re: Infinite loop in dcraw with current GCC versions
- Authentication-results: sourceware.org; auth=none
- References: <CAESRpQDZs=EZTAj7bO5Dn8d=M8p8MuN7_s__XNatnL2BWgs9wA at mail dot gmail dot com> <CAESRpQBx7V=O-pH5Ckvt=XpJHYyEwCyZGz1HQTByqdKftQC0MQ at mail dot gmail dot com> <20150227190206 dot GA6175 at shell dot cybercom dot net> <CAESRpQCCWVQGeWMByFFiX6MLoA-VxJ3AAp5u99VdOy7h8SsgQg at mail dot gmail dot com> <20150227204552 dot GA8916 at shell dot cybercom dot net> <CAESRpQAbO-6Zy3FBvR56NDiAGJg8CZYtSTUPLR5jud0baNHKHg at mail dot gmail dot com>
I fixed all the "undefined behavior" warnings with
typecasts, but I'm still getting array-bounds warnings
with manifestly correct code. E.g. when blend_highlights()
uses the global variable "colors":
static const float trans[2][4][4] = { ... }
...
if ((unsigned) (colors-3) > 1) return;
...
lab[i][c] += trans[colors-3][c][j] * cam[i][j];
How could "colors-3" be out of bounds? I just verified
that it's either 0 or 1, and if I hard-code 0 or 1 the warning
goes away.
Dave Coffin 3/1/2015
On Sat, Feb 28, 2015 at 05:27:01PM +0100, Manuel López-Ibáñez wrote:
> On 27 February 2015 at 21:45, <dcoffin@shell.cybercom.net> wrote:
> > Hi Manuel,
> >
> > Yes, I know that cam_xyz[] would have to be declared
> > differently for *(cam_xyz + (i)*3 + (j)) to work, but it's
> > all the same at the hardware level.
> >
> > If arrays are no longer pointers, but some sort of
> > abstract array-type, does ISO C allow them to be cast back
> > into pointers? Something like:
> >
> > ((double *)(cam_xyz[0]))[j] = table[i].trans[j] / 10000.0;
>
> cam_xyz[0] is type 'double [3]', thus I don't think you should cast it
> to 'double *', but in this respect I am just going by intuition, not
> by an actual reference to the standard. On the other hand,
> &cam_xyz[0][0] should have type 'double *', and the standard does say
> that the data is contiguously allocated, yet the c-faq says that
> ((double *)(&cam_xyz[0][0]))[j] "is not in strict conformance with the
> ANSI C Standard; according to an official interpretation"
> (http://c-faq.com/aryptr/ary2dfunc2.html), although without a
> reference to the standard, I have no idea what that means. In any
> case, I would be very wary of what anyone says unless they can really
> back it up with quotes from the standard.
>
> Unfortunately, it seems that, at least GCC 4.8.2, generates different
> code if you use ((double *)(&cam_xyz[0][0]))[j] and one for-loop or if
> you use cam_xyz[i][j] and two for-loops. If the former is faster and
> valid, this really is a missed optimization bug worth reporting.
>
> Cheers,
>
> Manuel.
>
>
>
>
>
>
>
>
>
>
> >
> > Dave Coffin 2/27/2015
> >
> > On Fri, Feb 27, 2015 at 09:08:50PM +0100, Manuel López-Ibáñez wrote:
> >> On 27 February 2015 at 20:02, <dcoffin@shell.cybercom.net> wrote:
> >> > Manuel,
> >> >
> >> > There is no "undefined behavior" here. K&R defined it
> >> > very clearly: Arrays are pointers, and square brackets are
> >> > syntactic sugar for pointer arithmetic and dereferencing:
> >> >
> >> > cam_xyz[i][j] vs. *(cam_xyz + (i)*3 + (j))
> >>
> >> Unfortunately, this is simply not true for ISO C, which is the
> >> language that most compilers implement nowadays. And it is easy to
> >> check for yourself:
> >>
> >> test.c:445:27: error: incompatible types when assigning to type
> >> 'double[3]' from type 'double'
> >> *(cam_xyz + (0)*3 + (j)) = table[i].trans[j] / 10000.0;
> >> ^
> >>
> >> See also the first answer to
> >> http://stackoverflow.com/questions/25139579/2d-array-indexing-undefined-behavior,
> >> which seems correct, AFAIU.
> >>
> >> Neither can you do: **(cam_xyz + (0)*3 + (j)), because cam_xyz has
> >> type 'double (*)[3]' thus **(cam_xyz + 2) is referencing
> >> cam_xyz[2][0].
> >>
> >> Cheers,
> >>
> >> Manuel.