As far as I can tell, nobody has yet provided a way to ensure that the argument of ARRAY_SIZE is actually an array.
Found Array-size macro that rejects pointers
Original answer follows:
The macro I use for this is:
#define ASSERT_EXPR(condition,return_value) \
(((char(*)[(condition)?1:-1])0)?(return_value):(return_value))
Principle:
0 is casted to pointer to array (with size of one (condition true) or minus one (condition false, generate error)). This null-pointer is then used as the condition of a ternary operator. Although we know, that it will always only evaluate the third operand (null-pointer means false), the second operand is also return_value -- this way the resulting type is the same as the type of return_value.
Using this, (and the IS_ARRAY from Richard J. Ross III's answer) I can define my safe ARRAY_SIZE macro as follows:
#define IS_ARRAY(arg) __builtin_choose_expr(__builtin_types_compatible_p(typeof(arg[0]) [], typeof(arg)), 1, 0)
#define ARRAY_SIZE(x) ASSERT_EXPR(IS_ARRAY(x), (sizeof(x)/sizeof((x)[0])) )
I didn't manage to get it working with Richard J. Ross III's two other IS_ARRAY variants, but that might be my (or gcc's) fault...