Skip to content

Commit

Permalink
[analyzer] Print a fully qualified name for functions in RetainCountC…
Browse files Browse the repository at this point in the history
…hecker diagnostics

Attempt to get a fully qualified name from AST if an SVal corresponding
to the object is not available.

Differential Revision: https://reviews.llvm.org/D55034

llvm-svn: 347944
  • Loading branch information
George Karpenkov committed Nov 30, 2018
1 parent f893ea1 commit e2f0954
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 12 deletions.
Expand Up @@ -173,10 +173,19 @@ CFRefReportVisitor::VisitNode(const ExplodedNode *N,
os << "Object loaded from instance variable";
} else {
if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
// Get the name of the callee (if it is available).
// Get the name of the callee (if it is available)
// from the tracked SVal.
SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
if (const FunctionDecl *FD = X.getAsFunctionDecl()) {
os << "Call to function '" << *FD << '\'';
const FunctionDecl *FD = X.getAsFunctionDecl();

// If failed, try to get it from AST.
if (!FD)
FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());

if (const auto *MD = dyn_cast<CXXMethodDecl>(CE->getCalleeDecl())) {
os << "Call to method '" << MD->getQualifiedNameAsString() << '\'';
} else if (FD) {
os << "Call to function '" << FD->getQualifiedNameAsString() << '\'';
} else {
os << "function call";
}
Expand Down
23 changes: 14 additions & 9 deletions clang/test/Analysis/osobject-retain-release.cpp
Expand Up @@ -60,14 +60,19 @@ void check_custom_iterator_rule(OSArray *arr) {
it->release();
}

void check_iterator_leak(OSArray *arr) {
arr->getIterator(); // expected-note{{Call to method 'OSArray::getIterator' returns an OSObject of type struct OSIterator * with a +1 retain count}}
} // expected-note{{Object leaked: allocated object of type struct OSIterator * is not referenced later}}
// expected-warning@-1{{Potential leak of an object of type struct OSIterator *}}n this execution path and has a retain count of +1}}

void check_no_invalidation() {
OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
OtherStruct::doNothingToArray(arr);
} // expected-warning{{Potential leak of an object stored into 'arr'}}
// expected-note@-1{{Object leaked}}

void check_no_invalidation_other_struct() {
OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
OtherStruct other(arr); // expected-warning{{Potential leak}}
// expected-note@-1{{Object leaked}}
}
Expand All @@ -94,8 +99,8 @@ struct ArrayOwner : public OSObject {
};

OSArray *generateArray() {
return OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
// expected-note@-1{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
return OSArray::withCapacity(10); // expected-note{{Call to method 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
// expected-note@-1{{Call to method 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
}

unsigned int check_leak_good_error_message() {
Expand Down Expand Up @@ -164,7 +169,7 @@ unsigned int check_dynamic_cast_no_null_on_orig(OSObject *obj) {
}

void check_dynamic_cast_null_branch(OSObject *obj) {
OSArray *arr1 = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject}}
OSArray *arr1 = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject}}
OSArray *arr = OSDynamicCast(OSArray, obj);
if (!arr) // expected-note{{Taking true branch}}
return; // expected-warning{{Potential leak of an object stored into 'arr1'}}
Expand All @@ -173,7 +178,7 @@ void check_dynamic_cast_null_branch(OSObject *obj) {
}

void check_dynamic_cast_null_check() {
OSArray *arr = OSDynamicCast(OSArray, OSObject::generateObject(1)); // expected-note{{Call to function 'generateObject' returns an OSObject}}
OSArray *arr = OSDynamicCast(OSArray, OSObject::generateObject(1)); // expected-note{{Call to method 'OSObject::generateObject' returns an OSObject}}
// expected-warning@-1{{Potential leak of an object}}
// expected-note@-2{{Object leaked}}
if (!arr)
Expand All @@ -182,14 +187,14 @@ void check_dynamic_cast_null_check() {
}

void use_after_release() {
OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
arr->release(); // expected-note{{Object released}}
arr->getCount(); // expected-warning{{Reference-counted object is used after it is released}}
// expected-note@-1{{Reference-counted object is used after it is released}}
}

void potential_leak() {
OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
arr->retain(); // expected-note{{Reference count incremented. The object now has a +2 retain count}}
arr->release(); // expected-note{{Reference count decremented. The object now has a +1 retain count}}
arr->getCount();
Expand Down Expand Up @@ -240,7 +245,7 @@ unsigned int no_warn_ok_release(ArrayOwner *owner) {
}

unsigned int warn_on_overrelease_with_unknown_source(ArrayOwner *owner) {
OSArray *arr = owner->getArraySourceUnknown(); // expected-note{{function call returns an OSObject of type OSArray with a +0 retain count}}
OSArray *arr = owner->getArraySourceUnknown(); // expected-note{{Call to method 'ArrayOwner::getArraySourceUnknown' returns an OSObject of type OSArray with a +0 retain count}}
arr->release(); // expected-warning{{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
// expected-note@-1{{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
return arr->getCount();
Expand Down

0 comments on commit e2f0954

Please sign in to comment.