Patch by Sean McBride, tests adjusted by me.
llvm-svn: 211453
}
//===----------------------------------------------------------------------===//
-// CFRetain/CFRelease/CFMakeCollectable checking for null arguments.
+// CFRetain/CFRelease/CFMakeCollectable/CFAutorelease checking for null arguments.
//===----------------------------------------------------------------------===//
namespace {
class CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > {
mutable std::unique_ptr<APIMisuse> BT;
- mutable IdentifierInfo *Retain, *Release, *MakeCollectable;
+ mutable IdentifierInfo *Retain, *Release, *MakeCollectable, *Autorelease;
public:
CFRetainReleaseChecker()
- : Retain(nullptr), Release(nullptr), MakeCollectable(nullptr) {}
+ : Retain(nullptr), Release(nullptr), MakeCollectable(nullptr),
+ Autorelease(nullptr) {}
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
};
} // end anonymous namespace
Retain = &Ctx.Idents.get("CFRetain");
Release = &Ctx.Idents.get("CFRelease");
MakeCollectable = &Ctx.Idents.get("CFMakeCollectable");
+ Autorelease = &Ctx.Idents.get("CFAutorelease");
BT.reset(new APIMisuse(
- this, "null passed to CFRetain/CFRelease/CFMakeCollectable"));
+ this, "null passed to CF memory management function"));
}
- // Check if we called CFRetain/CFRelease/CFMakeCollectable.
+ // Check if we called CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
const IdentifierInfo *FuncII = FD->getIdentifier();
- if (!(FuncII == Retain || FuncII == Release || FuncII == MakeCollectable))
+ if (!(FuncII == Retain || FuncII == Release || FuncII == MakeCollectable ||
+ FuncII == Autorelease))
return;
// FIXME: The rest of this just checks that the argument is non-null.
description = "Null pointer argument in call to CFRelease";
else if (FuncII == MakeCollectable)
description = "Null pointer argument in call to CFMakeCollectable";
+ else if (FuncII == Autorelease)
+ description = "Null pointer argument in call to CFAutorelease";
else
llvm_unreachable("impossible case");
CFRelease(*B); // no-warning
}
-// Test when we pass NULL to CFRetain/CFRelease/CFMakeCollectable.
+// Test when we pass NULL to CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
void f16(int x, CFTypeRef p) {
if (p)
return;
- if (x > 0) {
- CFRelease(p); // expected-warning{{Null pointer argument in call to CFRelease}}
- }
- else if (x < 0) {
- CFRetain(p); // expected-warning{{Null pointer argument in call to CFRetain}}
- }
- else {
- CFMakeCollectable(p); // expected-warning{{Null pointer argument in call to CFMakeCollectable}}
+ switch (x) {
+ case 0:
+ CFRelease(p);
+ break;
+ case 1:
+ CFRetain(p);
+ break;
+ case 2:
+ CFMakeCollectable(p);
+ break;
+ case 3:
+ CFAutorelease(p);
+ break;
+ default:
+ break;
}
}
-// Test that an object is non-null after being CFRetained/CFReleased.
+// Test that an object is non-null after CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
void f17(int x, CFTypeRef p) {
- if (x > 0) {
+ switch (x) {
+ case 0:
CFRelease(p);
if (!p)
CFRelease(0); // no-warning
- }
- else if (x < 0) {
+ break;
+ case 1:
CFRetain(p);
if (!p)
CFRetain(0); // no-warning
- }
- else {
+ break;
+ case 2:
CFMakeCollectable(p);
if (!p)
CFMakeCollectable(0); // no-warning
+ break;
+ case 3:
+ CFAutorelease(p);
+ if (!p)
+ CFAutorelease(0); // no-warning
+ break;
+ default:
+ break;
}
}
CFRelease(*B); // no-warning
}
-// Test when we pass NULL to CFRetain/CFRelease/CFMakeCollectable.
+// Test when we pass NULL to CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
void f16(int x, CFTypeRef p) {
if (p)
return;
- if (x > 0) {
- CFRelease(p); // expected-warning{{Null pointer argument in call to CFRelease}}
- }
- else if (x < 0) {
- CFRetain(p); // expected-warning{{Null pointer argument in call to CFRetain}}
- }
- else {
- CFMakeCollectable(p); // expected-warning{{Null pointer argument in call to CFMakeCollectable}}
+ switch (x) {
+ case 0:
+ CFRelease(p);
+ break;
+ case 1:
+ CFRetain(p);
+ break;
+ case 2:
+ CFMakeCollectable(p);
+ break;
+ case 3:
+ CFAutorelease(p);
+ break;
+ default:
+ break;
}
}
-// Test that an object is non-null after being CFRetained/CFReleased.
+// Test that an object is non-null after CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
void f17(int x, CFTypeRef p) {
- if (x > 0) {
+ switch (x) {
+ case 0:
CFRelease(p);
if (!p)
CFRelease(0); // no-warning
- }
- else if (x < 0) {
+ break;
+ case 1:
CFRetain(p);
if (!p)
CFRetain(0); // no-warning
- }
- else {
+ break;
+ case 2:
CFMakeCollectable(p);
if (!p)
CFMakeCollectable(0); // no-warning
+ break;
+ case 3:
+ CFAutorelease(p);
+ if (!p)
+ CFAutorelease(0); // no-warning
+ break;
+ default:
+ break;
}
}
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>description</key><string>Null pointer argument in call to CFRelease</string>
// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>null passed to CFRetain/CFRelease/CFMakeCollectable</string>
+// CHECK-NEXT: <key>type</key><string>null passed to CF memory management function</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
// CHECK-NEXT: <key>issue_context</key><string>test</string>
// CHECK-NEXT: <key>issue_hash</key><string>5</string>
CFRelease(*B); // no-warning
}
-// Test when we pass NULL to CFRetain/CFRelease/CFMakeCollectable.
+// Test when we pass NULL to CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
void f16(int x, CFTypeRef p) {
if (p)
return;
- if (x > 0) {
+ switch (x) {
+ case 0:
CFRelease(p); // expected-warning{{Null pointer argument in call to CFRelease}}
- }
- else if (x < 0) {
+ break;
+ case 1:
CFRetain(p); // expected-warning{{Null pointer argument in call to CFRetain}}
- }
- else {
+ break;
+ case 2:
CFMakeCollectable(p); // expected-warning{{Null pointer argument in call to CFMakeCollectable}}
+ break;
+ case 3:
+ CFAutorelease(p); // expected-warning{{Null pointer argument in call to CFAutorelease}}
+ break;
+ default:
+ break;
}
}
-// Test that an object is non-null after being CFRetained/CFReleased.
+// Test that an object is non-null after CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
void f17(int x, CFTypeRef p) {
- if (x > 0) {
+ switch (x) {
+ case 0:
CFRelease(p);
if (!p)
CFRelease(0); // no-warning
- }
- else if (x < 0) {
+ break;
+ case 1:
CFRetain(p);
if (!p)
CFRetain(0); // no-warning
- }
- else {
+ break;
+ case 2:
CFMakeCollectable(p);
if (!p)
CFMakeCollectable(0); // no-warning
+ break;
+ case 3:
+ CFAutorelease(p);
+ if (!p)
+ CFAutorelease(0); // no-warning
+ break;
+ default:
+ break;
}
}
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>description</key><string>Null pointer argument in call to CFRelease</string>
// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>null passed to CFRetain/CFRelease/CFMakeCollectable</string>
+// CHECK-NEXT: <key>type</key><string>null passed to CF memory management function</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>f16</string>
// CHECK-NEXT: <key>issue_hash</key><string>5</string>
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>description</key><string>Null pointer argument in call to CFRetain</string>
// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>null passed to CFRetain/CFRelease/CFMakeCollectable</string>
+// CHECK-NEXT: <key>type</key><string>null passed to CF memory management function</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>f16</string>
// CHECK-NEXT: <key>issue_hash</key><string>8</string>
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>description</key><string>Null pointer argument in call to CFMakeCollectable</string>
// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>null passed to CFRetain/CFRelease/CFMakeCollectable</string>
+// CHECK-NEXT: <key>type</key><string>null passed to CF memory management function</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>f16</string>
// CHECK-NEXT: <key>issue_hash</key><string>11</string>