ObjC blocks documentation


It seems that capturing arrays is not allowed in Clang Blocks i.e. the following code:

int arr[10];

int* (^bl)() = ^ int*() {return arr;};

fails with:

error: cannot refer to declaration with an array type inside block

I have checked the documentation on Blocks in Clang and some ObjC manual but can’t find anything related to it.

Also the Clang commit history doesn’t provide much information.

Does anyone know why is this restricted? Or could anyone point to good documentation where such things are explained?

Thanks in advance,


It was restricted due to performance implication of capturing the array. Earlier versions of ObjC blocks
captured the array address with this syntax. This was a source of confusion and it was decided to outright ban it.

- Fariborz

This seems like an odd rationale. For example, in C, clang happily accepts this:

struct {
  int arr[10];
} s;
int* (^bl)() = ^ int*() {return s.arr;};

This will generate similarly inefficient code. Indeed, it’s semantically equivalent to Anastasia’s example, yet clang accepts it and is happy to perform the copy.

In C++, it’s even worse. Clang will also accept structs with non-trivial copy constructors. For example, consider this (which clang emits with no warnings):

#include <stdio.h>

struct F
  int x = 42;
  F() {}
  F(const F&o) {
    fprintf(stderr, "Copying!\n");

int main() {
  struct v {
    F arr[1024];
  } s;
  int (^bl)() = ^ int() {return s.arr[10].x;};

This program will print “Copying!\n” 1024 times to standard error (and this is only copying the array to the *stack* - if someone then calls _Block_copy() on bl then you will get another 1024 copy constructor invocations as the blocks runtime copies all of these to the heap).

This is a contrived example, but clang happily accepts blocks that perform implicit copying of objects whose copy constructors perform deep copies, which have overheads *vastly* more than any C array that you might plausible fit on the stack, all without warning.


This seems like an odd rationale. For example, in C, clang happily accepts this:

IIRC, initial implementation of a stand-alone array was by capturing its address.
This was deemed confusing, and misuse of this syntax. Decision was made to disallow that syntax altogether so
people can rewrite their code with array embedded in a stuct/class (which was by then supported). In which case,
they are assumed to knowingly live with the performance hit. This omission can be revisited.

- Fariborz

Thanks for looking into it!

As far as I understand there is no real documentation where this is explained. So we should just rely on what Clang accepts and produces.