From af86b0c160bc998bdde2f35d526ca819d7b3a1f2 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Fri, 17 Dec 2010 04:44:43 +0000 Subject: [PATCH] Revise Cocoa conventions detection: 'copy' and 'mutableCopy' only indicates the create rule if it starts at the beginning of the method name, not within the method name. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122036 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Checker/CocoaConventions.cpp | 84 ++++++++++++-------------------- test/Analysis/refcnt_naming.m | 8 ++- test/Analysis/retain-release.m | 8 +-- 3 files changed, 40 insertions(+), 60 deletions(-) diff --git a/lib/Checker/CocoaConventions.cpp b/lib/Checker/CocoaConventions.cpp index b446a048d4..8a3abc8bae 100644 --- a/lib/Checker/CocoaConventions.cpp +++ b/lib/Checker/CocoaConventions.cpp @@ -63,72 +63,48 @@ cocoa::NamingConvention cocoa::deriveNamingConvention(Selector S) { // A method/function name may contain a prefix. We don't know it is there, // however, until we encounter the first '_'. - bool InPossiblePrefix = true; - bool AtBeginning = true; - NamingConvention C = NoConvention; - while (*s != '\0') { - // Skip '_'. - if (*s == '_') { - if (InPossiblePrefix) { - // If we already have a convention, return it. Otherwise, skip - // the prefix as if it wasn't there. - if (C != NoConvention) - break; - - InPossiblePrefix = false; - AtBeginning = true; - assert(C == NoConvention); - } - ++s; - continue; - } - - // Skip numbers, ':', etc. - if (!isalpha(*s)) { + // Skip '_', numbers, ':', etc. + if (*s == '_' || !isalpha(*s)) { ++s; continue; } + break; + } - const char *wordEnd = parseWord(s); - assert(wordEnd > s); - unsigned len = wordEnd - s; + // Parse the first word, and look for specific keywords. + const char *wordEnd = parseWord(s); + assert(wordEnd > s); + unsigned len = wordEnd - s; - switch (len) { + switch (len) { default: - break; + return NoConvention; case 3: // Methods starting with 'new' follow the create rule. - if (AtBeginning && StringRef(s, len).equals_lower("new")) - C = CreateRule; - break; + return (memcmp(s, "new", 3) == 0) ? CreateRule : NoConvention; case 4: - // Methods starting with 'alloc' or contain 'copy' follow the - // create rule - if (C == NoConvention && StringRef(s, len).equals_lower("copy")) - C = CreateRule; - else // Methods starting with 'init' follow the init rule. - if (AtBeginning && StringRef(s, len).equals_lower("init")) - C = InitRule; - break; + // Methods starting with 'copy' follow the create rule. + if (memcmp(s, "copy", 4) == 0) + return CreateRule; + // Methods starting with 'init' follow the init rule. + if (memcmp(s, "init", 4) == 0) + return InitRule; + return NoConvention; case 5: - if (AtBeginning && StringRef(s, len).equals_lower("alloc")) - C = CreateRule; - break; - } - - // If we aren't in the prefix and have a derived convention then just - // return it now. - if (!InPossiblePrefix && C != NoConvention) - return C; - - AtBeginning = false; - s = wordEnd; + return (memcmp(s, "alloc", 5) == 0) ? CreateRule : NoConvention; + case 7: + // Methods starting with 'mutableCopy' follow the create rule. + if (memcmp(s, "mutable", 7) == 0) { + // Look at the next word to see if it is "Copy". + s = wordEnd; + wordEnd = parseWord(s); + len = wordEnd - s; + if (len == 4 && memcmp(s, "Copy", 4) == 0) + return CreateRule; + } + return NoConvention; } - - // We will get here if there wasn't more than one word - // after the prefix. - return C; } bool cocoa::isRefType(QualType RetTy, llvm::StringRef Prefix, diff --git a/test/Analysis/refcnt_naming.m b/test/Analysis/refcnt_naming.m index 9defce2735..f84dd6e054 100644 --- a/test/Analysis/refcnt_naming.m +++ b/test/Analysis/refcnt_naming.m @@ -11,6 +11,8 @@ typedef signed char BOOL; @class NSArray, NSString, NSURL; @interface NamingTest : NSObject {} +-(NSObject*)copyPhoto; +-(NSObject*)mutableCopyPhoto; -(NSObject*)photocopy; // read as "photocopy" -(NSObject*)photoCopy; // read as "photo Copy" -(NSObject*)__blebPRCopy; // read as "bleb PRCopy" @@ -45,9 +47,11 @@ typedef signed char BOOL; } void testNames(NamingTest* x) { + [x copyPhoto]; // expected-warning{{leak}} + [x mutableCopyPhoto]; // expected-warning{{leak}} [x photocopy]; // no-warning - [x photoCopy]; // expected-warning{{leak}} - [x __blebPRCopy]; // expected-warning{{leak}} + [x photoCopy]; // no-warning + [x __blebPRCopy]; // no-warning [x __blebPRcopy]; // no-warning [x new_theprefixdoescount]; // expected-warning{{leak}} [x newestAwesomeStuff]; // no-warning diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index edaedcb4f5..f6e43c99e8 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -762,13 +762,13 @@ int RDar6320065_test() { @end @implementation RDar6859457 -- (NSString*) NoCopyString { return [[NSString alloc] init]; } // no-warning -- (NSString*) noCopyString { return [[NSString alloc] init]; } // no-warning +- (NSString*) NoCopyString { return [[NSString alloc] init]; } // expected-warning{{leak}} +- (NSString*) noCopyString { return [[NSString alloc] init]; } // expected-warning{{leak}} @end void test_RDar6859457(RDar6859457 *x, void *bytes, NSUInteger dataLength) { - [x NoCopyString]; // expected-warning{{leak}} - [x noCopyString]; // expected-warning{{leak}} + [x NoCopyString]; // no-warning + [x noCopyString]; // no-warning [NSData dataWithBytesNoCopy:bytes length:dataLength]; // no-warning [NSData dataWithBytesNoCopy:bytes length:dataLength freeWhenDone:1]; // no-warning } -- 2.40.0