Xcode 4.6 Recommended Build Settings

Xcode 4.6 introduced a number of additional compiler warnings that are enabled by default for new projects. Unfortunately the release notes are none too clear about the new options:

LLVM: New compiler warnings to help find subtle behavioral bugs when using automatic release counting (ARC) and weak references.

If you have an existing project you can update to the new recommended build settings from the project page using the “Validate Settings” button:

A diff with the Xcode project.pbxproj file checked into source control reveals the changed settings:

CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;

If you check the build settings for the project you will find three of the new settings in the Apple LLVM compiler 4.2 - Warnings - All languages section:

The remaining setting is in the Apple LLVM compiler 4.2 - Warnings - Objective C section:

A useful tip here to get a detailed description for a build setting is to have the quick help window open in the utilities sidebar when clicking on each setting.

New Project Build Settings

For the purposes of this post I have been using one of the example projects (WorldFacts) from my GitHub CodeExamples repository which was created back in June 2012. From the date I would guess that means I was probably using Xcode 4.3.3. Out of curiosity I compared the build settings after updating this project with a clean new project created with Xcode 4.6. There seems to be one additional compiler warning that is enabled by default for the new Xcode 4.6 project that the validate settings option does not enable for existing projects:

Empty Loop Bodies: Warn about loop bodies that are suspiciously empty. [CLANG_WARN_EMPTY_BODY, -Wempty-body]

It is possible this was already a default for new projects prior to Xcode 4.6 and I have never noticed. It does seem strange though that the validate settings option does not update it for existing projects. Anyway since I would probably like to know about suspiciously empty loop bodies I have also enabled it for the existing project.

What follows is a more detailed description of each of the four new Xcode 4.6 compiler warning build settings. In each case I have included the detailed description from the help documentation for reference.

Implicit Constant Conversions

Warn about implicit conversions of constant values that cause the constant value to change, either through a loss of precision, or entirely in its meaning. [CLANG_WARN_CONSTANT_CONVERSION, -Wconstant-conversion]

This catches problems such as the following where a constant is converted to a type that causes the value to change:

int8_t smallInt = 500;
Implicit conversion from 'int' to 'int8_t' (aka 'signed char') changes value from 500 to -12

NSInteger value = 4294967296;
Implicit conversion from 'long long' to 'NSInteger' (aka 'int') changes value from 4294967296 to 0

Implicit Enum Conversions

Warn about implicit conversions between different kinds of enum values. For example, this can catch issues when using the wrong enum flag as an argument to a function or method. [CLANG_WARN_ENUM_CONVERSION, -Wenum-conversion]

For an example, suppose I have two somewhat similar enum types defined for a class:

typedef enum {
  UYLMagicUser = 0,
  UYLMagicAdmin = 1
} UYLMagicValue;

typedef enum {
  UYLNonMagicUser = 10,
  UYLNonMagicAdmin = 11
} UYLNonMagicValue;

A method that is expecting a UYLMagicValue as an argument:

- (void)doSomeMagic:(UYLMagicValue)magicType {
  //
}

Most of the time Xcode autocompletion will guide you to the right value when calling this method but it is still easy to end up with the following by mistake:

[self doSomeMagic:UYLNonMagicAdmin];

Assuming that I had actually intended to pass UYLMagicAdmin this is going to end in disappointment. With the new compiler warning enabled you get the following:

Implicit conversion from enumeration type 'UYLNonMagicValue' to different enumeration type 'UYLMagicValue'

Incompatible Integer to Pointer Conversion

Warn about implicit conversions between pointers and integers. For example, this can catch issues when one incorrectly intermixes using NSNumber’s and raw integers. [CLANG_WARN_INT_CONVERSION, -Wint-conversion]

This warning works either way when there is an implicit conversion between integers and pointers:

char smallInt = @"1";
Incompatible pointer to integer conversion initializing 'char' with an expression of type 'NSString *'

char *pointer = 1234;
Incompatible integer to pointer conversion initializing 'char *' with an expression of type 'int'

Duplicate Method Definitions

Warn about declaring the same method more than once within the same @interface.

This is a pretty simple one that picks up multiple definitions of the same method in an interface definition:

@interface UYLMyClass ()
- (void)someRandomMethod:(NSString *)name;
// Lots of other stuff...
// and more...
- (void)someRandomMethod:(NSString *)name;
@end
Multiple declarations of method 'someRandomMethod:' found and ignored

One last thing

If you are still using the LLVM-GCC compiler or GDB debugger you should also note the following warning in the Xcode 4.6 release notes and start thinking about adopting LLVM/LLDB in the near future:

DEPRECATED: LLVM-GCC compiler and GDB debugger. Xcode 4.6 is the last release to include the LLVM-GCC compiler and the GDB debugger.

Use the LLVM compiler and the LLDB debugger, and file reports at https://bugreport.apple.com for issues that require the use of LLVM-GCC or GDB.