 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
88.7% |
94 / 106 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
100.0% |
106 / 106 |
| |
|
Line Coverage: |
97.5% |
79 / 81 |
| |
 |
|
 |
1 : //===- CocoaConventions.h - Special handling of Cocoa conventions -*- C++ -*--//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file defines
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "clang/Checker/DomainSpecific/CocoaConventions.h"
15 : #include "clang/AST/Type.h"
16 : #include "clang/AST/Decl.h"
17 : #include "clang/AST/DeclObjC.h"
18 : #include "llvm/ADT/StringExtras.h"
19 :
20 : using namespace clang;
21 :
22 : using llvm::StringRef;
23 :
24 : // The "fundamental rule" for naming conventions of methods:
25 : // (url broken into two lines)
26 : // http://developer.apple.com/documentation/Cocoa/Conceptual/
27 : // MemoryMgmt/Tasks/MemoryManagementRules.html
28 : //
29 : // "You take ownership of an object if you create it using a method whose name
30 : // begins with "alloc" or "new" or contains "copy" (for example, alloc,
31 : // newObject, or mutableCopy), or if you send it a retain message. You are
32 : // responsible for relinquishing ownership of objects you own using release
33 : // or autorelease. Any other time you receive an object, you must
34 : // not release it."
35 : //
36 :
37 6880: static bool isWordEnd(char ch, char prev, char next) {
38 : return ch == '\0'
39 : || (islower(prev) && isupper(ch)) // xxxC
40 : || (isupper(prev) && isupper(ch) && islower(next)) // XXCreate
6462: branch 0 taken
418: branch 1 taken
4482: branch 3 taken
1980: branch 4 taken
3815: branch 6 taken
667: branch 7 taken
803: branch 9 taken
4992: branch 10 taken
142: branch 12 taken
661: branch 13 taken
98: branch 15 taken
44: branch 16 taken
48: branch 18 taken
5703: branch 19 taken
41 6880: || !isalpha(ch);
42 : }
43 :
44 1177: static const char* parseWord(const char* s) {
45 1177: char ch = *s, prev = '\0';
0: branch 0 not taken
1177: branch 1 taken
46 1177: assert(ch != '\0');
47 1177: char next = *(s+1);
5703: branch 1 taken
1177: branch 2 taken
48 8057: while (!isWordEnd(ch, prev, next)) {
49 5703: prev = ch;
50 5703: ch = next;
51 5703: next = *((++s)+1);
52 : }
53 1177: return s;
54 : }
55 :
56 454: cocoa::NamingConvention cocoa::deriveNamingConvention(Selector S) {
57 454: IdentifierInfo *II = S.getIdentifierInfoForSlot(0);
58 :
2: branch 0 taken
452: branch 1 taken
59 454: if (!II)
60 2: return NoConvention;
61 :
62 452: const char *s = II->getNameStart();
63 :
64 : // A method/function name may contain a prefix. We don't know it is there,
65 : // however, until we encounter the first '_'.
66 452: bool InPossiblePrefix = true;
67 452: bool AtBeginning = true;
68 452: NamingConvention C = NoConvention;
69 :
1363: branch 0 taken
416: branch 1 taken
70 2231: while (*s != '\0') {
71 : // Skip '_'.
54: branch 0 taken
1309: branch 1 taken
72 1363: if (*s == '_') {
46: branch 0 taken
8: branch 1 taken
73 54: if (InPossiblePrefix) {
74 : // If we already have a convention, return it. Otherwise, skip
75 : // the prefix as if it wasn't there.
12: branch 0 taken
34: branch 1 taken
76 46: if (C != NoConvention)
77 12: break;
78 :
79 34: InPossiblePrefix = false;
80 34: AtBeginning = true;
0: branch 0 not taken
34: branch 1 taken
81 34: assert(C == NoConvention);
82 : }
83 42: ++s;
84 42: continue;
85 : }
86 :
87 : // Skip numbers, ':', etc.
132: branch 1 taken
1177: branch 2 taken
88 1309: if (!isalpha(*s)) {
89 132: ++s;
90 132: continue;
91 : }
92 :
93 1177: const char *wordEnd = parseWord(s);
0: branch 0 not taken
1177: branch 1 taken
94 1177: assert(wordEnd > s);
95 1177: unsigned len = wordEnd - s;
96 :
572: branch 0 taken
154: branch 1 taken
338: branch 2 taken
113: branch 3 taken
97 1177: switch (len) {
98 : default:
99 572: break;
100 : case 3:
101 : // Methods starting with 'new' follow the create rule.
86: branch 0 taken
68: branch 1 taken
34: branch 5 taken
52: branch 6 taken
34: branch 7 taken
120: branch 8 taken
102 154: if (AtBeginning && StringRef(s, len).equals_lower("new"))
103 34: C = CreateRule;
104 154: break;
105 : case 4:
106 : // Methods starting with 'alloc' or contain 'copy' follow the
107 : // create rule
221: branch 0 taken
117: branch 1 taken
32: branch 5 taken
189: branch 6 taken
32: branch 7 taken
306: branch 8 taken
108 338: if (C == NoConvention && StringRef(s, len).equals_lower("copy"))
109 32: C = CreateRule;
110 : else // Methods starting with 'init' follow the init rule.
135: branch 0 taken
171: branch 1 taken
95: branch 5 taken
40: branch 6 taken
95: branch 7 taken
211: branch 8 taken
111 306: if (AtBeginning && StringRef(s, len).equals_lower("init"))
112 95: C = InitRule;
113 338: break;
114 : case 5:
52: branch 0 taken
61: branch 1 taken
0: branch 5 not taken
52: branch 6 taken
0: branch 7 not taken
113: branch 8 taken
115 113: if (AtBeginning && StringRef(s, len).equals_lower("alloc"))
116 0: C = CreateRule;
117 : break;
118 : }
119 :
120 : // If we aren't in the prefix and have a derived convention then just
121 : // return it now.
54: branch 0 taken
1123: branch 1 taken
24: branch 2 taken
30: branch 3 taken
122 1177: if (!InPossiblePrefix && C != NoConvention)
123 24: return C;
124 :
125 1153: AtBeginning = false;
126 1153: s = wordEnd;
127 : }
128 :
129 : // We will get here if there wasn't more than one word
130 : // after the prefix.
131 428: return C;
132 : }
133 :
134 : bool cocoa::isRefType(QualType RetTy, llvm::StringRef Prefix,
135 2103: llvm::StringRef Name) {
136 : // Recursively walk the typedef stack, allowing typedefs of reference types.
902: branch 2 taken
1201: branch 3 taken
137 2640: while (TypedefType* TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) {
138 902: llvm::StringRef TDName = TD->getDecl()->getIdentifier()->getName();
365: branch 1 taken
537: branch 2 taken
365: branch 5 taken
0: branch 6 not taken
365: branch 7 taken
537: branch 8 taken
139 902: if (TDName.startswith(Prefix) && TDName.endswith("Ref"))
140 365: return true;
141 :
142 537: RetTy = TD->getDecl()->getUnderlyingType();
143 : }
144 :
895: branch 1 taken
306: branch 2 taken
145 1201: if (Name.empty())
146 895: return false;
147 :
148 : // Is the type void*?
149 306: const PointerType* PT = RetTy->getAs<PointerType>();
148: branch 4 taken
158: branch 5 taken
150 306: if (!(PT->getPointeeType().getUnqualifiedType()->isVoidType()))
151 148: return false;
152 :
153 : // Does the name start with the prefix?
154 158: return Name.startswith(Prefix);
155 : }
156 :
157 119: bool cocoa::isCFObjectRef(QualType T) {
158 : return isRefType(T, "CF") || // Core Foundation.
159 : isRefType(T, "CG") || // Core Graphics.
160 : isRefType(T, "DADisk") || // Disk Arbitration API.
161 : isRefType(T, "DADissenter") ||
101: branch 3 taken
18: branch 4 taken
101: branch 8 taken
0: branch 9 not taken
101: branch 13 taken
0: branch 14 not taken
101: branch 18 taken
0: branch 19 not taken
0: branch 23 not taken
101: branch 24 taken
162 119: isRefType(T, "DASessionRef");
163 : }
164 :
165 :
166 1966: bool cocoa::isCocoaObjectRef(QualType Ty) {
1440: branch 2 taken
526: branch 3 taken
167 1966: if (!Ty->isObjCObjectPointerType())
168 1440: return false;
169 :
170 526: const ObjCObjectPointerType *PT = Ty->getAs<ObjCObjectPointerType>();
171 :
172 : // Can be true for objects with the 'NSObject' attribute.
0: branch 0 not taken
526: branch 1 taken
173 526: if (!PT)
174 0: return true;
175 :
176 : // We assume that id<..>, id, and "Class" all represent tracked objects.
166: branch 1 taken
360: branch 2 taken
166: branch 4 taken
0: branch 5 not taken
12: branch 7 taken
154: branch 8 taken
372: branch 9 taken
154: branch 10 taken
177 526: if (PT->isObjCIdType() || PT->isObjCQualifiedIdType() ||
178 : PT->isObjCClassType())
179 372: return true;
180 :
181 : // Does the interface subclass NSObject?
182 : // FIXME: We can memoize here if this gets too expensive.
183 154: const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
184 :
185 : // Assume that anything declared with a forward declaration and no
186 : // @interface subclasses NSObject.
4: branch 1 taken
150: branch 2 taken
187 154: if (ID->isForwardDecl())
188 4: return true;
189 :
286: branch 1 taken
2: branch 2 taken
190 288: for ( ; ID ; ID = ID->getSuperClass())
148: branch 4 taken
138: branch 5 taken
191 286: if (ID->getIdentifier()->getName() == "NSObject")
192 148: return true;
193 :
194 2: return false;
195 : }
Generated: 2010-02-10 01:31 by zcov