httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Brian Candler <B.Cand...@pobox.com>
Subject Re: svn commit: r293305 - in /httpd/httpd/branches/2.2.x/modules:
Date Wed, 05 Oct 2005 12:49:15 GMT
On Tue, Oct 04, 2005 at 10:04:14PM +0200, Rdiger Plm wrote:
> >> P.S. The reverse case is sillier, given that the value is moving to a
> >> *larger* type and therefore no data loss can occur:
> >>
> >>     short a;
> >>     long b = a;          // (7) no warning
> >>
> >>     short a;
> >>     void *b = a;         // (8) warns "pointer from integer without a
> >> cast" (ok)
> >>     void *c = (void *)a; // (9) warns "cast to pointer from integer of
> >> different size"
> >>     void *d = (void *)(long)a;  // (10) even more stupid!!!
> >>
> >> Note that having a 'large enough' integral type in case (10) is not good
> >> enough. We need to cast 'a' to an integral type which is *exactly* the
> >> same
> >> size as a void *, to silence this particular warning.
> > 
> > 
> > I agree with your assertion that the code example above IS a gcc bug.
> > This is expected in C++, but the waning (9) above is completely bogus,
> 
> I do not think so. While "a" does fit in "c" from the storage point of view
> converting "c" to a different pointer type e.g. (char *) and dereferencing it
> afterwards most likely leads to SIGBUS or SIGSEGV. So I think a warning is
> justified here.

I disagree. For example, if you take a (char *) and cast it to a (void *),  
and later to an (int *), you will very likely get your SIGBUS error, but the 
compiler won't warn you about it. That's because (void *) is explicitly
meant to be "a pointer to anything you choose". Once you've cast anything
through a void *, you lose any type checking of the thing pointed to.

If you're casting an integer to a pointer, as Apache does: then almost
certainly the pointer isn't going to be usable for deferencing (unless the
value you're casting from happened to hold an integer representation of
another pointer). Furthermore, we're casting to a void *, and you can't
dereference through a void * anyway.

Now, Apache is arguably abusing void * by using it as a data type for
holding arbitrary integers. One assumption is that those integers (like
pid_t) are all no larger than a void *. That's a reasonable assumption on
most platforms (OK, TurboC excepted :-)

Once we agree on that assumption, then there is no need to see a warning
when casting a small integer type into a larger void *, or a void * back
into a smaller integer type. So I say it's the warning that's the problem,
not the code.

> What's your though on AP_PTRINT(n) / AP_INTPTR(p)?

Well, I suppose we're always going to have to have a cast if moving an int
into a void * or vice versa. So:

    pid = AP_PTRINT(ap_hash_get(....))

works as well as anything. I would vote having the second level of cast
though: that is, not

    pid = (pid_t)AP_INTPTR(ap_hash_get(....))

If we're using AP_PTRINT then I think we have to assume the compiler won't
give you a warning if assigning a 64-bit integral value into a 32-bit
variable. That seems to work for gcc, right now. But if it doesn't in
future, we would then need macros like

    AP_PTR_PID_T(n)
    AP_PID_T_PTR(p)

Ergh.

IMO this still boils down to: gcc is giving a code warning which is
inappropriate/irrelevant for the coding style of the Apache project. Hell,
just *document* that this warning is generated all over the place, and that
anyone building the code should ignore it. Then the code can say

    pid = (pid_t)ap_hash_get(...)

which is what was meant all along.

Cheers,

Brian.

Mime
View raw message