Index: lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp +++ lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp @@ -69,18 +69,21 @@ const Stmt *Conv = Result.Nodes.getNodeAs("conv"); assert(Conv); - const Expr *Osboolean = Result.Nodes.getNodeAs("osboolean"); - const Expr *Nsnumber = Result.Nodes.getNodeAs("nsnumber"); - bool IsObjC = (bool)Nsnumber; - const Expr *Obj = IsObjC ? Nsnumber : Osboolean; + const Expr *ConvertedCObject = Result.Nodes.getNodeAs("c_object"); + const Expr *ConvertedCppObject = Result.Nodes.getNodeAs("cpp_object"); + const Expr *ConvertedObjCObject = Result.Nodes.getNodeAs("objc_object"); + bool IsCpp = (ConvertedCppObject != nullptr); + bool IsObjC = (ConvertedObjCObject != nullptr); + const Expr *Obj = IsObjC ? ConvertedObjCObject + : IsCpp ? ConvertedCppObject + : ConvertedCObject; assert(Obj); ASTContext &ACtx = ADC->getASTContext(); if (const Expr *CheckIfNull = Result.Nodes.getNodeAs("check_if_null")) { - // We consider NULL to be a pointer, even if it is defined as a plain 0. - // FIXME: Introduce a matcher to implement this logic? + // FIXME: Introduce an AST matcher to implement the macro-related logic? SourceLocation Loc = CheckIfNull->getLocStart(); if (Loc.isMacroID()) { StringRef MacroName = Lexer::getImmediateMacroName( @@ -104,26 +107,31 @@ llvm::SmallString<64> Msg; llvm::raw_svector_ostream OS(Msg); - OS << "Converting '" - << Obj->getType().getCanonicalType().getUnqualifiedType().getAsString() - << "' to a plain "; + + // Remove ObjC ARC qualifiers. + QualType ObjT = Obj->getType().getUnqualifiedType(); + + OS << "Converting '" << ObjT.getAsString() << "' pointer to a "; if (Result.Nodes.getNodeAs("int_type") != nullptr) - OS << "integer value"; + OS << "plain integer value"; else if (Result.Nodes.getNodeAs("objc_bool_type") != nullptr) - OS << "BOOL value"; + OS << "plain BOOL value"; else if (Result.Nodes.getNodeAs("cpp_bool_type") != nullptr) - OS << "bool value"; + OS << "plain bool value"; else - OS << "boolean value for branching"; + OS << "branch condition"; if (IsPedanticMatch) { if (IsObjC) { - OS << "; please compare the pointer to nil instead " - "to suppress this warning"; + OS << "; instead, compare the pointer to nil " + "or take the encapsulated scalar value"; + } else if (IsCpp) { + OS << "; instead, compare the pointer to nullptr " + "or take the encapsulated scalar value"; } else { - OS << "; please compare the pointer to NULL or nullptr instead " - "to suppress this warning"; + OS << "; instead, compare the pointer to NULL " + "or take the encapsulated scalar value"; } } else { OS << "; pointer value is being used instead"; @@ -139,107 +147,130 @@ void NumberObjectConversionChecker::checkASTCodeBody(const Decl *D, AnalysisManager &AM, BugReporter &BR) const { - MatchFinder F; - Callback CB(this, BR, AM.getAnalysisDeclContext(D)); - - auto OSBooleanExprM = + // Currently this matches CoreFoundation opaque pointer typedefs. + auto CSuspiciousNumberObjectExprM = + expr(ignoringParenImpCasts( + expr(hasType( + typedefType(hasDeclaration(anyOf( + typedefDecl(hasName("CFNumberRef")), + typedefDecl(hasName("CFBooleanRef"))))))) + .bind("c_object"))); + + // Currently this matches XNU kernel number-object pointers. + auto CppSuspiciousNumberObjectExprM = expr(ignoringParenImpCasts( expr(hasType(hasCanonicalType( pointerType(pointee(hasCanonicalType( recordType(hasDeclaration( - cxxRecordDecl(hasName( - "OSBoolean")))))))))).bind("osboolean"))); - - auto NSNumberExprM = - expr(ignoringParenImpCasts(expr(hasType(hasCanonicalType( - objcObjectPointerType(pointee( - qualType(hasCanonicalType( - qualType(hasDeclaration( - objcInterfaceDecl(hasName( - "NSNumber"))))))))))).bind("nsnumber"))); - - auto SuspiciousExprM = - anyOf(OSBooleanExprM, NSNumberExprM); + anyOf( + cxxRecordDecl(hasName("OSBoolean")), + cxxRecordDecl(hasName("OSNumber"))))))))))) + .bind("cpp_object"))); - auto AnotherNSNumberExprM = - expr(equalsBoundNode("nsnumber")); + // Currently this matches NeXTSTEP number objects. + auto ObjCSuspiciousNumberObjectExprM = + expr(ignoringParenImpCasts( + expr(hasType(hasCanonicalType( + objcObjectPointerType(pointee( + qualType(hasCanonicalType( + qualType(hasDeclaration( + objcInterfaceDecl(hasName("NSNumber"))))))))))) + .bind("objc_object"))); + + auto SuspiciousNumberObjectExprM = anyOf( + CSuspiciousNumberObjectExprM, + CppSuspiciousNumberObjectExprM, + ObjCSuspiciousNumberObjectExprM); + + // Useful for predicates like "Unless we've seen the same object elsewhere". + auto AnotherSuspiciousNumberObjectExprM = + expr(anyOf( + equalsBoundNode("c_object"), + equalsBoundNode("objc_object"), + equalsBoundNode("cpp_object"))); // The .bind here is in order to compose the error message more accurately. - auto ObjCBooleanTypeM = + auto ObjCSuspiciousScalarBooleanTypeM = qualType(typedefType(hasDeclaration( typedefDecl(hasName("BOOL"))))).bind("objc_bool_type"); // The .bind here is in order to compose the error message more accurately. - auto AnyBooleanTypeM = + auto SuspiciousScalarBooleanTypeM = qualType(anyOf(qualType(booleanType()).bind("cpp_bool_type"), - ObjCBooleanTypeM)); - + ObjCSuspiciousScalarBooleanTypeM)); // The .bind here is in order to compose the error message more accurately. - auto AnyNumberTypeM = + // Also avoid intptr_t and uintptr_t because they were specifically created + // for storing pointers. + auto SuspiciousScalarNumberTypeM = qualType(hasCanonicalType(isInteger()), unless(typedefType(hasDeclaration( typedefDecl(matchesName("^::u?intptr_t$")))))) .bind("int_type"); - auto AnyBooleanOrNumberTypeM = - qualType(anyOf(AnyBooleanTypeM, AnyNumberTypeM)); + auto SuspiciousScalarTypeM = + qualType(anyOf(SuspiciousScalarBooleanTypeM, + SuspiciousScalarNumberTypeM)); - auto AnyBooleanOrNumberExprM = - expr(ignoringParenImpCasts(expr(hasType(AnyBooleanOrNumberTypeM)))); + auto SuspiciousScalarExprM = + expr(ignoringParenImpCasts(expr(hasType(SuspiciousScalarTypeM)))); auto ConversionThroughAssignmentM = binaryOperator(hasOperatorName("="), - hasLHS(AnyBooleanOrNumberExprM), - hasRHS(SuspiciousExprM)); + hasLHS(SuspiciousScalarExprM), + hasRHS(SuspiciousNumberObjectExprM)); auto ConversionThroughBranchingM = - ifStmt(hasCondition(SuspiciousExprM)) + ifStmt(hasCondition(SuspiciousNumberObjectExprM)) .bind("pedantic"); auto ConversionThroughCallM = - callExpr(hasAnyArgument(allOf(hasType(AnyBooleanOrNumberTypeM), - ignoringParenImpCasts(SuspiciousExprM)))); + callExpr(hasAnyArgument(allOf(hasType(SuspiciousScalarTypeM), + ignoringParenImpCasts( + SuspiciousNumberObjectExprM)))); // We bind "check_if_null" to modify the warning message // in case it was intended to compare a pointer to 0 with a relatively-ok // construct "x == 0" or "x != 0". auto ConversionThroughEquivalenceM = binaryOperator(anyOf(hasOperatorName("=="), hasOperatorName("!=")), - hasEitherOperand(SuspiciousExprM), - hasEitherOperand(AnyBooleanOrNumberExprM + hasEitherOperand(SuspiciousNumberObjectExprM), + hasEitherOperand(SuspiciousScalarExprM .bind("check_if_null"))); auto ConversionThroughComparisonM = binaryOperator(anyOf(hasOperatorName(">="), hasOperatorName(">"), hasOperatorName("<="), hasOperatorName("<")), - hasEitherOperand(SuspiciousExprM), - hasEitherOperand(AnyBooleanOrNumberExprM)); + hasEitherOperand(SuspiciousNumberObjectExprM), + hasEitherOperand(SuspiciousScalarExprM)); auto ConversionThroughConditionalOperatorM = conditionalOperator( - hasCondition(SuspiciousExprM), - unless(hasTrueExpression(hasDescendant(AnotherNSNumberExprM))), - unless(hasFalseExpression(hasDescendant(AnotherNSNumberExprM)))) + hasCondition(SuspiciousNumberObjectExprM), + unless(hasTrueExpression( + hasDescendant(AnotherSuspiciousNumberObjectExprM))), + unless(hasFalseExpression( + hasDescendant(AnotherSuspiciousNumberObjectExprM)))) .bind("pedantic"); auto ConversionThroughExclamationMarkM = - unaryOperator(hasOperatorName("!"), has(expr(SuspiciousExprM))) + unaryOperator(hasOperatorName("!"), + has(expr(SuspiciousNumberObjectExprM))) .bind("pedantic"); auto ConversionThroughExplicitBooleanCastM = - explicitCastExpr(hasType(AnyBooleanTypeM), - has(expr(SuspiciousExprM))) + explicitCastExpr(hasType(SuspiciousScalarBooleanTypeM), + has(expr(SuspiciousNumberObjectExprM))) .bind("pedantic"); auto ConversionThroughExplicitNumberCastM = - explicitCastExpr(hasType(AnyNumberTypeM), - has(expr(SuspiciousExprM))); + explicitCastExpr(hasType(SuspiciousScalarNumberTypeM), + has(expr(SuspiciousNumberObjectExprM))); auto ConversionThroughInitializerM = declStmt(hasSingleDecl( - varDecl(hasType(AnyBooleanOrNumberTypeM), - hasInitializer(SuspiciousExprM)))); + varDecl(hasType(SuspiciousScalarTypeM), + hasInitializer(SuspiciousNumberObjectExprM)))); auto FinalM = stmt(anyOf(ConversionThroughAssignmentM, ConversionThroughBranchingM, @@ -252,16 +283,16 @@ ConversionThroughExplicitNumberCastM, ConversionThroughInitializerM)).bind("conv"); + MatchFinder F; + Callback CB(this, BR, AM.getAnalysisDeclContext(D)); + F.addMatcher(stmt(forEachDescendant(FinalM)), &CB); F.match(*D->getBody(), AM.getASTContext()); } void ento::registerNumberObjectConversionChecker(CheckerManager &Mgr) { - const LangOptions &LO = Mgr.getLangOpts(); - if (LO.CPlusPlus || LO.ObjC2) { - NumberObjectConversionChecker *Chk = - Mgr.registerChecker(); - Chk->Pedantic = - Mgr.getAnalyzerOptions().getBooleanOption("Pedantic", false, Chk); - } + NumberObjectConversionChecker *Chk = + Mgr.registerChecker(); + Chk->Pedantic = + Mgr.getAnalyzerOptions().getBooleanOption("Pedantic", false, Chk); } Index: test/Analysis/number-object-conversion.c =================================================================== --- /dev/null +++ test/Analysis/number-object-conversion.c @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin10 -w -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify +// RUN: %clang_cc1 -triple i386-apple-darwin10 -w -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify + +#define NULL ((void *)0) + +typedef const struct __CFNumber *CFNumberRef; + + +void takes_int(int); + +void bad(CFNumberRef p) { +#ifdef PEDANTIC + if (p) {} // expected-warning{{Converting 'CFNumberRef' pointer to a branch condition; instead, compare the pointer to NULL or take the encapsulated scalar value}} + if (!p) {} // expected-warning{{Converting 'CFNumberRef' pointer to a branch condition; instead, compare the pointer to NULL or take the encapsulated scalar value}} + p ? 1 : 2; // expected-warning{{Converting 'CFNumberRef' pointer to a branch condition; instead, compare the pointer to NULL or take the encapsulated scalar value}} + if (p == 0) {} // expected-warning{{Converting 'CFNumberRef' pointer to a plain integer value; instead, compare the pointer to NULL or take the encapsulated scalar value}} +#else + if (p) {} // no-warning + if (!p) {} // no-warning + p ? 1 : 2; // no-warning + if (p == 0) {} // no-warning +#endif + if (p > 0) {} // expected-warning{{Converting 'CFNumberRef' pointer to a plain integer value; pointer value is being used instead}} + int x = p; // expected-warning{{Converting 'CFNumberRef' pointer to a plain integer value; pointer value is being used instead}} + x = p; // expected-warning{{Converting 'CFNumberRef' pointer to a plain integer value; pointer value is being used instead}} + takes_int(p); // expected-warning{{Converting 'CFNumberRef' pointer to a plain integer value; pointer value is being used instead}} + takes_int(x); // no-warning +} Index: test/Analysis/number-object-conversion.cpp =================================================================== --- test/Analysis/number-object-conversion.cpp +++ test/Analysis/number-object-conversion.cpp @@ -10,28 +10,59 @@ virtual bool isFalse() const; }; +class OSNumber { +public: + virtual bool isEqualTo(const OSNumber *); + virtual unsigned char unsigned8BitValue() const; + virtual unsigned short unsigned16BitValue() const; + virtual unsigned int unsigned32BitValue() const; + virtual unsigned long long unsigned64BitValue() const; +}; + extern const OSBoolean *const &kOSBooleanFalse; extern const OSBoolean *const &kOSBooleanTrue; void takes_bool(bool); -void bad(const OSBoolean *p) { +void bad_boolean(const OSBoolean *p) { #ifdef PEDANTIC - if (p) {} // expected-warning{{Converting 'const class OSBoolean *' to a plain boolean value for branching; please compare the pointer to NULL or nullptr instead to suppress this warning}} - if (!p) {} // expected-warning{{Converting 'const class OSBoolean *' to a plain boolean value for branching; please compare the pointer to NULL or nullptr instead to suppress this warning}} - p ? 1 : 2; // expected-warning{{Converting 'const class OSBoolean *' to a plain boolean value for branching; please compare the pointer to NULL or nullptr instead to suppress this warning}} - (bool)p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; please compare the pointer to NULL or nullptr instead to suppress this warning}} + if (p) {} // expected-warning{{Converting 'const class OSBoolean *' pointer to a branch condition; instead, compare the pointer to nullptr or take the encapsulated scalar value}} + if (!p) {} // expected-warning{{Converting 'const class OSBoolean *' pointer to a branch condition; instead, compare the pointer to nullptr or take the encapsulated scalar value}} + p ? 1 : 2; // expected-warning{{Converting 'const class OSBoolean *' pointer to a branch condition; instead, compare the pointer to nullptr or take the encapsulated scalar value}} + (bool)p; // expected-warning{{Converting 'const class OSBoolean *' pointer to a plain bool value; instead, compare the pointer to nullptr or take the encapsulated scalar value}} +#else + if (p) {} // no-warning + if (!p) {} // no-warning + p ? 1 : 2; // no-warning + (bool)p; // no-warning #endif - bool x = p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}} - x = p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}} - takes_bool(p); // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}} + bool x = p; // expected-warning{{Converting 'const class OSBoolean *' pointer to a plain bool value; pointer value is being used instead}} + x = p; // expected-warning{{Converting 'const class OSBoolean *' pointer to a plain bool value; pointer value is being used instead}} + takes_bool(p); // expected-warning{{Converting 'const class OSBoolean *' pointer to a plain bool value; pointer value is being used instead}} takes_bool(x); // no-warning } +void bad_number(const OSNumber *p) { +#ifdef PEDANTIC + if (p) {} // expected-warning{{Converting 'const class OSNumber *' pointer to a branch condition; instead, compare the pointer to nullptr or take the encapsulated scalar value}} + if (!p) {} // expected-warning{{Converting 'const class OSNumber *' pointer to a branch condition; instead, compare the pointer to nullptr or take the encapsulated scalar value}} + p ? 1 : 2; // expected-warning{{Converting 'const class OSNumber *' pointer to a branch condition; instead, compare the pointer to nullptr or take the encapsulated scalar value}} + if (p == 0) {} // expected-warning{{Converting 'const class OSNumber *' pointer to a plain integer value; instead, compare the pointer to nullptr or take the encapsulated scalar value}} +#else + if (p) {} // no-warning + if (!p) {} // no-warning + p ? 1 : 2; // no-warning + if (p == 0) {} // no-warning +#endif + if (p > 0) {} // expected-warning{{Converting 'const class OSNumber *' pointer to a plain integer value; pointer value is being used instead}} + (int)p; // expected-warning{{Converting 'const class OSNumber *' pointer to a plain integer value; pointer value is being used instead}} + takes_bool(p); // expected-warning{{Converting 'const class OSNumber *' pointer to a plain bool value; pointer value is being used instead}} +} + typedef bool sugared_bool; typedef const OSBoolean *sugared_OSBoolean; void bad_sugared(sugared_OSBoolean p) { - sugared_bool x = p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}} + sugared_bool x = p; // expected-warning{{Converting 'sugared_OSBoolean' pointer to a plain bool value; pointer value is being used instead}} } void good(const OSBoolean *p) { @@ -50,11 +81,11 @@ typedef unsigned long uintptr_t; typedef long fintptr_t; // Fake, for testing the regex. void test_intptr_t(const OSBoolean *p) { - (long)p; // expected-warning{{Converting 'const class OSBoolean *' to a plain integer value; pointer value is being used instead}} + (long)p; // expected-warning{{Converting 'const class OSBoolean *' pointer to a plain integer value; pointer value is being used instead}} (intptr_t)p; // no-warning - (unsigned long)p; // expected-warning{{Converting 'const class OSBoolean *' to a plain integer value; pointer value is being used instead}} + (unsigned long)p; // expected-warning{{Converting 'const class OSBoolean *' pointer to a plain integer value; pointer value is being used instead}} (uintptr_t)p; // no-warning - (fintptr_t)p; // expected-warning{{Converting 'const class OSBoolean *' to a plain integer value; pointer value is being used instead}} + (fintptr_t)p; // expected-warning{{Converting 'const class OSBoolean *' pointer to a plain integer value; pointer value is being used instead}} } // Test a different definition of NULL. Index: test/Analysis/number-object-conversion.m =================================================================== --- test/Analysis/number-object-conversion.m +++ test/Analysis/number-object-conversion.m @@ -10,30 +10,36 @@ void bad(NSNumber *p) { #ifdef PEDANTIC - if (p) {} // expected-warning{{Converting 'NSNumber *' to a plain boolean value for branching; please compare the pointer to nil instead to suppress this warning}} - if (!p) {} // expected-warning{{Converting 'NSNumber *' to a plain boolean value for branching; please compare the pointer to nil instead to suppress this warning}} - (!p) ? 1 : 2; // expected-warning{{Converting 'NSNumber *' to a plain boolean value for branching; please compare the pointer to nil instead to suppress this warning}} - (BOOL)p; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; please compare the pointer to nil instead to suppress this warning}} - if (p == 0) {} // expected-warning{{Converting 'NSNumber *' to a plain integer value; please compare the pointer to nil instead to suppress this warning}} - if (p > 0) {} // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}} + if (p) {} // expected-warning{{Converting 'NSNumber *' pointer to a branch condition; instead, compare the pointer to nil or take the encapsulated scalar value}} + if (!p) {} // expected-warning{{Converting 'NSNumber *' pointer to a branch condition; instead, compare the pointer to nil or take the encapsulated scalar value}} + (!p) ? 1 : 2; // expected-warning{{Converting 'NSNumber *' pointer to a branch condition; instead, compare the pointer to nil or take the encapsulated scalar value}} + (BOOL)p; // expected-warning{{Converting 'NSNumber *' pointer to a plain BOOL value; instead, compare the pointer to nil or take the encapsulated scalar value}} + if (p == 0) {} // expected-warning{{Converting 'NSNumber *' pointer to a plain integer value; instead, compare the pointer to nil or take the encapsulated scalar value}} +#else + if (p) {} // no-warning + if (!p) {} // no-warning + (!p) ? 1 : 2; // no-warning + (BOOL)p; // no-warning + if (p == 0) {} // no-warning #endif - if (p == YES) {} // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}} - if (p == NO) {} // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}} - BOOL x = p; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}} - x = p; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}} - x = (p == YES); // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}} - if (p == 1) {} // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}} - int y = p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}} - y = p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}} - takes_boolean(p); // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}} - takes_integer(p); // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}} + if (p > 0) {} // expected-warning{{Converting 'NSNumber *' pointer to a plain integer value; pointer value is being used instead}} + if (p == YES) {} // expected-warning{{Converting 'NSNumber *' pointer to a plain BOOL value; pointer value is being used instead}} + if (p == NO) {} // expected-warning{{Converting 'NSNumber *' pointer to a plain BOOL value; pointer value is being used instead}} + BOOL x = p; // expected-warning{{Converting 'NSNumber *' pointer to a plain BOOL value; pointer value is being used instead}} + x = p; // expected-warning{{Converting 'NSNumber *' pointer to a plain BOOL value; pointer value is being used instead}} + x = (p == YES); // expected-warning{{Converting 'NSNumber *' pointer to a plain BOOL value; pointer value is being used instead}} + if (p == 1) {} // expected-warning{{Converting 'NSNumber *' pointer to a plain integer value; pointer value is being used instead}} + int y = p; // expected-warning{{Converting 'NSNumber *' pointer to a plain integer value; pointer value is being used instead}} + y = p; // expected-warning{{Converting 'NSNumber *' pointer to a plain integer value; pointer value is being used instead}} + takes_boolean(p); // expected-warning{{Converting 'NSNumber *' pointer to a plain BOOL value; pointer value is being used instead}} + takes_integer(p); // expected-warning{{Converting 'NSNumber *' pointer to a plain integer value; pointer value is being used instead}} takes_boolean(x); // no-warning takes_integer(y); // no-warning } typedef NSNumber *SugaredNumber; void bad_sugared(SugaredNumber p) { - p == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}} + p == YES; // expected-warning{{Converting 'SugaredNumber' pointer to a plain BOOL value; pointer value is being used instead}} } @interface I : NSObject { @@ -50,9 +56,9 @@ @end void bad_ivar(I *i) { - i->ivar == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}} - i->prop == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}} - [i foo] == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}} + i->ivar == YES; // expected-warning{{Converting 'NSNumber *' pointer to a plain BOOL value; pointer value is being used instead}} + i->prop == YES; // expected-warning{{Converting 'NSNumber *' pointer to a plain BOOL value; pointer value is being used instead}} + [i foo] == YES; // expected-warning{{Converting 'NSNumber *' pointer to a plain BOOL value; pointer value is being used instead}} } void good(NSNumber *p) { @@ -71,11 +77,11 @@ typedef unsigned long uintptr_t; typedef long fintptr_t; // Fake, for testing the regex. void test_intptr_t(NSNumber *p) { - (long)p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}} + (long)p; // expected-warning{{Converting 'NSNumber *' pointer to a plain integer value; pointer value is being used instead}} (intptr_t)p; // no-warning - (unsigned long)p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}} + (unsigned long)p; // expected-warning{{Converting 'NSNumber *' pointer to a plain integer value; pointer value is being used instead}} (uintptr_t)p; // no-warning - (fintptr_t)p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}} + (fintptr_t)p; // expected-warning{{Converting 'NSNumber *' pointer to a plain integer value; pointer value is being used instead}} } // Test a different definition of NULL.