Clang::SemaCXX/reinterpret-cast.cpp failing

Clang::SemaCXX/reinterpret-cast.cpp fails because on 64bit platforms long is a 32bit int rather than 64bit. I tried using size_t, but that isn’t a builtin type so that doesn’t work.

Clang::SemaCXX/reinterpret-cast.cpp fails because on 64bit platforms long is
a 32bit int rather than 64bit. I tried using size_t, but that isn't a
builtin type so that doesn't work.

Currently we have clang tests running on a mix of 32-bit and 64-bit
platforms with no problems, can you elaborate on the problem you are
seeing?

- Daniel

I agree, it doesn’t fail on linux for me either, but I would expect long to be 32bits rather than 64, so the warnings below make sense.

Sorry that I didn’t send the output:

Ahmed Charles wrote:

I agree, it doesn't fail on linux for me either, but I would expect long to be 32bits rather than 64, so the warnings below make sense.

Sorry that I didn't send the output:

Linux uses LP64. I'd expect this to be an issue only on Windows 64-bit builds, where LLP64 is an issue.

This should be fixed by using intptr_t.

Sean

Linux uses LP64. I’d expect this to be an issue only on Windows 64-bit
builds, where LLP64 is an issue.

Just curious, what’s LP64/LLP64?

This should be fixed by using intptr_t.

Doesn’t seem to work or maybe I did it wrong?

error: ‘error’ diagnostics seen but not expected:
Line 23: use of undeclared identifier ‘intptr_t’
Line 24: use of undeclared identifier ‘l’
Line 25: use of undeclared identifier ‘l’
Line 27: unknown type name ‘intptr_t’
16 diagnostics generated.

void integral_conversion()
{
void vp = reinterpret_cast<void>(testval);
intptr_t l = reinterpret_cast<intptr_t>(vp);
(void)reinterpret_cast<float*>(l);
fnptr fnp = reinterpret_cast(l);
(void)reinterpret_cast(fnp); // expected-error {{cast from pointer to smaller type ‘char’ loses information}}
(void)reinterpret_cast<intptr_t>(fnp);
}

Noticed your checkin, but it fails with this error:

error: ‘error’ diagnostics seen but not expected:
Line 25: cast from pointer to smaller type ‘intptr_t’ (aka ‘int’) loses information
Line 29: cast from pointer to smaller type ‘intptr_t’ (aka ‘int’) loses information
14 diagnostics generated.

Ahmed Charles wrote:

Noticed your checkin, but it fails with this error:

error: 'error' diagnostics seen but not expected:
  Line 25: cast from pointer to smaller type 'intptr_t' (aka 'int') loses information
  Line 29: cast from pointer to smaller type 'intptr_t' (aka 'int') loses information
14 diagnostics generated.

Hmm - that's smells fishy. Is this a 64-bit system? If so, that probably indicates a problem with the definition of intptr_t; it should always be at least as wide as the platform's pointer.

Sean

We define intptr_t as a signed long unless the target overrides it.
I attached a small untested patch that corrects it for Win64.

win64.patch (581 Bytes)

* Ahmed Charles:

Linux uses LP64. I'd expect this to be an issue only on Windows 64-bit
builds, where LLP64 is an issue.

Just curious, what's LP64/LLP64?

"longs and pointers are 64 bits, and the rest is 32 bits or less" and
"long longs and pointers are 64 bits, and the rest (including long) is
32 bits". I think LLP64 is sometimes also called P64. In short, on
Windows, you've got sizeof(long) == 4, no matter if you're running in
32 bit or 64 bit mode. But on most UNIX systems, sizeof(long) ==
sizeof(void *), so it is 8 in 64 bit mode.

“longs and pointers are 64 bits, and the rest is 32 bits or less” and
“long longs and pointers are 64 bits, and the rest (including long) is
32 bits”. I think LLP64 is sometimes also called P64. In short, on
Windows, you’ve got sizeof(long) == 4, no matter if you’re running in
32 bit or 64 bit mode. But on most UNIX systems, sizeof(long) ==
sizeof(void *), so it is 8 in 64 bit mode.

Interesting, I didn’t know that. Thanks. I thought long was always 32 bits, not sure why.

Ahmed Charles wrote:

    "longs and pointers are 64 bits, and the rest is 32 bits or less" and
    "long longs and pointers are 64 bits, and the rest (including long) is
    32 bits". I think LLP64 is sometimes also called P64. In short, on
    Windows, you've got sizeof(long) == 4, no matter if you're running in
    32 bit or 64 bit mode. But on most UNIX systems, sizeof(long) ==
    sizeof(void *), so it is 8 in 64 bit mode.

Interesting, I didn't know that. Thanks. I thought long was always 32 bits, not sure why.

Long is always at least 32 bits, but can be longer if the implementation chooses so (even on 32-bit platforms)

Sean

We define intptr_t as a signed long unless the target overrides it.
I attached a small untested patch that corrects it for Win64.

That patch worked.

These tests should also use intptr_t:

Clang::CodeGenCXX/reinterpret-cast.cpp (562 of 1789)
Clang::SemaCXX/cstyle-cast.cpp (1329 of 1789)
Clang::SemaCXX/functional-cast.cpp (1363 of 1789)

And this test fails for what is probably a similar reason, it should be a unsigned long long, I think.