Tweak the interface for analyzing the CF conventions for a name

to take a FunctionDecl* instead of an llvm::StringRef.  Eventually
we might push more logic in there, like using slightly different
conventions for C++ methods.

Also, fix a bug where 'copy' and 'create' were being caught in 
non-camel-cased strings.  We want copyFoo and CopyFoo and XCopy
but not Xcopy or xcopy.

llvm-svn: 140911
This commit is contained in:
John McCall 2011-10-01 00:48:56 +00:00
parent 1ed54f50c5
commit 525f05597f
4 changed files with 31 additions and 12 deletions

View File

@ -14,12 +14,13 @@
#ifndef LLVM_CLANG_ANALYSIS_DS_COCOA
#define LLVM_CLANG_ANALYSIS_DS_COCOA
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/StringRef.h"
#include "clang/AST/Type.h"
namespace clang {
class FunctionDecl;
class ObjCMethodDecl;
class QualType;
namespace ento {
namespace cocoa {
@ -43,7 +44,7 @@ namespace cocoa {
namespace coreFoundation {
bool isCFObjectRef(QualType T);
bool followsCreateRule(StringRef functionName);
bool followsCreateRule(const FunctionDecl *FD);
}
}} // end: "clang:ento"

View File

@ -125,7 +125,13 @@ bool cocoa::isCocoaObjectRef(QualType Ty) {
return false;
}
bool coreFoundation::followsCreateRule(StringRef functionName) {
bool coreFoundation::followsCreateRule(const FunctionDecl *fn) {
// For now, *just* base this on the function name, not on anything else.
const IdentifierInfo *ident = fn->getIdentifier();
if (!ident) return false;
StringRef functionName = ident->getName();
StringRef::iterator it = functionName.begin();
StringRef::iterator start = it;
StringRef::iterator endI = functionName.end();
@ -136,6 +142,10 @@ bool coreFoundation::followsCreateRule(StringRef functionName) {
// Search for the first character. It can either be 'C' or 'c'.
char ch = *it;
if (ch == 'C' || ch == 'c') {
// Make sure this isn't something like 'recreate' or 'Scopy'.
if (ch == 'c' && it != start && isalpha(*(it - 1)))
continue;
++it;
break;
}

View File

@ -623,8 +623,7 @@ public:
RetainSummary* getCFSummaryCreateRule(const FunctionDecl *FD);
RetainSummary* getCFSummaryGetRule(const FunctionDecl *FD);
RetainSummary* getCFCreateGetRuleSummary(const FunctionDecl *FD,
StringRef FName);
RetainSummary* getCFCreateGetRuleSummary(const FunctionDecl *FD);
RetainSummary* getPersistentSummary(ArgEffects AE, RetEffect RetEff,
ArgEffect ReceiverEff = DoNothing,
@ -1000,7 +999,7 @@ RetainSummary* RetainSummaryManager::getSummary(const FunctionDecl *FD) {
else if (isMakeCollectable(FD, FName))
S = getUnarySummary(FT, cfmakecollectable);
else
S = getCFCreateGetRuleSummary(FD, FName);
S = getCFCreateGetRuleSummary(FD);
break;
}
@ -1010,7 +1009,7 @@ RetainSummary* RetainSummaryManager::getSummary(const FunctionDecl *FD) {
if (isRetain(FD, FName))
S = getUnarySummary(FT, cfretain);
else
S = getCFCreateGetRuleSummary(FD, FName);
S = getCFCreateGetRuleSummary(FD);
break;
}
@ -1019,7 +1018,7 @@ RetainSummary* RetainSummaryManager::getSummary(const FunctionDecl *FD) {
if (cocoa::isRefType(RetTy, "DADisk") ||
cocoa::isRefType(RetTy, "DADissenter") ||
cocoa::isRefType(RetTy, "DASessionRef")) {
S = getCFCreateGetRuleSummary(FD, FName);
S = getCFCreateGetRuleSummary(FD);
break;
}
@ -1072,9 +1071,8 @@ RetainSummary* RetainSummaryManager::getSummary(const FunctionDecl *FD) {
}
RetainSummary*
RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD,
StringRef FName) {
if (coreFoundation::followsCreateRule(FName))
RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) {
if (coreFoundation::followsCreateRule(FD))
return getCFSummaryCreateRule(FD);
return getCFSummaryGetRule(FD);

View File

@ -304,4 +304,14 @@ void test_smartpointer_3() {
foo.noAdopt(x);
}
extern CFStringRef ElectronMicroscopyEngage(void);
void test_microscopy() {
NSString *token = (NSString*) ElectronMicroscopyEngage();
[token release]; // expected-warning {{object that is not owned}}
}
extern CFStringRef Scopy(void);
void test_Scopy() {
NSString *token = (NSString*) Scopy();
[token release]; // expected-warning {{object that is not owned}}
}