Hi Sameer, Anastasia,
Do you have any comment on this? Thanks!
Ruiling
Hi Sameer, Anastasia,
Do you have any comment on this? Thanks!
Ruiling
Hello Ruiling,
As far as I can see, the C spec defines the literal “0” as the null pointer, so the following macro seems better:
#define NULL 0
But ignoring the NULL, I think the behaviour might change between OpenCL 1.2 and OpenCL 2.0. In CL12, the “void *” is likely to be a pointer to the private address space. In that case, the comparison is undefined. In CL20, it is likely to be a pointer to the generic address space, and it should be allowed by the frontend. (Because generic address space includes global address space).
I have to use words like “should” and “likely to” because this needs confirmation from language lawyers … the question actually pushes the boundaries of how much I understand the details of OpenCL!
Sameer.
While this is technically true (a null pointer constant is an integer constant expression that evaluates to 0 or such an expression cast to a pointer type), a lot of C code will break on LP64 platforms in exciting and difficult-to-debug ways if the NULL macro does not contain the void* cast. The simplest case is a variadic function that expects a NULL terminator. If this now ends with NULL-defined-as-0, the caller will stick 4 bytes of 0 on the stack and the callee may see a NULL terminator or may see something else, depending on what the adjacent 4 bytes on the stack already contain.
For CHERI, we have made clang special-case pointer casts of zero integer pointer expressions for this reason.
David
Hi Ruiling,
I agree with Sameer, in general in CL2.0 your example will have a comparison between global and generic address spaces, which is allowed.
However, for all CL versions Clang still uses private as default address space of pointers. Some time ago, I’ve sent a patch changing this to comply with CL2.0 rules. My patch wasn’t complete though, because default address space rules are a bit more complex, i.e. program scope pointers should have global address space as default and all other pointers generic. I will see if I can find time to rework this patch.
In the meantime, would this be sufficient for you:
#define NULL 0
This will result in the comparison between a pointer and an integer literal, which is allowed in OpenCL. Also this is the only solution for CL earlier than v2.0.
Regards,
Anastasia
Hi Anastasia,
Thanks for your detailed explanation. Using zero is OK enough to solve the issue.
So, when Clang do semantic check, 0 is interpreted as integer instead of null pointer?
I previously thought Clang treat 0 as null pointer here directly, which it is finally transformed into.
BTW, in C language, NULL may be defined as 0 or (void*)0 in different implementation.
Thanks!
Ruiling
So, when Clang do semantic check, 0 is interpreted as integer instead of null pointer?
Yes, Clang will cast 0 implicitly to the null pointer of the type it is being compare to, so the address space will be taken into account correctly in this case.
If you use (void *)0, Clang will apply default address space to your null pointer (as it’s not provided explicitly). Therefore, pointers will appear to point to different address spaces.
Regards,
Anastasia