]> granicus.if.org Git - clang/commitdiff
-Wobjc-literal-compare: don't warn when comparing against nil.
authorJordan Rose <jordan_rose@apple.com>
Tue, 17 Jul 2012 17:46:48 +0000 (17:46 +0000)
committerJordan Rose <jordan_rose@apple.com>
Tue, 17 Jul 2012 17:46:48 +0000 (17:46 +0000)
Checks against nil often appear as guards in macros, and comparing
Objective-C literals to nil has well-defined behavior (if tautological).

On OS X, 'nil' has not been typed as 'id' since 10.6 (possibly earlier),
so the warning was already not firing, but other runtimes continue to use
((id)0) or some variant. This change accepts comparisons to any null pointer;
to keep it simple, it looks through all casts (not just casts to 'id').

PR13276

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160379 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
test/SemaObjC/objc-literal-comparison.m

index fabd673d1b160674847a15f112f679334206d89d..34fb9d06a7a97c980a6867fa543f2f484311f072 100644 (file)
@@ -6742,10 +6742,24 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) {
 static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
                                           ExprResult &LHS, ExprResult &RHS,
                                           BinaryOperator::Opcode Opc){
-  Expr *Literal = (isObjCObjectLiteral(LHS) ? LHS : RHS).get();
+  Expr *Literal;
+  Expr *Other;
+  if (isObjCObjectLiteral(LHS)) {
+    Literal = LHS.get();
+    Other = RHS.get();
+  } else {
+    Literal = RHS.get();
+    Other = LHS.get();
+  }
+
+  // Don't warn on comparisons against nil.
+  Other = Other->IgnoreParenCasts();
+  if (Other->isNullPointerConstant(S.getASTContext(),
+                                   Expr::NPC_ValueDependentIsNotNull))
+    return;
 
   // This should be kept in sync with warn_objc_literal_comparison.
-  // LK_String should always be last, since it has its own flag.
+  // LK_String should always be last, since it has its own warning flag.
   enum {
     LK_Array,
     LK_Dictionary,
index ea42a176ef03f8f02fc4de181d131c9854495577..f1aa8ecd91e22066f5a8dbfd4d8f8baf457f7b74 100644 (file)
@@ -1,8 +1,10 @@
-// RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare "-Dnil=((id)0)" -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare "-Dnil=(id)0" -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare "-Dnil=0" -verify %s
 
 // (test the warning flag as well)
 
-typedef unsigned char BOOL;
+typedef signed char BOOL;
 
 @interface BaseObject
 + (instancetype)new;
@@ -79,3 +81,16 @@ void testWarningFlags(id obj) {
 
 #pragma clang diagnostic pop
 
+
+void testNilComparison() {
+  // Don't warn when comparing to nil in a macro.
+#define RETURN_IF_NIL(x) if (x == nil || nil == x) return
+  RETURN_IF_NIL(@"");
+  RETURN_IF_NIL(@1);
+  RETURN_IF_NIL(@1.0);
+  RETURN_IF_NIL(@[]);
+  RETURN_IF_NIL(@{});
+  RETURN_IF_NIL(@__objc_yes);
+  RETURN_IF_NIL(@(1+1));
+}
+