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,
-// 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;
#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));
+}
+