Xcode “Hard Mode”

Posted by on Mar 29, 2013 in Blog | Tags: , , , , , | No Comments

In 2009, Peter Hosey wrote Warnings I turn on, and why. It remains an excellent explanation of why certain warnings, off by default, are a good idea to use. In it, he mentions the use of “treat warnings as errors” and calls it “hardass mode.”

I’ve been using -Wall on GCC for more years than I can remember, but contrary to its name, -Wall does not actually turn on all warnings. This is especially true today, now that Apple has transitioned Mac and iOS developers over to Clang, which offers a much larger set of warnings. As part of Xcode 4.4, Apple introduced -Weverything, which, true to its name, really does turn on every warning the compiler can generate. What makes this flag great is that when Apple ships a new version of Clang with new warnings, you can see their effect right away, without having to know what the new warnings are and turn them on explicitly.

Coupled with -Werror, this is a great combination to stop potential bugs from creeping into your code. I turn both of these flags on as soon as I start a new project.

Unfortunately, Clang seems to include some warnings that cross the line from useful to nit-picky. Approaching this from the opposite direction from Peter, here I present my own version of Xcode Hard Mode:

Warnings I turn off, and why

Each of these warnings may be turned off by inserting no- between the W and the specific warning flag (e.g., -Wno-pedantic). I typically put them in Other Warning Flags, under Apple LLVM compiler – Warnings – All languages.


The -pedantic flag has long existed as a way to enforce strict ISO C requirements. ISO C requires diagnostics for certain constructs, which are, at least for the style of code I write, extremely rare. Lately, however, I’ve been making more regular use of NS_ENUM after the write-up on NSHipster. Unfortunately, Apple’s macro violates ISO C and triggers a warning.


Since the introduction of properties in Objective-C 2.0, Apple has continued to refine them. Today, as long as you’re OK with Apple’s naming convention, you don’t need a backing instance variable or @synthesize. Skipping the @synthesize, however, generates a warning.


Most classes have a least a little bit of internal state. I generally put this state in property-less instance variables, but apparently that’s bad. I’d be on board with this one if it only warned about directly accessing the ivar behind a property, but as of Xcode 4.6.1, that isn’t how it works.


This one surprised me the other day with its depth of ridiculousness. This code is fine:

@property (weak) IBOutlet UILabel *label;
// in a method:
label.text = @"hello, world";

While Clang thinks this code is dangerous:

@property (weak) IBOutlet UILabel *label;
// again, in a method:
if (someFlag)
    label.text = @"hello, world";
    label.text = @"goodbye, world";

That’s right: referencing a weak property twice in one method crosses the line for Clang, because the property might unexpectedly become nil.

Occasional Annoyances

Some warnings work most of the time, but once in a while, or in certain projects, don’t make any sense. For the once-in-a-while case, it’s useful to disable the warning for only a section of code, rather than the entire project:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wwhatever"
// ...
#pragma clang diagnostic pop


This one deals with code cleanliness, much like -Wunused-function, -Wunused-label, -Wunused-parameter, -Wunused-value and -Wunused-variable. As Peter said, code you don’t have is code you don’t have to debug.

If you #define something, but never use it, this warning flags it. Macros defined in libraries (intended for users of the library and not the library itself) or debugging macros are common and useful, and it might be better to keep those around at the expense of others that you could otherwise get rid of.


I’ll update this post as I run across other overzealous warnings. Suggestions or comments? Get in touch with me on App.net or Twitter (@sjmadsen on both).