NSArray
rather dislikes being passed a nil
object as part of its constructor:
UIView *aView;
UIView *aSecondView = [[UIView alloc] init];
NSArray *array = @[aView, aSecondView];
will throw an exception at runtime when array
is created.
Does clang
have any facilities to try and detect this kind of error? For some trivial cases (like the one above: a stack-local variable that's never assigned to), it seems like the sort of problem the static analyzer would hit out of the park.
TL;DR: -Wuninitialized
catches that specific example, __attribute__((nonnull))
for parameters to functions/methods would help catch nil
as argument in general.
For this specific example (variable not specifically initialized), you can use -Wuninitialized
to catch those uses:
○ xcrun clang a.m -F/System/Library/Frameworks -c -o a.o -Wuninitialized
a.m:6:22: warning: variable 'aView' is uninitialized when used here [-Wuninitialized]
NSArray *array = @[aView, aSecondView];
^~~~~
a.m:4:16: note: initialize the variable 'aView' to silence this warning
NSView *aView;// = nil;
^
= nil
1 warning generated.
For passing nullptr
/NULL
/nil
to functions/methods, __attribute__((nonnull))
should work for most cases. Since this is an API provided by Apple, you would need to file a radar and hope they add it.
P.S: Actually, __attribute__((nonnull))
wouldn't “simply work”, in this case (if you initialized aView
to nil
, for example. The @[...]
sequence seems to be creating an array, and calling +[NSArray arrayWithObjects: count:]
, where you would be able to mark the first argument as nonnull
, but not the things pointed to by it. In any case, it should be relatively simple to write a clang pass for the analysis you mention. You should file a radar, since such a pass could avoid lots of time losses.
P.P.S: It seems __attribute__((nonnull))
doesn't propagate much information, which is sad. :-( If you have a function f(type arg __attribute__((nonnull)))
and you pass it a variable which you initialized to nil
and never touched again, it doesn't warn.