From 797a7be0de6fbedaa85082b07ec9ce0674f30773 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Sat, 16 Jul 2011 19:50:36 +0000 Subject: [PATCH] [analyzer] Per discussions with the Cocoa team, extend CF naming conventions to extend to camel case functions instead of just title case functions. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135350 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/CocoaConventions.cpp | 43 +++++++++++++++++++++++-- test/Analysis/retain-release.m | 53 +++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/lib/Analysis/CocoaConventions.cpp b/lib/Analysis/CocoaConventions.cpp index 428032bee5..90f7092f90 100644 --- a/lib/Analysis/CocoaConventions.cpp +++ b/lib/Analysis/CocoaConventions.cpp @@ -128,6 +128,45 @@ bool cocoa::isCocoaObjectRef(QualType Ty) { } bool coreFoundation::followsCreateRule(llvm::StringRef functionName) { - return functionName.find("Create") != StringRef::npos || - functionName.find("Copy") != StringRef::npos; + llvm::StringRef::iterator it = functionName.begin(); + llvm::StringRef::iterator start = it; + llvm::StringRef::iterator endI = functionName.end(); + + while (true) { + // Scan for the start of 'create' or 'copy'. + for ( ; it != endI ; ++it) { + // Search for the first character. It can either be 'C' or 'c'. + char ch = *it; + if (ch == 'C' || ch == 'c') { + ++it; + break; + } + } + + // Did we hit the end of the string? If so, we didn't find a match. + if (it == endI) + return false; + + // Scan for *lowercase* 'reate' or 'opy', followed by no lowercase + // character. + llvm::StringRef suffix = functionName.substr(it - start); + if (suffix.startswith("reate")) { + it += 5; + } + else if (suffix.startswith("opy")) { + it += 3; + } + else { + // Keep scanning. + continue; + } + + if (it == endI || !islower(*it)) + return true; + + // If we matched a lowercase character, it isn't the end of the + // word. Keep scanning. + } + + return false; } diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index 61973cebe0..71ae756cf0 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -1487,3 +1487,56 @@ void rdar9726279() { NSValue *value = [[NSValue alloc] _prefix_initWithTwoDoubles:twoDoubles]; [value release]; } + +// +// Test camelcase support for CF conventions. While Core Foundation APIs +// don't use camel casing, other code is allowed to use it. +CFArrayRef camelcase_create_1() { + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning +} + +CFArrayRef camelcase_createno() { + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning {{leak}} +} + +CFArrayRef camelcase_copy() { + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning +} + +CFArrayRef camelcase_copying() { + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning {{leak}} +} + +CFArrayRef copyCamelCase() { + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning +} + +CFArrayRef __copyCamelCase() { + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning +} + +CFArrayRef __createCamelCase() { + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning +} + +CFArrayRef camel_create() { + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning +} + + +CFArrayRef camel_creat() { + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning {{leak}} +} + +CFArrayRef camel_copy() { + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning +} + +CFArrayRef camel_copyMachine() { + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning +} + +CFArrayRef camel_copymachine() { + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning {{leak}} +} + -- 2.50.1