Xcodeのコンパイル設定で、ワーニングとして検知できる項目をまとめてみました。
Future Workshops: Xcode Warningsを参考に作成。
この設定を上手く使えばレビュー時に指摘する/されることも減らせるはず!
Apple LLVM 7.0 - Warnings - Warning Policies で定義している項目
Treat Warnings as Errors (GCC_TREAT_WARNINGS_AS_ERRORS)
ビルド時に出た警告をエラーとして扱う。
Apple LLVM 7.0 - Warnings - All Languages で定義している項目
Check Switch Statements (GCC_WARN_CHECK_SWITCH_STATEMENTS)
Switch文の条件にEnumを使っている時、case句でEnumの項目が網羅されていない時に警告を出す。
typedef enum {
swift = 0,
objectiveC
} Languages;
- (NSInteger)testFunc:(Languages)num
{
int ret = 0;
switch (num) {
case swift:
ret = 100;
break;
}
return ret;
} // Enumeration value 'objectiveC' not handled in switchという警告が出る
Deprecated Functions (GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS)
deprecated化された関数を使っている時、警告を出す。
Empty Loop Bodies (CLANG_WARN_EMPTY_BODY)
ループ内で処理が何も行われないような場合、警告を出す。
Hidden Local Variables (GCC_WARN_SHADOW)
ローカル変数の名前が以下のもののいずれかと一致する場合、警告を出す。
* 別なローカル変数
* 引数
* グローバル変数
* 組み込み関数
-(void)someMethod {
NSInteger index; // Cのindex()と同じ名前なので、警告が出る
}
Implicit Boolean Conversions (CLANG_WARN_BOOL_CONVERSION)
指定した変数がbooleanに変換されるのか疑わしい場合に警告を出す。
BOOL foo() {
// some implementations...
}
-(void)someMethod {
if (foo) { // fooがBOOL型の変数なのか関数名を指してるのか判断できない
}
}
Implicit Constant Conversions (CLANG_WARN_CONSTANT_CONVERSION)
数値リテラルを変数に代入する時、値が変わってしまう場合や精度が落ちてしまうような場合に警告を出す。
Implicit Conversion to 32 Bit Type (GCC_WARN_64_TO_32_BIT_CONVERSION)
64bitの型から32bitの型に暗黙的に変換するような場合に警告を出す。
Implicit Enum Conversions (CLANG_WARN_ENUM_CONVERSION)
typedef enum
{
SAPUser = 0,
SAPAdmin = 1,
} SAPUserRoll;
typedef enum
{
SAPNonUser = 2,
SAPNonAdmin = 3,
} SAPNonUserRoll;
-(void)doSomeStuff:(SAPUserRoll)roll;
-(void)someMethod {
[self doSomeStuff:SAPNonUser]; // ここで警告が出る
}
Incompatible Integer to Pointer Conversion (CLANG_WARN_INT_CONVERSION)
ポインタとintegerの変数を暗黙的に変換している場合に警告を出す。
NSInteger val = @1; // integer型の変数にポインタを代入しようとしているので警告が出る
NSNumber * num = 1234; // ポインタ型の変数にintegerを代入しようとしているので警告が出る
Initializer Not Fully Bracketed (GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED)
配列や構造体の初期化時に、大カッコで要素やメンバに代入する値が指定されていない場合に警告を出す。
int bracketed[2][2] = { { 0, 1 }, { 2, 3 } }; // 要素数2の配列が、それぞれ初期化されていることを示す書き方になっているので警告は出ない
int notBracketed[2][2] = { 0, 1, 2, 3 }; // 要素数4の配列を初期化する書き方になっているので、警告が出る
// CGRectはCGPointとCGSizeをメンバに持っている
CGRect bracketed = { { 0.0f, 0.0f }, { 640.0f, 480.0f } }; // CGPointとCGSizeのそれぞれを初期化することを示しているので、警告は出ない
CGRect notBracketed = { 0.0f, 0.0f, 640.0f, 480.0f }; // 警告が出る
Mismatched return type (GCC_WARN_ABOUT_RETURN_TYPE)
シグネチャの戻り値の型と実際に返す値の型が異なっている場合に警告を出す。
- (NSInteger)count:(NSInteger)condition
{
if (condition == 0) {
return 1;
} else {
return; // NSInteger型の値を返すべきと警告が出る
}
}
Missing Braces and Parentheses (CLANG_WARN_MISSING_PARENTHESES)
if文のカッコ付けが行われていないため、どのようにif-elseが評価されるのか明確でない場合に警告を出す。
- (void)someMethod {
if (YES)
if (YES)
NSLog(@"true");
else // どちらのifに対するelseなのかわからないので警告が出る
NSLog(@"FALSE");
}
Missing Fields in Structure Initializers (GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS)
構造体の初期化時、メンバ名を指定して初期化しないと警告を出す。
- (void)someMethod {
struct s { int f, g, h; };
struct s x = { 3, 4 }; // 警告が出る
struct s y = { .f = 3, .g = 4}; // 警告は出ない
}
Missing Newline At End Of File (GCC_WARN_ABOUT_MISSING_NEWLINE)
ソースファイルの最終行が空行で終わっていない場合に警告を出す。
C++03までは、ソースファイルの最終行が空行でない場合の振る舞いが未定義だったため、挿入する必要があった。
ただ、C++11以降は空行でなくても良いように変わった。
参考: Stackoverflow:“No newline at end of file” compiler warning
Sign Comparison (GCC_WARN_SIGN_COMPARE)
符号付きの数値と符号なしの数値を比較する場合に警告を出す。
Typecheck Calls to printf/scanf (GCC_WARN_TYPECHECK_CALLS_TO_PRINTF)
printfやscanf、NSLog等のフォーマット付き文字列で引数の数が一致しない場合に警告を出す。
Unused Functions (GCC_WARN_UNUSED_FUNCTION)
外部に宣言しているが、呼びだされていないstatic関数がある場合に警告を出す。
インラインのstatic関数は対象外。
Unused labels, values and variables (GCC_WARN_UNUSED_[LABEL|VALUE|PARAMETER])
宣言したラベルや変数、引数などが使われていない場合に警告を出す。
Apple LLVM 7.0 - Warnings - Objective C で定義している項目
Direct usage of 'isa' (CLANG_WARN_DIRECT_OBJC_ISA_USAGE)
iOS7以降、isa
ポインタには直接アクセスできなくなった。そのため、警告として扱われるようになった。
(arm64化に伴って、isa
ポインタはdeprecated化されている)
こちらも参考: Converting Your App to a 64-Bit Binary
Duplicate Method Definitions (CLANG_WARN_DUPLICATE_METHOD_MATCH)
インタフェース宣言の中で同じメソッド宣言がある場合、警告として扱う。
Overriding deprecated Objective-C methods (CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS)
deprecated化されたObjective-Cのメソッドをオーバーライドしている場合、警告として扱う。
Deployment Targetで指定したバージョンを元に、deprecatedな扱いか判定している模様。
// iOS8以降、deprecated化されたメソッド。
// Deployment Targetが8.0の場合、警告が出されるが
// 7.0の場合、警告は出ない。
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
}
Undeclared Selector (GCC_WARN_UNDECLARED_SELECTOR)
@selector(...)
で、未定義なメソッド名を指定した場合に警告を出す。
KVOやKVC、KVV等を使っている場合や、マクロで @selector()
を使うような場合でも警告を出してくれる模様。
Unintentional root class (CLANG_WARN_OBJC_ROOT_CLASS)
NSObject
を継承していないクラスを継承してしまった場合に警告を出す。
Apple LLVM 7.0 - Warnings - Objective C and ARCで定義している項目
Implicit retain of 'self' within blocks (CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF)
ブロック内で暗黙的に self
を参照している場合に警告を出す。
dispatch_async(dispatch_get_main_queue(), ^{
_someIvar = @"fooBar"; // ivarの参照は暗黙的にselfを指している
};
Repeatedly using a __weak reference (CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK)
強参照に紐付いていない弱参照を何度も繰り返し使うような場合に警告を出す。
typeof(self) __weak zelf = self;
[UIView animateWithDuration:duration
animations:^{
zelf.constraint.constant = constraintConstant; // このブロック内では警告として通知される
[zelf.view layoutIfNeeded]; // 何度も呼び出される恐れがあるから?
}
completion:^(BOOL finished) {
zelf.toolbar.hidden = #hidden; // ここでは警告が発生しない。完了した時だけ呼び出されるから?
}];
Implicit ownership types on out parameters (CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE)
Cによくある、メソッドの実行結果が引数に格納されるようなメソッドの場合、所有権がどこにあるのか明確でないので警告が出る。
- (void)someMethod:(NSError **)error // ここで警告が出る
{
// some implementations...
}
- (void *)someMethod:(NSError * __autoreleasing *)error // __autoreleasingを明示的に指定すると警告は出ない
{
// some implementations...
}
Using _bridge Casts Outside of ARC (CLANG_WARN__ARC_BRIDGE_CAST_NONARC)
ARCの管理外の場所で__bridgeキャストした場合に警告する。
ARCと非ARCのソースが混在しているプロジェクトなら有効そう。
デフォルトでYESが設定されている。