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