www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - size_t, size_t, wherefore art thou aliased?

reply Gregor Richards <Richards codu.org> writes:
(For the early-modern-English-impaired, "wherefore art thou aliased" 
means "why are you aliased")

In the process of porting GDC to x86_64 (which has actually been 
somewhat successful, but more on that later), I've discovered what I 
consider to be a fairly significant problem.

Because size_t is aliased (and also partially because DDoc follows 
aliases apparently), there is a tendency to use uint instead of size_t, 
and no error or even feedback if you do!

For example, std.socketstream overrides:

size_t readBlock(void* _buffer, size_t size)

with

uint readBlock(void* _buffer, uint size)

Ouch!  Works fine on 32-bit systems, but totally fails on 64-bit 
systems, and the writer has no way of knowing there's a bug until he 
tries to compile it on a 64-bit system!  The biggest problem here is 
with overriding (as in the above example), where it'll override properly 
on 32-bit but improperly on 64-bit systems.

The folks on #d and I have created several possible solutions.

Our original thought was to make size_t (and ptrdiff_t) typedefs instead 
of aliases - this would at least require no change to the language 
proper.  Unfortunately, this makes assigning values to size_t and 
ptrdiff_t obnoxious, since it only implicitly casts one way (not the way 
that's helpful here).

Secondly, size_t and ptrdiff_t could be compiler-defined types, rather 
than aliased types.  This would make the implicit casting come out 
right, but is sort of ugly.

Finally, the preferred option seems to be a sort of weak typedef. 
Basically, this would be a typedef, but with implicit casting both ways. 
  So, [u]ints, [u]longs, size_ts and ptrdiff_ts would all play nicely 
together, but overrides would not be happy if improperly defined.

The most unfortunate thing about this is that there's virtually no way 
for a programmer on a 32-bit system to know when they've ran into a bug 
like this.  Yuck.

  - Gregor Richards
Sep 20 2006
next sibling parent reply "Lionello Lunesu" <lionello lunesu.remove.com> writes:
 Unfortunately, this makes assigning values to size_t and ptrdiff_t 
 obnoxious, since it only implicitly casts one way (not the way that's 
 helpful here).
typedef int test_t; void main(){ test_t x = 2; } works just fine. Am I missing something? L.
Sep 20 2006
parent Gregor Richards <Richards codu.org> writes:
Lionello Lunesu wrote:
 Unfortunately, this makes assigning values to size_t and ptrdiff_t 
 obnoxious, since it only implicitly casts one way (not the way that's 
 helpful here).
typedef int test_t; void main(){ test_t x = 2; } works just fine. Am I missing something? L.
typedef int test_t; int main() { test_t x; int y = 2; x = y; return 0; } Actually, the absolutely precise solution would be a precise reversal of the typedef rules - size_t should accept ints/longs/etc, but ints/longs/etc should not accept size_t. - Gregor Richards
Sep 20 2006
prev sibling next sibling parent Steve Horne <stephenwantshornenospam100 aol.com> writes:
On Wed, 20 Sep 2006 08:15:29 -0700, Gregor Richards
<Richards codu.org> wrote:

The most unfortunate thing about this is that there's virtually no way 
for a programmer on a 32-bit system to know when they've ran into a bug 
like this.  Yuck.
In Visual C++, you get warnings about size issues even when they don't exist. VC++ will complain if it thinks the type you specified might be a 64 bit type in the future, and your using it somewhere 32-bitty for instance. Maybe a similar (optional) compiler warning? The compiler could flag 'this is being treated as an uint32_t/uint64_t but it was originally size_t' and give warnings as needed? -- Remove 'wants' and 'nospam' from e-mail.
Sep 20 2006
prev sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
I think I don't really understand the issue, but I'm gonna throw in my 2 
cents anyway ... even though it might sound pretty stupid:

Wouldn't a versioned alias declaration solve this?

version( X32 )
{
   alias something ...
}
version( X64 )
{
   alias something else ...
}

Gregor Richards wrote:
 (For the early-modern-English-impaired, "wherefore art thou aliased" 
 means "why are you aliased")
 
 In the process of porting GDC to x86_64 (which has actually been 
 somewhat successful, but more on that later), I've discovered what I 
 consider to be a fairly significant problem.
 
 Because size_t is aliased (and also partially because DDoc follows 
 aliases apparently), there is a tendency to use uint instead of size_t, 
 and no error or even feedback if you do!
 
 For example, std.socketstream overrides:
 
 size_t readBlock(void* _buffer, size_t size)
 
 with
 
 uint readBlock(void* _buffer, uint size)
 
 Ouch!  Works fine on 32-bit systems, but totally fails on 64-bit 
 systems, and the writer has no way of knowing there's a bug until he 
 tries to compile it on a 64-bit system!  The biggest problem here is 
 with overriding (as in the above example), where it'll override properly 
 on 32-bit but improperly on 64-bit systems.
 
 The folks on #d and I have created several possible solutions.
 
 Our original thought was to make size_t (and ptrdiff_t) typedefs instead 
 of aliases - this would at least require no change to the language 
 proper.  Unfortunately, this makes assigning values to size_t and 
 ptrdiff_t obnoxious, since it only implicitly casts one way (not the way 
 that's helpful here).
 
 Secondly, size_t and ptrdiff_t could be compiler-defined types, rather 
 than aliased types.  This would make the implicit casting come out 
 right, but is sort of ugly.
 
 Finally, the preferred option seems to be a sort of weak typedef. 
 Basically, this would be a typedef, but with implicit casting both ways. 
  So, [u]ints, [u]longs, size_ts and ptrdiff_ts would all play nicely 
 together, but overrides would not be happy if improperly defined.
 
 The most unfortunate thing about this is that there's virtually no way 
 for a programmer on a 32-bit system to know when they've ran into a bug 
 like this.  Yuck.
 
  - Gregor Richards
Sep 21 2006
parent Frank Benoit <keinfarbton nospam.xyz> writes:
Hasan Aljudy schrieb:
 I think I don't really understand the issue, but I'm gonna throw in my 2
 cents anyway ... even though it might sound pretty stupid:
 
 Wouldn't a versioned alias declaration solve this?
 
 version( X32 )
 {
   alias something ...
 }
 version( X64 )
 {
   alias something else ...
 }
 
I think this is exactly like size_t is defined. And the problem Gregor describes is a result from that.
Sep 23 2006