There is an issue with taking an address of captured variables, because captures can be put in different locations depending on the vendor implementation (and therefore they are passed as generic AS pointer to the block).
The physical location for the captures can be:
(a) in case the block is called as a lambda function the captures are put on the stack - in the private AS.
(b) in case the block is used in enqueue it depends on the vendor implementation to put the captured content in the memory accessible for the enqueued kernels. In general case global memory can be used which is accessible everywhere.
Example:
void foo(){ int a; void (^bl)(void) = ^(void) { private int* b = &a; // a here is not the same object as a in foo }
Currently Clang hits unreachable due to bitcast of generic to private AS pointer because the original location of a is on the stack but the location of the captures is in generic AS.
This patch disallows taking address of captures because the physical address space can be different depending on the block use cases and vendor implementations.
An alternative approached could be (in case we want to allow this code) to assume captures are located in the generic AS implicitly. However, in this case programmers should be advised that erroneous AS casts can occur further that can't be diagnosed by the frontend (i.e. if capture address is used further in the operations of a different address space to where the captures physical location is).
Example:
void foo(){ int a; void (^bl)(void) = ^(void) { local int* b = (local int*)&a; //valid cast of implicitly generic to local but &a will be located in private or global AS for the 2 uses below } b(); enqueue_kernel(..., b) }
@sam, @Alexey, does it make sense taking this route?
PS, this patch also contains a minor clean up - removal of duplicate diagnostic for taking an address of a function.