Discussion:
[freetds] pointer arithmetic on a pointer to void
Craig A. Berry
2013-10-10 22:47:43 UTC
Permalink
The compiler I'm using (HP C V7.3-020 on OpenVMS IA64 V8.4) doesn't like the fact that we now (as of branch-0_92-611-g7dc0487) try to do arithmetic on a pointer to void:

CC/DECC /DEFINE=(TDS50,"_THREAD_SAFE"=1)/PREFIX=(ALL)/FLOAT=IEEE/IEEE=DENORM/OBJECT=[.SRC.TDS]STREAM.OBJ /NAMES=SHORTENED /DEBUG/NOOPTIMIZE/LIST=[.S
RC.TDS]STREAM/SHOW=(EXPANSION,INCLUDE)/INCLUDE=("./","./include") [.SRC.TDS]STREAM.C

stream->buffer += len;
........^
%CC-W-BADPTRARITH, In this statement, performing pointer arithmetic on a pointer to void or a pointer to function is not allowed. The compiler will treat the type as if it were pointer to char.
at line number 175 in file D0:[craig.freetds-0^.92^.dev^.20131003.src.tds]stream.c;1

According to the Stack Overflow article at <http://stackoverflow.com/questions/3523145/pointer-arithmetic-for-void-pointer-in-c>, MSVC would have the same problem and the consensus there is that this does in fact violate the C99 standard.

Since the compiler is going to treat it like pointer to char anyway, and since what we have now is dubious from a sC standards viewpoint, wouldn't it be better to just make it a pointer to char in the first place, like so:

--- include/freetds/stream.h;-0 2013-10-03 15:19:49 -0500
+++ include/freetds/stream.h 2013-10-03 21:30:57 -0500
@@ -45,7 +45,7 @@ typedef struct tds_output_stream {
* client should not cache buffer and buf_len before a call
* to write as write can change these values.
*/
- void *buffer;
+ char *buffer;
size_t buf_len;
} TDSOUTSTREAM;

[end]

________________________________________
Craig A. Berry
mailto:craigberry at mac.com

"... getting out of a sonnet is much more
difficult than getting in."
Brad Leithauser
James K. Lowden
2013-10-11 00:57:03 UTC
Permalink
On Thu, 10 Oct 2013 17:47:43 -0500
Since what we have now is dubious from a sC standards viewpoint,
wouldn't it be better to just make it a pointer to char in the first
place
Absolutely right on all counts. The only valid uses of void* are

1. compare with NULL
2. convert to char*
3. convert back to the type it points to

In olden times, as I'm sure you remember, the standard library declared
ordinary buffers to be char*, and the compiler never complained if you
happened to send int* (because, say, you're reading ints). With the
introduction of functional prototypes in C89, that was no longer
possible because the compiler would not "convert" int* to char* for
you. So ANSI invented void* to stand in for char*'s old role, albeit
in a more limited form. char* retained its elevated status: anything
could be cast to and from char* in order to gain byte-addressability.

Pointer arithmetic on void* is invalid for the perfectly good reason
that the void type has no size.

The choice between redefining the pointer to char* or casting void* to
char* is one of convenience. If your one-liner makes the compiler
happy, I'd say that's most convenient.

Thanks for pointing it out. I'm surprised it hasn't cropped up
before.

--jkl
Craig A. Berry
2013-10-11 14:54:50 UTC
Permalink
Post by James K. Lowden
Pointer arithmetic on void* is invalid for the perfectly good reason
that the void type has no size.
Indeed.
Post by James K. Lowden
The choice between redefining the pointer to char* or casting void* to
char* is one of convenience. If your one-liner makes the compiler
happy, I'd say that's most convenient.
Seems to to the trick and causes no new test failures here.
Post by James K. Lowden
Thanks for pointing it out. I'm surprised it hasn't cropped up
before.
FWIW, clang and gcc can be made to complain about the same thing by adding -Werror-pointer-arith to CFLAGS.

________________________________________
Craig A. Berry
mailto:craigberry at mac.com

"... getting out of a sonnet is much more
difficult than getting in."
Brad Leithauser
Frediano Ziglio
2013-10-12 13:07:59 UTC
Permalink
Post by Craig A. Berry
Post by James K. Lowden
Pointer arithmetic on void* is invalid for the perfectly good reason
that the void type has no size.
Indeed.
Post by James K. Lowden
The choice between redefining the pointer to char* or casting void* to
char* is one of convenience. If your one-liner makes the compiler
happy, I'd say that's most convenient.
Seems to to the trick and causes no new test failures here.
Post by James K. Lowden
Thanks for pointing it out. I'm surprised it hasn't cropped up
before.
FWIW, clang and gcc can be made to complain about the same thing by adding -Werror-pointer-arith to CFLAGS.
Committed 2 patches, one to add the warning and the other to remove the problem

Frediano

Loading...