blob: 9580e0cbf8571de5fd20c2074e9bfabd8da86e3b [file] [log] [blame]
Chris Lattner10318b82008-03-16 00:19:01 +00001//===--- DeclObjC.cpp - ObjC Declaration AST Node Implementation ----------===//
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 implements the Objective-C related Decl classes.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/DeclObjC.h"
15#include "clang/AST/ASTContext.h"
16using namespace clang;
17
Chris Lattner114add62008-03-16 00:49:28 +000018//===----------------------------------------------------------------------===//
19// ObjC Decl Allocation/Deallocation Method Implementations
20//===----------------------------------------------------------------------===//
21
22ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C, SourceLocation beginLoc,
23 SourceLocation endLoc,
24 Selector SelInfo, QualType T,
25 Decl *contextDecl,
Chris Lattner114add62008-03-16 00:49:28 +000026 AttributeList *M, bool isInstance,
27 bool isVariadic,
Chris Lattnerf7355832008-03-16 00:58:16 +000028 ImplementationControl impControl) {
Chris Lattner114add62008-03-16 00:49:28 +000029 void *Mem = C.getAllocator().Allocate<ObjCMethodDecl>();
30 return new (Mem) ObjCMethodDecl(beginLoc, endLoc, SelInfo, T, contextDecl,
Chris Lattnerf7355832008-03-16 00:58:16 +000031 M, isInstance,
32 isVariadic, impControl);
Chris Lattner114add62008-03-16 00:49:28 +000033
34}
35
Chris Lattner10318b82008-03-16 00:19:01 +000036
37//===----------------------------------------------------------------------===//
38// Objective-C Decl Implementation
39//===----------------------------------------------------------------------===//
40
41void ObjCMethodDecl::setMethodParams(ParmVarDecl **NewParamInfo,
42 unsigned NumParams) {
43 assert(ParamInfo == 0 && "Already has param info!");
44
45 // Zero params -> null pointer.
46 if (NumParams) {
47 ParamInfo = new ParmVarDecl*[NumParams];
48 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
49 NumMethodParams = NumParams;
50 }
51}
52
53ObjCMethodDecl::~ObjCMethodDecl() {
54 delete[] ParamInfo;
55}
56
57/// ObjCAddInstanceVariablesToClass - Inserts instance variables
58/// into ObjCInterfaceDecl's fields.
59///
60void ObjCInterfaceDecl::addInstanceVariablesToClass(ObjCIvarDecl **ivars,
61 unsigned numIvars,
62 SourceLocation RBrac) {
63 NumIvars = numIvars;
64 if (numIvars) {
65 Ivars = new ObjCIvarDecl*[numIvars];
66 memcpy(Ivars, ivars, numIvars*sizeof(ObjCIvarDecl*));
67 }
68 setLocEnd(RBrac);
69}
70
71/// ObjCAddInstanceVariablesToClassImpl - Checks for correctness of Instance
72/// Variables (Ivars) relative to what declared in @implementation;s class.
73/// Ivars into ObjCImplementationDecl's fields.
74///
75void ObjCImplementationDecl::ObjCAddInstanceVariablesToClassImpl(
76 ObjCIvarDecl **ivars, unsigned numIvars) {
77 NumIvars = numIvars;
78 if (numIvars) {
79 Ivars = new ObjCIvarDecl*[numIvars];
80 memcpy(Ivars, ivars, numIvars*sizeof(ObjCIvarDecl*));
81 }
82}
83
84/// addMethods - Insert instance and methods declarations into
85/// ObjCInterfaceDecl's InsMethods and ClsMethods fields.
86///
87void ObjCInterfaceDecl::addMethods(ObjCMethodDecl **insMethods,
88 unsigned numInsMembers,
89 ObjCMethodDecl **clsMethods,
90 unsigned numClsMembers,
91 SourceLocation endLoc) {
92 NumInstanceMethods = numInsMembers;
93 if (numInsMembers) {
94 InstanceMethods = new ObjCMethodDecl*[numInsMembers];
95 memcpy(InstanceMethods, insMethods, numInsMembers*sizeof(ObjCMethodDecl*));
96 }
97 NumClassMethods = numClsMembers;
98 if (numClsMembers) {
99 ClassMethods = new ObjCMethodDecl*[numClsMembers];
100 memcpy(ClassMethods, clsMethods, numClsMembers*sizeof(ObjCMethodDecl*));
101 }
102 AtEndLoc = endLoc;
103}
104
105/// addMethods - Insert instance and methods declarations into
106/// ObjCProtocolDecl's ProtoInsMethods and ProtoClsMethods fields.
107///
108void ObjCProtocolDecl::addMethods(ObjCMethodDecl **insMethods,
109 unsigned numInsMembers,
110 ObjCMethodDecl **clsMethods,
111 unsigned numClsMembers,
112 SourceLocation endLoc) {
113 NumInstanceMethods = numInsMembers;
114 if (numInsMembers) {
115 InstanceMethods = new ObjCMethodDecl*[numInsMembers];
116 memcpy(InstanceMethods, insMethods, numInsMembers*sizeof(ObjCMethodDecl*));
117 }
118 NumClassMethods = numClsMembers;
119 if (numClsMembers) {
120 ClassMethods = new ObjCMethodDecl*[numClsMembers];
121 memcpy(ClassMethods, clsMethods, numClsMembers*sizeof(ObjCMethodDecl*));
122 }
123 AtEndLoc = endLoc;
124}
125
126/// addMethods - Insert instance and methods declarations into
127/// ObjCCategoryDecl's CatInsMethods and CatClsMethods fields.
128///
129void ObjCCategoryDecl::addMethods(ObjCMethodDecl **insMethods,
130 unsigned numInsMembers,
131 ObjCMethodDecl **clsMethods,
132 unsigned numClsMembers,
133 SourceLocation endLoc) {
134 NumInstanceMethods = numInsMembers;
135 if (numInsMembers) {
136 InstanceMethods = new ObjCMethodDecl*[numInsMembers];
137 memcpy(InstanceMethods, insMethods, numInsMembers*sizeof(ObjCMethodDecl*));
138 }
139 NumClassMethods = numClsMembers;
140 if (numClsMembers) {
141 ClassMethods = new ObjCMethodDecl*[numClsMembers];
142 memcpy(ClassMethods, clsMethods, numClsMembers*sizeof(ObjCMethodDecl*));
143 }
144 AtEndLoc = endLoc;
145}
146
147ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(
148 IdentifierInfo *ID, ObjCInterfaceDecl *&clsDeclared) {
149 ObjCInterfaceDecl* ClassDecl = this;
150 while (ClassDecl != NULL) {
151 for (ivar_iterator I = ClassDecl->ivar_begin(), E = ClassDecl->ivar_end();
152 I != E; ++I) {
153 if ((*I)->getIdentifier() == ID) {
154 clsDeclared = ClassDecl;
155 return *I;
156 }
157 }
158 ClassDecl = ClassDecl->getSuperClass();
159 }
160 return NULL;
161}
162
163/// lookupInstanceMethod - This method returns an instance method by looking in
164/// the class, its categories, and its super classes (using a linear search).
165ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(Selector Sel) {
166 ObjCInterfaceDecl* ClassDecl = this;
167 ObjCMethodDecl *MethodDecl = 0;
168
169 while (ClassDecl != NULL) {
170 if ((MethodDecl = ClassDecl->getInstanceMethod(Sel)))
171 return MethodDecl;
172
173 // Didn't find one yet - look through protocols.
174 ObjCProtocolDecl **protocols = ClassDecl->getReferencedProtocols();
175 int numProtocols = ClassDecl->getNumIntfRefProtocols();
176 for (int pIdx = 0; pIdx < numProtocols; pIdx++) {
177 if ((MethodDecl = protocols[pIdx]->getInstanceMethod(Sel)))
178 return MethodDecl;
179 }
180 // Didn't find one yet - now look through categories.
181 ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
182 while (CatDecl) {
183 if ((MethodDecl = CatDecl->getInstanceMethod(Sel)))
184 return MethodDecl;
185 CatDecl = CatDecl->getNextClassCategory();
186 }
187 ClassDecl = ClassDecl->getSuperClass();
188 }
189 return NULL;
190}
191
192// lookupClassMethod - This method returns a class method by looking in the
193// class, its categories, and its super classes (using a linear search).
194ObjCMethodDecl *ObjCInterfaceDecl::lookupClassMethod(Selector Sel) {
195 ObjCInterfaceDecl* ClassDecl = this;
196 ObjCMethodDecl *MethodDecl = 0;
197
198 while (ClassDecl != NULL) {
199 if ((MethodDecl = ClassDecl->getClassMethod(Sel)))
200 return MethodDecl;
201
202 // Didn't find one yet - look through protocols.
203 ObjCProtocolDecl **protocols = ClassDecl->getReferencedProtocols();
204 int numProtocols = ClassDecl->getNumIntfRefProtocols();
205 for (int pIdx = 0; pIdx < numProtocols; pIdx++) {
206 if ((MethodDecl = protocols[pIdx]->getClassMethod(Sel)))
207 return MethodDecl;
208 }
209 // Didn't find one yet - now look through categories.
210 ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
211 while (CatDecl) {
212 if ((MethodDecl = CatDecl->getClassMethod(Sel)))
213 return MethodDecl;
214 CatDecl = CatDecl->getNextClassCategory();
215 }
216 ClassDecl = ClassDecl->getSuperClass();
217 }
218 return NULL;
219}
220
221/// lookupInstanceMethod - This method returns an instance method by looking in
222/// the class implementation. Unlike interfaces, we don't look outside the
223/// implementation.
224ObjCMethodDecl *ObjCImplementationDecl::getInstanceMethod(Selector Sel) {
225 for (instmeth_iterator I = instmeth_begin(), E = instmeth_end(); I != E; ++I)
226 if ((*I)->getSelector() == Sel)
227 return *I;
228 return NULL;
229}
230
231/// lookupClassMethod - This method returns a class method by looking in
232/// the class implementation. Unlike interfaces, we don't look outside the
233/// implementation.
234ObjCMethodDecl *ObjCImplementationDecl::getClassMethod(Selector Sel) {
235 for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
236 I != E; ++I)
237 if ((*I)->getSelector() == Sel)
238 return *I;
239 return NULL;
240}
241
242// lookupInstanceMethod - This method returns an instance method by looking in
243// the class implementation. Unlike interfaces, we don't look outside the
244// implementation.
245ObjCMethodDecl *ObjCCategoryImplDecl::getInstanceMethod(Selector Sel) {
246 for (instmeth_iterator I = instmeth_begin(), E = instmeth_end(); I != E; ++I)
247 if ((*I)->getSelector() == Sel)
248 return *I;
249 return NULL;
250}
251
252// lookupClassMethod - This method returns an instance method by looking in
253// the class implementation. Unlike interfaces, we don't look outside the
254// implementation.
255ObjCMethodDecl *ObjCCategoryImplDecl::getClassMethod(Selector Sel) {
256 for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
257 I != E; ++I)
258 if ((*I)->getSelector() == Sel)
259 return *I;
260 return NULL;
261}
262
263// lookupInstanceMethod - Lookup a instance method in the protocol and protocols
264// it inherited.
265ObjCMethodDecl *ObjCProtocolDecl::lookupInstanceMethod(Selector Sel) {
266 ObjCMethodDecl *MethodDecl = NULL;
267
268 if ((MethodDecl = getInstanceMethod(Sel)))
269 return MethodDecl;
270
271 if (getNumReferencedProtocols() > 0) {
272 ObjCProtocolDecl **RefPDecl = getReferencedProtocols();
273
274 for (unsigned i = 0; i < getNumReferencedProtocols(); i++) {
275 if ((MethodDecl = RefPDecl[i]->getInstanceMethod(Sel)))
276 return MethodDecl;
277 }
278 }
279 return NULL;
280}
281
282// lookupInstanceMethod - Lookup a class method in the protocol and protocols
283// it inherited.
284ObjCMethodDecl *ObjCProtocolDecl::lookupClassMethod(Selector Sel) {
285 ObjCMethodDecl *MethodDecl = NULL;
286
287 if ((MethodDecl = getClassMethod(Sel)))
288 return MethodDecl;
289
290 if (getNumReferencedProtocols() > 0) {
291 ObjCProtocolDecl **RefPDecl = getReferencedProtocols();
292
293 for(unsigned i = 0; i < getNumReferencedProtocols(); i++) {
294 if ((MethodDecl = RefPDecl[i]->getClassMethod(Sel)))
295 return MethodDecl;
296 }
297 }
298 return NULL;
299}
300
301/// getSynthesizedMethodSize - Compute size of synthesized method name
302/// as done be the rewrite.
303///
304unsigned ObjCMethodDecl::getSynthesizedMethodSize() const {
305 // syntesized method name is a concatenation of -/+[class-name selector]
306 // Get length of this name.
307 unsigned length = 3; // _I_ or _C_
308 length += strlen(getClassInterface()->getName()) +1; // extra for _
309 NamedDecl *MethodContext = getMethodContext();
310 if (ObjCCategoryImplDecl *CID =
311 dyn_cast<ObjCCategoryImplDecl>(MethodContext))
312 length += strlen(CID->getName()) +1;
313 length += getSelector().getName().size(); // selector name
314 return length;
315}
316
317ObjCInterfaceDecl *const ObjCMethodDecl::getClassInterface() const {
318 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(MethodContext))
319 return ID;
320 if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(MethodContext))
321 return CD->getClassInterface();
322 if (ObjCImplementationDecl *IMD =
323 dyn_cast<ObjCImplementationDecl>(MethodContext))
324 return IMD->getClassInterface();
325 if (ObjCCategoryImplDecl *CID =
326 dyn_cast<ObjCCategoryImplDecl>(MethodContext))
327 return CID->getClassInterface();
328 assert(false && "unknown method context");
329 return 0;
330}