NoQ updated this revision to Diff 75411.
NoQ marked 5 inline comments as done.
NoQ added a comment.
Address review comments. Add the forgotten tests.
https://reviews.llvm.org/D25731
Files:
lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
test/Analysis/number-object-conversion.c
test/Analysis/number-object-conversion.cpp
test/Analysis/number-object-conversion.m
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.
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.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: 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<Stmt>("conv");
assert(Conv);
- const Expr *Osboolean = Result.Nodes.getNodeAs<Expr>("osboolean");
- const Expr *Nsnumber = Result.Nodes.getNodeAs<Expr>("nsnumber");
- bool IsObjC = (bool)Nsnumber;
- const Expr *Obj = IsObjC ? Nsnumber : Osboolean;
+ const Expr *ConvertedCObject = Result.Nodes.getNodeAs<Expr>("c_object");
+ const Expr *ConvertedCppObject = Result.Nodes.getNodeAs<Expr>("cpp_object");
+ const Expr *ConvertedObjCObject = Result.Nodes.getNodeAs<Expr>("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<Expr>("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<QualType>("int_type") != nullptr)
- OS << "integer value";
+ OS << "plain integer value";
else if (Result.Nodes.getNodeAs<QualType>("objc_bool_type") != nullptr)
- OS << "BOOL value";
+ OS << "plain BOOL value";
else if (Result.Nodes.getNodeAs<QualType>("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<NumberObjectConversionChecker>();
- Chk->Pedantic =
- Mgr.getAnalyzerOptions().getBooleanOption("Pedantic", false, Chk);
- }
+ NumberObjectConversionChecker *Chk =
+ Mgr.registerChecker<NumberObjectConversionChecker>();
+ Chk->Pedantic =
+ Mgr.getAnalyzerOptions().getBooleanOption("Pedantic", false, Chk);
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits