Cocoaphony

Stop mutating, evolve

NSLog Ain't Printf in -Wformat

So say you had this code:

printf("%s", 1);
NSLog(@"%s", 1);

And you compiled with -Wformat. You might expect both of these lines to kick out a warning:

Format '%s' expects type 'char *', but argument 2 has type 'int'

You’d be particularly misled when you went and looked at the definition of NSLog():

FOUNDATION_EXPORT void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));

Why look there, doesn’t that look like it should provide format type checking? Oh how foolish. Neither gcc nor clang can actually handle that __NSString__ specifier in a robust way. So the first line above will give a useful warning, but the second one will silently compile and later crash. Exciting, I know. You have been warned.

-Wformat-nonliteral and -Wformat-security do catch dangerous calls like NSLog(foo), so __NSString__ isn’t a complete loss, but it’s a shame we can’t get type checking here.

There’s a good discussion of this at NSLog(…) improper format specifier affects other variables?