blob: 05d7e1149536f72572f91cf20c9dd586298f4610 [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"
Daniel Dunbarde300732008-08-11 04:54:23 +000016#include "clang/AST/Stmt.h"
Chris Lattner10318b82008-03-16 00:19:01 +000017using namespace clang;
18
Chris Lattner114add62008-03-16 00:49:28 +000019//===----------------------------------------------------------------------===//
20// ObjC Decl Allocation/Deallocation Method Implementations
21//===----------------------------------------------------------------------===//
22
Chris Lattnereee57c02008-04-04 06:12:32 +000023ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
24 SourceLocation beginLoc,
Chris Lattner114add62008-03-16 00:49:28 +000025 SourceLocation endLoc,
26 Selector SelInfo, QualType T,
Steve Naroffab63fd62009-01-08 17:28:14 +000027 DeclContext *contextDecl,
Daniel Dunbard8bd6822008-08-20 18:02:42 +000028 bool isInstance,
Chris Lattner114add62008-03-16 00:49:28 +000029 bool isVariadic,
Fariborz Jahanian5f2e2242008-05-07 20:53:44 +000030 bool isSynthesized,
Chris Lattnerf7355832008-03-16 00:58:16 +000031 ImplementationControl impControl) {
Chris Lattner114add62008-03-16 00:49:28 +000032 void *Mem = C.getAllocator().Allocate<ObjCMethodDecl>();
Chris Lattnereee57c02008-04-04 06:12:32 +000033 return new (Mem) ObjCMethodDecl(beginLoc, endLoc,
34 SelInfo, T, contextDecl,
Daniel Dunbard8bd6822008-08-20 18:02:42 +000035 isInstance,
Fariborz Jahanian5f2e2242008-05-07 20:53:44 +000036 isVariadic, isSynthesized, impControl);
Chris Lattner0db541b2008-03-16 01:15:50 +000037}
Chris Lattner114add62008-03-16 00:49:28 +000038
Ted Kremenek8c945b12008-06-06 16:45:15 +000039ObjCMethodDecl::~ObjCMethodDecl() {
40 delete [] ParamInfo;
Ted Kremenek8c945b12008-06-06 16:45:15 +000041}
42
43void ObjCMethodDecl::Destroy(ASTContext& C) {
44 if (Body) Body->Destroy(C);
45 if (SelfDecl) SelfDecl->Destroy(C);
46
47 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
48 if (*I) (*I)->Destroy(C);
49
50 Decl::Destroy(C);
51}
52
Chris Lattnereee57c02008-04-04 06:12:32 +000053ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C,
54 SourceLocation atLoc,
Steve Naroff7c371742008-04-11 19:35:35 +000055 IdentifierInfo *Id,
56 SourceLocation ClassLoc,
Chris Lattner0db541b2008-03-16 01:15:50 +000057 bool ForwardDecl, bool isInternal){
58 void *Mem = C.getAllocator().Allocate<ObjCInterfaceDecl>();
Chris Lattner5cece462008-07-21 07:06:49 +000059 return new (Mem) ObjCInterfaceDecl(atLoc, Id, ClassLoc, ForwardDecl,
Chris Lattner0db541b2008-03-16 01:15:50 +000060 isInternal);
61}
62
Steve Naroffd9d4d502009-01-07 17:57:40 +000063ObjCContainerDecl::~ObjCContainerDecl() {
Steve Naroffd9d4d502009-01-07 17:57:40 +000064}
65
66ObjCInterfaceDecl::~ObjCInterfaceDecl() {
67 delete [] Ivars;
Ted Kremenek8c945b12008-06-06 16:45:15 +000068 delete [] PropertyDecl;
69 // FIXME: CategoryList?
70}
71
72void ObjCInterfaceDecl::Destroy(ASTContext& C) {
73 for (ivar_iterator I=ivar_begin(), E=ivar_end(); I!=E; ++I)
74 if (*I) (*I)->Destroy(C);
75
76 for (instmeth_iterator I=instmeth_begin(), E=instmeth_end(); I!=E; ++I)
77 if (*I) (*I)->Destroy(C);
78
79 for (classmeth_iterator I=classmeth_begin(), E=classmeth_end(); I!=E; ++I)
80 if (*I) (*I)->Destroy(C);
Ted Kremenek22db1602008-06-06 17:21:42 +000081
82 // FIXME: Because there is no clear ownership
83 // role between ObjCInterfaceDecls and the ObjCPropertyDecls that they
84 // reference, we destroy ObjCPropertyDecls in ~TranslationUnit.
85
Ted Kremenek8c945b12008-06-06 16:45:15 +000086 Decl::Destroy(C);
87}
88
89
Chris Lattnerf3874bc2008-04-06 04:47:34 +000090ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, SourceLocation L,
Ted Kremenek173dd312008-07-23 18:04:17 +000091 IdentifierInfo *Id, QualType T,
92 AccessControl ac, Expr *BW) {
Chris Lattner0db541b2008-03-16 01:15:50 +000093 void *Mem = C.getAllocator().Allocate<ObjCIvarDecl>();
Ted Kremenek173dd312008-07-23 18:04:17 +000094 return new (Mem) ObjCIvarDecl(L, Id, T, ac, BW);
Chris Lattner114add62008-03-16 00:49:28 +000095}
96
Ted Kremeneke5bedfe2008-08-20 03:26:33 +000097
98ObjCAtDefsFieldDecl
Douglas Gregor8acb7272008-12-11 16:49:14 +000099*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
Ted Kremeneke5bedfe2008-08-20 03:26:33 +0000100 IdentifierInfo *Id, QualType T, Expr *BW) {
101 void *Mem = C.getAllocator().Allocate<ObjCAtDefsFieldDecl>();
Douglas Gregor8acb7272008-12-11 16:49:14 +0000102 return new (Mem) ObjCAtDefsFieldDecl(DC, L, Id, T, BW);
Ted Kremeneke5bedfe2008-08-20 03:26:33 +0000103}
104
105void ObjCAtDefsFieldDecl::Destroy(ASTContext& C) {
106 this->~ObjCAtDefsFieldDecl();
107 C.getAllocator().Deallocate((void *)this);
108}
109
Chris Lattnereee57c02008-04-04 06:12:32 +0000110ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C,
111 SourceLocation L,
Chris Lattner7afba9c2008-03-16 20:19:15 +0000112 IdentifierInfo *Id) {
Chris Lattner180f7e22008-03-16 01:23:04 +0000113 void *Mem = C.getAllocator().Allocate<ObjCProtocolDecl>();
Chris Lattner0be08822008-07-21 21:32:27 +0000114 return new (Mem) ObjCProtocolDecl(L, Id);
Chris Lattner180f7e22008-03-16 01:23:04 +0000115}
116
Ted Kremenekc906e5e2008-06-06 19:48:57 +0000117ObjCProtocolDecl::~ObjCProtocolDecl() {
Ted Kremenekc906e5e2008-06-06 19:48:57 +0000118 delete [] PropertyDecl;
119}
120
121void ObjCProtocolDecl::Destroy(ASTContext& C) {
122
123 // Referenced Protocols are not owned, so don't Destroy them.
124
125 for (instmeth_iterator I=instmeth_begin(), E=instmeth_end(); I!=E; ++I)
126 if (*I) (*I)->Destroy(C);
127
128 for (classmeth_iterator I=classmeth_begin(), E=classmeth_end(); I!=E; ++I)
129 if (*I) (*I)->Destroy(C);
130
131 // FIXME: Because there is no clear ownership
132 // role between ObjCProtocolDecls and the ObjCPropertyDecls that they
133 // reference, we destroy ObjCPropertyDecls in ~TranslationUnit.
134
135 Decl::Destroy(C);
136}
137
138
Chris Lattnereee57c02008-04-04 06:12:32 +0000139ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C,
140 SourceLocation L,
Chris Lattnere29dc832008-03-16 20:34:23 +0000141 ObjCInterfaceDecl **Elts, unsigned nElts) {
142 void *Mem = C.getAllocator().Allocate<ObjCClassDecl>();
143 return new (Mem) ObjCClassDecl(L, Elts, nElts);
144}
145
Ted Kremenekff291622008-06-06 20:11:53 +0000146ObjCClassDecl::~ObjCClassDecl() {
147 delete [] ForwardDecls;
148}
149
150void ObjCClassDecl::Destroy(ASTContext& C) {
151
152 // FIXME: There is no clear ownership policy now for referenced
153 // ObjCInterfaceDecls. Some of them can be forward declarations that
154 // are never later defined (in which case the ObjCClassDecl owns them)
155 // or the ObjCInterfaceDecl later becomes a real definition later. Ideally
156 // we should have separate objects for forward declarations and definitions,
157 // obviating this problem. Because of this situation, referenced
158 // ObjCInterfaceDecls are destroyed in ~TranslationUnit.
159
160 Decl::Destroy(C);
161}
162
Chris Lattnere29dc832008-03-16 20:34:23 +0000163ObjCForwardProtocolDecl *
Chris Lattnereee57c02008-04-04 06:12:32 +0000164ObjCForwardProtocolDecl::Create(ASTContext &C,
165 SourceLocation L,
Chris Lattnere29dc832008-03-16 20:34:23 +0000166 ObjCProtocolDecl **Elts, unsigned NumElts) {
167 void *Mem = C.getAllocator().Allocate<ObjCForwardProtocolDecl>();
168 return new (Mem) ObjCForwardProtocolDecl(L, Elts, NumElts);
169}
170
Ted Kremenek1e5e0bf2008-06-06 21:05:33 +0000171ObjCForwardProtocolDecl::~ObjCForwardProtocolDecl() {
172 delete [] ReferencedProtocols;
173}
174
Chris Lattnereee57c02008-04-04 06:12:32 +0000175ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C,
176 SourceLocation L,
Chris Lattnere29dc832008-03-16 20:34:23 +0000177 IdentifierInfo *Id) {
178 void *Mem = C.getAllocator().Allocate<ObjCCategoryDecl>();
Chris Lattner321b5d12008-03-16 20:47:45 +0000179 return new (Mem) ObjCCategoryDecl(L, Id);
Chris Lattnere29dc832008-03-16 20:34:23 +0000180}
181
Chris Lattner1b6de332008-03-16 20:53:07 +0000182ObjCCategoryImplDecl *
Chris Lattnereee57c02008-04-04 06:12:32 +0000183ObjCCategoryImplDecl::Create(ASTContext &C,
184 SourceLocation L,IdentifierInfo *Id,
Chris Lattner1b6de332008-03-16 20:53:07 +0000185 ObjCInterfaceDecl *ClassInterface) {
186 void *Mem = C.getAllocator().Allocate<ObjCCategoryImplDecl>();
187 return new (Mem) ObjCCategoryImplDecl(L, Id, ClassInterface);
188}
189
190ObjCImplementationDecl *
Chris Lattnereee57c02008-04-04 06:12:32 +0000191ObjCImplementationDecl::Create(ASTContext &C,
192 SourceLocation L,
Chris Lattner1b6de332008-03-16 20:53:07 +0000193 IdentifierInfo *Id,
194 ObjCInterfaceDecl *ClassInterface,
195 ObjCInterfaceDecl *SuperDecl) {
196 void *Mem = C.getAllocator().Allocate<ObjCImplementationDecl>();
197 return new (Mem) ObjCImplementationDecl(L, Id, ClassInterface, SuperDecl);
198}
Chris Lattner10318b82008-03-16 00:19:01 +0000199
Chris Lattner2d1c4312008-03-16 21:17:37 +0000200ObjCCompatibleAliasDecl *
Chris Lattnereee57c02008-04-04 06:12:32 +0000201ObjCCompatibleAliasDecl::Create(ASTContext &C,
202 SourceLocation L,
Chris Lattner2d1c4312008-03-16 21:17:37 +0000203 IdentifierInfo *Id,
204 ObjCInterfaceDecl* AliasedClass) {
205 void *Mem = C.getAllocator().Allocate<ObjCCompatibleAliasDecl>();
206 return new (Mem) ObjCCompatibleAliasDecl(L, Id, AliasedClass);
207}
208
Chris Lattnereee57c02008-04-04 06:12:32 +0000209ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C,
Fariborz Jahaniane7071722008-04-11 23:40:25 +0000210 SourceLocation L,
Fariborz Jahanian0ceb4be2008-04-14 23:36:35 +0000211 IdentifierInfo *Id,
Fariborz Jahanian4aa72a72008-05-05 18:51:55 +0000212 QualType T,
213 PropertyControl propControl) {
Chris Lattner2d1c4312008-03-16 21:17:37 +0000214 void *Mem = C.getAllocator().Allocate<ObjCPropertyDecl>();
Fariborz Jahanian0ceb4be2008-04-14 23:36:35 +0000215 return new (Mem) ObjCPropertyDecl(L, Id, T);
Chris Lattner2d1c4312008-03-16 21:17:37 +0000216}
217
Chris Lattner10318b82008-03-16 00:19:01 +0000218//===----------------------------------------------------------------------===//
219// Objective-C Decl Implementation
220//===----------------------------------------------------------------------===//
221
Fariborz Jahanian91dd9d32008-12-09 20:23:04 +0000222void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
223 const ObjCInterfaceDecl *OID) {
Daniel Dunbar88116372008-08-26 06:08:30 +0000224 QualType selfTy;
225 if (isInstance()) {
226 // There may be no interface context due to error in declaration
227 // of the interface (which has been reported). Recover gracefully.
Fariborz Jahanian91dd9d32008-12-09 20:23:04 +0000228 if (OID) {
229 selfTy = Context.getObjCInterfaceType(const_cast<ObjCInterfaceDecl *>(OID));
Daniel Dunbar88116372008-08-26 06:08:30 +0000230 selfTy = Context.getPointerType(selfTy);
231 } else {
232 selfTy = Context.getObjCIdType();
233 }
234 } else // we have a factory method.
235 selfTy = Context.getObjCClassType();
236
237 SelfDecl = ImplicitParamDecl::Create(Context, this,
238 SourceLocation(),
239 &Context.Idents.get("self"),
240 selfTy, 0);
241
242 CmdDecl = ImplicitParamDecl::Create(Context, this,
243 SourceLocation(),
244 &Context.Idents.get("_cmd"),
245 Context.getObjCSelType(), 0);
246}
247
Chris Lattner10318b82008-03-16 00:19:01 +0000248void ObjCMethodDecl::setMethodParams(ParmVarDecl **NewParamInfo,
249 unsigned NumParams) {
250 assert(ParamInfo == 0 && "Already has param info!");
251
252 // Zero params -> null pointer.
253 if (NumParams) {
254 ParamInfo = new ParmVarDecl*[NumParams];
255 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
256 NumMethodParams = NumParams;
257 }
258}
259
Fariborz Jahanian4739da12008-11-25 21:48:26 +0000260/// isPropertyReadonly - Return true if property is a readonly, by seaching
261/// for the property in the class and in its categories.
262///
263bool ObjCInterfaceDecl::isPropertyReadonly(ObjCPropertyDecl *PDecl) const
264{
265 if (PDecl->isReadOnly()) {
266 // Main class has the property as 'readyonly'. Must search
267 // through the category list to see if the property's
268 // attribute has been over-ridden to 'readwrite'.
269 for (ObjCCategoryDecl *Category = getCategoryList();
270 Category; Category = Category->getNextClassCategory()) {
271 PDecl= Category->FindPropertyDeclaration(PDecl->getIdentifier());
272 if (PDecl && !PDecl->isReadOnly())
273 return false;
274 }
275 return true;
276 }
277 return false;
278}
279
Fariborz Jahanianef8a3df2008-04-21 19:04:53 +0000280/// FindPropertyDeclaration - Finds declaration of the property given its name
281/// in 'PropertyId' and returns it. It returns 0, if not found.
282///
283ObjCPropertyDecl *
284 ObjCInterfaceDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
285 for (ObjCInterfaceDecl::classprop_iterator I = classprop_begin(),
286 E = classprop_end(); I != E; ++I) {
287 ObjCPropertyDecl *property = *I;
288 if (property->getIdentifier() == PropertyId)
289 return property;
290 }
Steve Naroff30faf472008-06-04 04:46:04 +0000291 // Look through categories.
292 for (ObjCCategoryDecl *Category = getCategoryList();
293 Category; Category = Category->getNextClassCategory()) {
294 ObjCPropertyDecl *property = Category->FindPropertyDeclaration(PropertyId);
295 if (property)
296 return property;
297 }
Steve Naroffd1f0eb42008-06-05 13:55:23 +0000298 // Look through protocols.
299 for (ObjCInterfaceDecl::protocol_iterator I = protocol_begin(),
300 E = protocol_end(); I != E; ++I) {
301 ObjCProtocolDecl *Protocol = *I;
302 ObjCPropertyDecl *property = Protocol->FindPropertyDeclaration(PropertyId);
303 if (property)
304 return property;
305 }
Fariborz Jahanian8acf3352008-04-21 23:57:08 +0000306 if (getSuperClass())
307 return getSuperClass()->FindPropertyDeclaration(PropertyId);
Fariborz Jahanianef8a3df2008-04-21 19:04:53 +0000308 return 0;
309}
310
311/// FindCategoryDeclaration - Finds category declaration in the list of
312/// categories for this class and returns it. Name of the category is passed
313/// in 'CategoryId'. If category not found, return 0;
314///
315ObjCCategoryDecl *
316 ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
317 for (ObjCCategoryDecl *Category = getCategoryList();
318 Category; Category = Category->getNextClassCategory())
319 if (Category->getIdentifier() == CategoryId)
320 return Category;
321 return 0;
322}
323
324/// FindIvarDeclaration - Find an Ivar declaration in this class given its
325/// name in 'IvarId'. On failure to find, return 0;
326///
327ObjCIvarDecl *
328 ObjCInterfaceDecl::FindIvarDeclaration(IdentifierInfo *IvarId) const {
329 for (ObjCInterfaceDecl::ivar_iterator IVI = ivar_begin(),
330 IVE = ivar_end(); IVI != IVE; ++IVI) {
331 ObjCIvarDecl* Ivar = (*IVI);
332 if (Ivar->getIdentifier() == IvarId)
333 return Ivar;
334 }
Fariborz Jahanian8acf3352008-04-21 23:57:08 +0000335 if (getSuperClass())
336 return getSuperClass()->FindIvarDeclaration(IvarId);
Fariborz Jahanianef8a3df2008-04-21 19:04:53 +0000337 return 0;
338}
339
Chris Lattner10318b82008-03-16 00:19:01 +0000340/// ObjCAddInstanceVariablesToClass - Inserts instance variables
341/// into ObjCInterfaceDecl's fields.
342///
343void ObjCInterfaceDecl::addInstanceVariablesToClass(ObjCIvarDecl **ivars,
344 unsigned numIvars,
345 SourceLocation RBrac) {
346 NumIvars = numIvars;
347 if (numIvars) {
348 Ivars = new ObjCIvarDecl*[numIvars];
349 memcpy(Ivars, ivars, numIvars*sizeof(ObjCIvarDecl*));
350 }
351 setLocEnd(RBrac);
352}
353
Fariborz Jahanian09772392008-12-13 22:20:28 +0000354/// lookupFieldDeclForIvar - looks up a field decl' in the laid out
355/// storage which matches this 'ivar'.
356///
357FieldDecl *ObjCInterfaceDecl::lookupFieldDeclForIvar(ASTContext &Context,
Fariborz Jahanian86008c02008-12-15 20:35:07 +0000358 const ObjCIvarDecl *ivar) {
Fariborz Jahanian0556b152008-12-17 21:40:49 +0000359 const RecordDecl *RecordForDecl = Context.addRecordToClass(this);
Fariborz Jahanian09772392008-12-13 22:20:28 +0000360 assert(RecordForDecl && "lookupFieldDeclForIvar no storage for class");
361 DeclarationName Member = ivar->getDeclName();
Fariborz Jahanian0556b152008-12-17 21:40:49 +0000362 DeclContext::lookup_result Lookup = (const_cast< RecordDecl *>(RecordForDecl))
Steve Naroffab63fd62009-01-08 17:28:14 +0000363 ->lookup(Member);
Fariborz Jahanian09772392008-12-13 22:20:28 +0000364 assert((Lookup.first != Lookup.second) && "field decl not found");
365 FieldDecl *MemberDecl = dyn_cast<FieldDecl>(*Lookup.first);
366 assert(MemberDecl && "field decl not found");
367 return MemberDecl;
368}
369
Chris Lattner10318b82008-03-16 00:19:01 +0000370/// ObjCAddInstanceVariablesToClassImpl - Checks for correctness of Instance
371/// Variables (Ivars) relative to what declared in @implementation;s class.
372/// Ivars into ObjCImplementationDecl's fields.
373///
374void ObjCImplementationDecl::ObjCAddInstanceVariablesToClassImpl(
375 ObjCIvarDecl **ivars, unsigned numIvars) {
376 NumIvars = numIvars;
377 if (numIvars) {
378 Ivars = new ObjCIvarDecl*[numIvars];
379 memcpy(Ivars, ivars, numIvars*sizeof(ObjCIvarDecl*));
380 }
381}
382
Fariborz Jahanian52ff8442008-04-16 21:08:45 +0000383/// addProperties - Insert property declaration AST nodes into
384/// ObjCInterfaceDecl's PropertyDecl field.
Chris Lattnercffe3662008-03-16 21:23:50 +0000385///
386void ObjCInterfaceDecl::addProperties(ObjCPropertyDecl **Properties,
387 unsigned NumProperties) {
388 if (NumProperties == 0) return;
389
390 NumPropertyDecl = NumProperties;
391 PropertyDecl = new ObjCPropertyDecl*[NumProperties];
392 memcpy(PropertyDecl, Properties, NumProperties*sizeof(ObjCPropertyDecl*));
393}
394
Fariborz Jahanian33973a22008-05-02 19:17:30 +0000395/// mergeProperties - Adds properties to the end of list of current properties
396/// for this class.
397
398void ObjCInterfaceDecl::mergeProperties(ObjCPropertyDecl **Properties,
399 unsigned NumNewProperties) {
400 if (NumNewProperties == 0) return;
401
402 if (PropertyDecl) {
403 ObjCPropertyDecl **newPropertyDecl =
404 new ObjCPropertyDecl*[NumNewProperties + NumPropertyDecl];
405 ObjCPropertyDecl **buf = newPropertyDecl;
406 // put back original properties in buffer.
407 memcpy(buf, PropertyDecl, NumPropertyDecl*sizeof(ObjCPropertyDecl*));
408 // Add new properties to this buffer.
409 memcpy(buf+NumPropertyDecl, Properties,
410 NumNewProperties*sizeof(ObjCPropertyDecl*));
Nuno Lopes1ee78042008-05-10 10:31:54 +0000411 delete[] PropertyDecl;
Fariborz Jahanian33973a22008-05-02 19:17:30 +0000412 PropertyDecl = newPropertyDecl;
413 NumPropertyDecl += NumNewProperties;
414 }
415 else {
Nuno Lopes1ee78042008-05-10 10:31:54 +0000416 addProperties(Properties, NumNewProperties);
Fariborz Jahanian33973a22008-05-02 19:17:30 +0000417 }
418}
419
Steve Naroffab63fd62009-01-08 17:28:14 +0000420// Get the local instance method declared in this interface.
421// FIXME: handle overloading, instance & class methods can have the same name.
422ObjCMethodDecl *ObjCContainerDecl::getInstanceMethod(Selector Sel) const {
423 lookup_const_result MethodResult = lookup(Sel);
424 if (MethodResult.first)
425 return const_cast<ObjCMethodDecl*>(
426 dyn_cast<ObjCMethodDecl>(*MethodResult.first));
427 return 0;
428}
429
430// Get the local class method declared in this interface.
431ObjCMethodDecl *ObjCContainerDecl::getClassMethod(Selector Sel) const {
432 lookup_const_result MethodResult = lookup(Sel);
433 if (MethodResult.first)
434 return const_cast<ObjCMethodDecl*>(
435 dyn_cast<ObjCMethodDecl>(*MethodResult.first));
436 return 0;
437}
438
439unsigned ObjCContainerDecl::getNumInstanceMethods() const {
440 unsigned sum = 0;
441 for (instmeth_iterator I=instmeth_begin(), E=instmeth_end(); I != E; ++I)
442 sum++;
443 return sum;
444}
445unsigned ObjCContainerDecl::getNumClassMethods() const {
446 unsigned sum = 0;
447 for (classmeth_iterator I=classmeth_begin(), E=classmeth_end(); I != E; ++I)
448 sum++;
449 return sum;
450}
451
452/// addPropertyMethods - Goes through list of properties declared in this class
453/// and builds setter/getter method declartions depending on the setter/getter
454/// attributes of the property.
455///
456void ObjCContainerDecl::getPropertyMethods(
457 ASTContext &Context, ObjCPropertyDecl *property,
458 ObjCMethodDecl *& GetterDecl, ObjCMethodDecl *&SetterDecl) {
Daniel Dunbardd24b9a2008-08-26 06:53:45 +0000459 // FIXME: The synthesized property we set here is misleading. We
460 // almost always synthesize these methods unless the user explicitly
461 // provided prototypes (which is odd, but allowed). Sema should be
462 // typechecking that the declarations jive in that situation (which
463 // it is not currently).
464
Fariborz Jahaniane4534e72008-05-07 17:43:59 +0000465 // Find the default getter and if one not found, add one.
Daniel Dunbar70cdeaa2008-08-26 02:32:45 +0000466 if (!GetterDecl) {
Fariborz Jahaniane4534e72008-05-07 17:43:59 +0000467 // No instance method of same name as property getter name was found.
468 // Declare a getter method and add it to the list of methods
469 // for this class.
Daniel Dunbar70cdeaa2008-08-26 02:32:45 +0000470 GetterDecl =
471 ObjCMethodDecl::Create(Context, property->getLocation(),
472 property->getLocation(),
473 property->getGetterName(),
Steve Naroffab63fd62009-01-08 17:28:14 +0000474 property->getType(), this,
Fariborz Jahanian2255ed32008-12-22 20:41:58 +0000475 true, false, true,
476 (property->getPropertyImplementation() ==
477 ObjCPropertyDecl::Optional) ?
478 ObjCMethodDecl::Optional :
479 ObjCMethodDecl::Required);
Fariborz Jahaniane4534e72008-05-07 17:43:59 +0000480 }
Fariborz Jahanian0b7716c2008-12-09 22:43:22 +0000481 else
482 // A user declared getter will be synthesize when @synthesize of
483 // the property with the same name is seen in the @implementation
484 GetterDecl->setIsSynthesized();
Daniel Dunbar70cdeaa2008-08-26 02:32:45 +0000485 property->setGetterMethodDecl(GetterDecl);
486
Daniel Dunbardb3b4492008-08-26 07:16:44 +0000487 // Skip setter if property is read-only.
488 if (property->isReadOnly())
489 return;
490
Daniel Dunbar70cdeaa2008-08-26 02:32:45 +0000491 // Find the default setter and if one not found, add one.
Daniel Dunbar70cdeaa2008-08-26 02:32:45 +0000492 if (!SetterDecl) {
493 // No instance method of same name as property setter name was found.
494 // Declare a setter method and add it to the list of methods
495 // for this class.
496 SetterDecl =
497 ObjCMethodDecl::Create(Context, property->getLocation(),
498 property->getLocation(),
499 property->getSetterName(),
Steve Naroffab63fd62009-01-08 17:28:14 +0000500 Context.VoidTy, this,
Fariborz Jahanian2255ed32008-12-22 20:41:58 +0000501 true, false, true,
502 (property->getPropertyImplementation() ==
503 ObjCPropertyDecl::Optional) ?
504 ObjCMethodDecl::Optional :
505 ObjCMethodDecl::Required);
Daniel Dunbar70cdeaa2008-08-26 02:32:45 +0000506 // Invent the arguments for the setter. We don't bother making a
507 // nice name for the argument.
508 ParmVarDecl *Argument = ParmVarDecl::Create(Context,
509 SetterDecl,
510 SourceLocation(),
511 property->getIdentifier(),
512 property->getType(),
513 VarDecl::None,
514 0, 0);
515 SetterDecl->setMethodParams(&Argument, 1);
516 }
Fariborz Jahanian0b7716c2008-12-09 22:43:22 +0000517 else
518 // A user declared setter will be synthesize when @synthesize of
519 // the property with the same name is seen in the @implementation
520 SetterDecl->setIsSynthesized();
Daniel Dunbar70cdeaa2008-08-26 02:32:45 +0000521 property->setSetterMethodDecl(SetterDecl);
Fariborz Jahaniane4534e72008-05-07 17:43:59 +0000522}
523
Fariborz Jahanianacad6d12008-12-06 23:03:39 +0000524/// mergeProperties - Adds properties to the end of list of current properties
525/// for this category.
526
527void ObjCCategoryDecl::mergeProperties(ObjCPropertyDecl **Properties,
528 unsigned NumNewProperties) {
529 if (NumNewProperties == 0) return;
530
531 if (PropertyDecl) {
532 ObjCPropertyDecl **newPropertyDecl =
533 new ObjCPropertyDecl*[NumNewProperties + NumPropertyDecl];
534 ObjCPropertyDecl **buf = newPropertyDecl;
535 // put back original properties in buffer.
536 memcpy(buf, PropertyDecl, NumPropertyDecl*sizeof(ObjCPropertyDecl*));
537 // Add new properties to this buffer.
538 memcpy(buf+NumPropertyDecl, Properties,
539 NumNewProperties*sizeof(ObjCPropertyDecl*));
540 delete[] PropertyDecl;
541 PropertyDecl = newPropertyDecl;
542 NumPropertyDecl += NumNewProperties;
543 }
544 else {
545 addProperties(Properties, NumNewProperties);
546 }
547}
548
Fariborz Jahanian52ff8442008-04-16 21:08:45 +0000549/// addProperties - Insert property declaration AST nodes into
Fariborz Jahanian8516e9a2008-04-17 18:25:18 +0000550/// ObjCProtocolDecl's PropertyDecl field.
551///
552void ObjCProtocolDecl::addProperties(ObjCPropertyDecl **Properties,
553 unsigned NumProperties) {
554 if (NumProperties == 0) return;
555
556 NumPropertyDecl = NumProperties;
557 PropertyDecl = new ObjCPropertyDecl*[NumProperties];
558 memcpy(PropertyDecl, Properties, NumProperties*sizeof(ObjCPropertyDecl*));
559}
560
561/// addProperties - Insert property declaration AST nodes into
Fariborz Jahanian5742a0f2008-04-16 21:11:25 +0000562/// ObjCCategoryDecl's PropertyDecl field.
Fariborz Jahanian52ff8442008-04-16 21:08:45 +0000563///
564void ObjCCategoryDecl::addProperties(ObjCPropertyDecl **Properties,
565 unsigned NumProperties) {
566 if (NumProperties == 0) return;
567
568 NumPropertyDecl = NumProperties;
569 PropertyDecl = new ObjCPropertyDecl*[NumProperties];
570 memcpy(PropertyDecl, Properties, NumProperties*sizeof(ObjCPropertyDecl*));
571}
572
Fariborz Jahanianef8a3df2008-04-21 19:04:53 +0000573/// FindPropertyDeclaration - Finds declaration of the property given its name
574/// in 'PropertyId' and returns it. It returns 0, if not found.
575///
576ObjCPropertyDecl *
577ObjCCategoryDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
578 for (ObjCCategoryDecl::classprop_iterator I = classprop_begin(),
579 E = classprop_end(); I != E; ++I) {
580 ObjCPropertyDecl *property = *I;
581 if (property->getIdentifier() == PropertyId)
582 return property;
583 }
584 return 0;
585}
586
Steve Naroffd1f0eb42008-06-05 13:55:23 +0000587/// FindPropertyDeclaration - Finds declaration of the property given its name
588/// in 'PropertyId' and returns it. It returns 0, if not found.
589///
590ObjCPropertyDecl *
591ObjCProtocolDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
592 for (ObjCProtocolDecl::classprop_iterator I = classprop_begin(),
593 E = classprop_end(); I != E; ++I) {
594 ObjCPropertyDecl *property = *I;
595 if (property->getIdentifier() == PropertyId)
596 return property;
597 }
598 return 0;
599}
600
Chris Lattner10318b82008-03-16 00:19:01 +0000601ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(
602 IdentifierInfo *ID, ObjCInterfaceDecl *&clsDeclared) {
603 ObjCInterfaceDecl* ClassDecl = this;
604 while (ClassDecl != NULL) {
605 for (ivar_iterator I = ClassDecl->ivar_begin(), E = ClassDecl->ivar_end();
606 I != E; ++I) {
607 if ((*I)->getIdentifier() == ID) {
608 clsDeclared = ClassDecl;
609 return *I;
610 }
611 }
612 ClassDecl = ClassDecl->getSuperClass();
613 }
614 return NULL;
615}
616
617/// lookupInstanceMethod - This method returns an instance method by looking in
618/// the class, its categories, and its super classes (using a linear search).
619ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(Selector Sel) {
620 ObjCInterfaceDecl* ClassDecl = this;
621 ObjCMethodDecl *MethodDecl = 0;
622
623 while (ClassDecl != NULL) {
624 if ((MethodDecl = ClassDecl->getInstanceMethod(Sel)))
625 return MethodDecl;
626
627 // Didn't find one yet - look through protocols.
Chris Lattner8bcb5252008-07-21 18:19:38 +0000628 const ObjCList<ObjCProtocolDecl> &Protocols =
629 ClassDecl->getReferencedProtocols();
630 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
631 E = Protocols.end(); I != E; ++I)
632 if ((MethodDecl = (*I)->getInstanceMethod(Sel)))
Chris Lattner10318b82008-03-16 00:19:01 +0000633 return MethodDecl;
Chris Lattner8bcb5252008-07-21 18:19:38 +0000634
Chris Lattner10318b82008-03-16 00:19:01 +0000635 // Didn't find one yet - now look through categories.
636 ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
637 while (CatDecl) {
638 if ((MethodDecl = CatDecl->getInstanceMethod(Sel)))
639 return MethodDecl;
Steve Naroffaf151802008-12-08 20:57:28 +0000640
641 // Didn't find one yet - look through protocols.
642 const ObjCList<ObjCProtocolDecl> &Protocols =
643 CatDecl->getReferencedProtocols();
644 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
645 E = Protocols.end(); I != E; ++I)
646 if ((MethodDecl = (*I)->getInstanceMethod(Sel)))
647 return MethodDecl;
Chris Lattner10318b82008-03-16 00:19:01 +0000648 CatDecl = CatDecl->getNextClassCategory();
649 }
650 ClassDecl = ClassDecl->getSuperClass();
651 }
652 return NULL;
653}
654
655// lookupClassMethod - This method returns a class method by looking in the
656// class, its categories, and its super classes (using a linear search).
657ObjCMethodDecl *ObjCInterfaceDecl::lookupClassMethod(Selector Sel) {
658 ObjCInterfaceDecl* ClassDecl = this;
659 ObjCMethodDecl *MethodDecl = 0;
660
661 while (ClassDecl != NULL) {
662 if ((MethodDecl = ClassDecl->getClassMethod(Sel)))
663 return MethodDecl;
664
665 // Didn't find one yet - look through protocols.
Chris Lattner0be08822008-07-21 21:32:27 +0000666 for (ObjCInterfaceDecl::protocol_iterator I = ClassDecl->protocol_begin(),
667 E = ClassDecl->protocol_end(); I != E; ++I)
Chris Lattner8bcb5252008-07-21 18:19:38 +0000668 if ((MethodDecl = (*I)->getClassMethod(Sel)))
Chris Lattner10318b82008-03-16 00:19:01 +0000669 return MethodDecl;
Chris Lattner0be08822008-07-21 21:32:27 +0000670
Chris Lattner10318b82008-03-16 00:19:01 +0000671 // Didn't find one yet - now look through categories.
672 ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
673 while (CatDecl) {
674 if ((MethodDecl = CatDecl->getClassMethod(Sel)))
675 return MethodDecl;
676 CatDecl = CatDecl->getNextClassCategory();
677 }
678 ClassDecl = ClassDecl->getSuperClass();
679 }
680 return NULL;
681}
682
Daniel Dunbardd24b9a2008-08-26 06:53:45 +0000683/// getInstanceMethod - This method returns an instance method by
684/// looking in the class implementation. Unlike interfaces, we don't
685/// look outside the implementation.
686ObjCMethodDecl *ObjCImplementationDecl::getInstanceMethod(Selector Sel) const {
Chris Lattner10318b82008-03-16 00:19:01 +0000687 for (instmeth_iterator I = instmeth_begin(), E = instmeth_end(); I != E; ++I)
688 if ((*I)->getSelector() == Sel)
689 return *I;
690 return NULL;
691}
692
Daniel Dunbardd24b9a2008-08-26 06:53:45 +0000693/// getClassMethod - This method returns a class method by looking in
694/// the class implementation. Unlike interfaces, we don't look outside
695/// the implementation.
696ObjCMethodDecl *ObjCImplementationDecl::getClassMethod(Selector Sel) const {
Chris Lattner10318b82008-03-16 00:19:01 +0000697 for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
698 I != E; ++I)
699 if ((*I)->getSelector() == Sel)
700 return *I;
701 return NULL;
702}
703
Fariborz Jahanian68342282008-12-05 22:32:48 +0000704/// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl
705/// added to the list of those properties @synthesized/@dynamic in this
706/// @implementation block.
707///
708ObjCPropertyImplDecl *ObjCImplementationDecl::FindPropertyImplDecl(IdentifierInfo *Id) const {
709 for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i) {
710 ObjCPropertyImplDecl *PID = *i;
711 if (PID->getPropertyDecl()->getIdentifier() == Id)
712 return PID;
713 }
714 return 0;
715}
716
717/// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
Fariborz Jahanian17eb8882008-12-05 22:36:19 +0000718/// properties implemented in this @implementation block and returns the
719/// implemented property that uses it.
Fariborz Jahanian68342282008-12-05 22:32:48 +0000720///
721ObjCPropertyImplDecl *ObjCImplementationDecl::FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
722 for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i) {
723 ObjCPropertyImplDecl *PID = *i;
724 if (PID->getPropertyIvarDecl() &&
725 PID->getPropertyIvarDecl()->getIdentifier() == ivarId)
726 return PID;
727 }
728 return 0;
729}
730
731/// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
Fariborz Jahanian17eb8882008-12-05 22:36:19 +0000732/// properties implemented in this category @implementation block and returns the
733/// implemented property that uses it.
Fariborz Jahanian68342282008-12-05 22:32:48 +0000734///
735ObjCPropertyImplDecl *ObjCCategoryImplDecl::FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
736 for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i) {
737 ObjCPropertyImplDecl *PID = *i;
738 if (PID->getPropertyIvarDecl() &&
739 PID->getPropertyIvarDecl()->getIdentifier() == ivarId)
740 return PID;
741 }
742 return 0;
743}
744
745/// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl
746/// added to the list of those properties @synthesized/@dynamic in this
747/// category @implementation block.
748///
749ObjCPropertyImplDecl *ObjCCategoryImplDecl::FindPropertyImplDecl(IdentifierInfo *Id) const {
750 for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i) {
751 ObjCPropertyImplDecl *PID = *i;
752 if (PID->getPropertyDecl()->getIdentifier() == Id)
753 return PID;
754 }
755 return 0;
756}
757
Chris Lattner10318b82008-03-16 00:19:01 +0000758// lookupInstanceMethod - This method returns an instance method by looking in
759// the class implementation. Unlike interfaces, we don't look outside the
760// implementation.
Daniel Dunbardd24b9a2008-08-26 06:53:45 +0000761ObjCMethodDecl *ObjCCategoryImplDecl::getInstanceMethod(Selector Sel) const {
Chris Lattner10318b82008-03-16 00:19:01 +0000762 for (instmeth_iterator I = instmeth_begin(), E = instmeth_end(); I != E; ++I)
763 if ((*I)->getSelector() == Sel)
764 return *I;
765 return NULL;
766}
767
768// lookupClassMethod - This method returns an instance method by looking in
769// the class implementation. Unlike interfaces, we don't look outside the
770// implementation.
Daniel Dunbardd24b9a2008-08-26 06:53:45 +0000771ObjCMethodDecl *ObjCCategoryImplDecl::getClassMethod(Selector Sel) const {
Chris Lattner10318b82008-03-16 00:19:01 +0000772 for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
773 I != E; ++I)
774 if ((*I)->getSelector() == Sel)
775 return *I;
776 return NULL;
777}
778
779// lookupInstanceMethod - Lookup a instance method in the protocol and protocols
780// it inherited.
781ObjCMethodDecl *ObjCProtocolDecl::lookupInstanceMethod(Selector Sel) {
782 ObjCMethodDecl *MethodDecl = NULL;
783
784 if ((MethodDecl = getInstanceMethod(Sel)))
785 return MethodDecl;
786
Chris Lattner0be08822008-07-21 21:32:27 +0000787 for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I)
Steve Naroff30fb1da2008-12-18 15:50:41 +0000788 if ((MethodDecl = (*I)->lookupInstanceMethod(Sel)))
Chris Lattner0be08822008-07-21 21:32:27 +0000789 return MethodDecl;
Chris Lattner10318b82008-03-16 00:19:01 +0000790 return NULL;
791}
792
793// lookupInstanceMethod - Lookup a class method in the protocol and protocols
794// it inherited.
795ObjCMethodDecl *ObjCProtocolDecl::lookupClassMethod(Selector Sel) {
796 ObjCMethodDecl *MethodDecl = NULL;
797
798 if ((MethodDecl = getClassMethod(Sel)))
799 return MethodDecl;
800
Chris Lattner0be08822008-07-21 21:32:27 +0000801 for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I)
Steve Naroff30fb1da2008-12-18 15:50:41 +0000802 if ((MethodDecl = (*I)->lookupClassMethod(Sel)))
Chris Lattner0be08822008-07-21 21:32:27 +0000803 return MethodDecl;
Chris Lattner10318b82008-03-16 00:19:01 +0000804 return NULL;
805}
806
807/// getSynthesizedMethodSize - Compute size of synthesized method name
808/// as done be the rewrite.
809///
810unsigned ObjCMethodDecl::getSynthesizedMethodSize() const {
811 // syntesized method name is a concatenation of -/+[class-name selector]
812 // Get length of this name.
813 unsigned length = 3; // _I_ or _C_
Chris Lattnerd120b9e2008-11-24 03:54:41 +0000814 length += getClassInterface()->getNameAsString().size()+1; // extra for _
Steve Naroff438be772009-01-08 19:41:02 +0000815 if (const ObjCCategoryImplDecl *CID =
816 dyn_cast<ObjCCategoryImplDecl>(getDeclContext()))
Chris Lattnerd120b9e2008-11-24 03:54:41 +0000817 length += CID->getNameAsString().size()+1;
Chris Lattner3a8f2942008-11-24 03:33:13 +0000818 length += getSelector().getAsString().size(); // selector name
Chris Lattner10318b82008-03-16 00:19:01 +0000819 return length;
820}
821
Chris Lattner052fbcd2008-04-06 05:25:03 +0000822ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
Steve Naroff438be772009-01-08 19:41:02 +0000823 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext()))
Chris Lattner10318b82008-03-16 00:19:01 +0000824 return ID;
Steve Naroff438be772009-01-08 19:41:02 +0000825 if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
Chris Lattner10318b82008-03-16 00:19:01 +0000826 return CD->getClassInterface();
827 if (ObjCImplementationDecl *IMD =
Steve Naroff438be772009-01-08 19:41:02 +0000828 dyn_cast<ObjCImplementationDecl>(getDeclContext()))
Chris Lattner10318b82008-03-16 00:19:01 +0000829 return IMD->getClassInterface();
Steve Naroff438be772009-01-08 19:41:02 +0000830 if (ObjCCategoryImplDecl *CID =
831 dyn_cast<ObjCCategoryImplDecl>(getDeclContext()))
Chris Lattner10318b82008-03-16 00:19:01 +0000832 return CID->getClassInterface();
833 assert(false && "unknown method context");
834 return 0;
835}
Chris Lattner44859612008-03-17 01:19:02 +0000836
Fariborz Jahaniandc0569e2008-04-23 00:06:01 +0000837ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C,
838 SourceLocation atLoc,
839 SourceLocation L,
840 ObjCPropertyDecl *property,
Daniel Dunbar14117fc2008-08-26 04:47:31 +0000841 Kind PK,
Fariborz Jahaniandc0569e2008-04-23 00:06:01 +0000842 ObjCIvarDecl *ivar) {
843 void *Mem = C.getAllocator().Allocate<ObjCPropertyImplDecl>();
Daniel Dunbar14117fc2008-08-26 04:47:31 +0000844 return new (Mem) ObjCPropertyImplDecl(atLoc, L, property, PK, ivar);
Fariborz Jahaniandc0569e2008-04-23 00:06:01 +0000845}
Chris Lattner44859612008-03-17 01:19:02 +0000846
Chris Lattnereee57c02008-04-04 06:12:32 +0000847