blob: e978a5b60fabadfc876d1bb748298eeed80828ed [file] [log] [blame]
Chris Lattner89375192008-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 Dunbar221fa942008-08-11 04:54:23 +000016#include "clang/AST/Stmt.h"
Steve Naroffc4173fa2009-02-22 19:35:57 +000017#include "llvm/ADT/STLExtras.h"
Chris Lattner89375192008-03-16 00:19:01 +000018using namespace clang;
19
Chris Lattner8d8829e2008-03-16 00:49:28 +000020//===----------------------------------------------------------------------===//
Chris Lattner4d1eb762009-02-20 21:16:26 +000021// ObjCListBase
22//===----------------------------------------------------------------------===//
23
Chris Lattner22298722009-02-20 21:35:13 +000024void ObjCListBase::Destroy(ASTContext &Ctx) {
Chris Lattner7c981a72009-02-20 21:44:01 +000025 Ctx.Deallocate(List);
Chris Lattner4d1eb762009-02-20 21:16:26 +000026 NumElts = 0;
27 List = 0;
28}
29
Chris Lattner22298722009-02-20 21:35:13 +000030void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
Chris Lattner4d1eb762009-02-20 21:16:26 +000031 assert(List == 0 && "Elements already set!");
32 if (Elts == 0) return; // Setting to an empty list is a noop.
Mike Stump11289f42009-09-09 15:08:12 +000033
34
Chris Lattner7c981a72009-02-20 21:44:01 +000035 List = new (Ctx) void*[Elts];
Chris Lattner4d1eb762009-02-20 21:16:26 +000036 NumElts = Elts;
37 memcpy(List, InList, sizeof(void*)*Elts);
38}
39
40
41//===----------------------------------------------------------------------===//
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +000042// ObjCInterfaceDecl
Chris Lattner8d8829e2008-03-16 00:49:28 +000043//===----------------------------------------------------------------------===//
44
Fariborz Jahanian68453832009-06-05 18:16:35 +000045/// getIvarDecl - This method looks up an ivar in this ContextDecl.
46///
47ObjCIvarDecl *
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +000048ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const {
Fariborz Jahanian68453832009-06-05 18:16:35 +000049 lookup_const_iterator Ivar, IvarEnd;
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +000050 for (llvm::tie(Ivar, IvarEnd) = lookup(Id); Ivar != IvarEnd; ++Ivar) {
Fariborz Jahanian68453832009-06-05 18:16:35 +000051 if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar))
52 return ivar;
53 }
54 return 0;
55}
56
Argyrios Kyrtzidis6de05602009-07-25 22:15:22 +000057// Get the local instance/class method declared in this interface.
Douglas Gregorbcced4e2009-04-09 21:40:53 +000058ObjCMethodDecl *
Argyrios Kyrtzidis6de05602009-07-25 22:15:22 +000059ObjCContainerDecl::getMethod(Selector Sel, bool isInstance) const {
Steve Naroffc4173fa2009-02-22 19:35:57 +000060 // Since instance & class methods can have the same name, the loop below
61 // ensures we get the correct method.
62 //
63 // @interface Whatever
64 // - (int) class_method;
65 // + (float) class_method;
66 // @end
67 //
68 lookup_const_iterator Meth, MethEnd;
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +000069 for (llvm::tie(Meth, MethEnd) = lookup(Sel); Meth != MethEnd; ++Meth) {
Steve Naroffc4173fa2009-02-22 19:35:57 +000070 ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
Argyrios Kyrtzidis6de05602009-07-25 22:15:22 +000071 if (MD && MD->isInstanceMethod() == isInstance)
Steve Naroffc4173fa2009-02-22 19:35:57 +000072 return MD;
73 }
Steve Naroff35c62ae2009-01-08 17:28:14 +000074 return 0;
75}
76
Fariborz Jahaniana054e992008-04-21 19:04:53 +000077/// FindPropertyDeclaration - Finds declaration of the property given its name
78/// in 'PropertyId' and returns it. It returns 0, if not found.
Steve Naroffba3dc382009-01-11 12:47:58 +000079/// FIXME: Convert to DeclContext lookup...
Fariborz Jahaniana054e992008-04-21 19:04:53 +000080///
81ObjCPropertyDecl *
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +000082ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
83 for (prop_iterator I = prop_begin(), E = prop_end(); I != E; ++I)
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +000084 if ((*I)->getIdentifier() == PropertyId)
85 return *I;
Mike Stump11289f42009-09-09 15:08:12 +000086
Fariborz Jahanian519976c2009-01-09 21:04:52 +000087 const ObjCProtocolDecl *PID = dyn_cast<ObjCProtocolDecl>(this);
88 if (PID) {
Mike Stump11289f42009-09-09 15:08:12 +000089 for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +000090 E = PID->protocol_end(); I != E; ++I)
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +000091 if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +000092 return P;
Fariborz Jahanian519976c2009-01-09 21:04:52 +000093 }
Mike Stump11289f42009-09-09 15:08:12 +000094
Fariborz Jahaniandab04842009-01-19 18:16:19 +000095 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(this)) {
Steve Naroffb3a87982009-01-09 15:36:25 +000096 // Look through categories.
97 for (ObjCCategoryDecl *Category = OID->getCategoryList();
98 Category; Category = Category->getNextClassCategory()) {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +000099 if (ObjCPropertyDecl *P = Category->FindPropertyDeclaration(PropertyId))
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000100 return P;
Steve Naroffb3a87982009-01-09 15:36:25 +0000101 }
102 // Look through protocols.
103 for (ObjCInterfaceDecl::protocol_iterator I = OID->protocol_begin(),
104 E = OID->protocol_end(); I != E; ++I) {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +0000105 if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000106 return P;
Steve Naroffb3a87982009-01-09 15:36:25 +0000107 }
108 if (OID->getSuperClass())
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +0000109 return OID->getSuperClass()->FindPropertyDeclaration(PropertyId);
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000110 } else if (const ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(this)) {
Fariborz Jahaniandab04842009-01-19 18:16:19 +0000111 // Look through protocols.
112 for (ObjCInterfaceDecl::protocol_iterator I = OCD->protocol_begin(),
113 E = OCD->protocol_end(); I != E; ++I) {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +0000114 if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000115 return P;
Fariborz Jahaniandab04842009-01-19 18:16:19 +0000116 }
117 }
Steve Narofff9c65242008-06-05 13:55:23 +0000118 return 0;
119}
120
Fariborz Jahanian092cd6e2009-10-05 20:41:32 +0000121void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
122 ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
123 ASTContext &C)
124{
125 if (ReferencedProtocols.empty()) {
126 ReferencedProtocols.set(ExtList, ExtNum, C);
127 return;
128 }
129 // Check for duplicate protocol in class's protocol list.
130 // This is (O)2. But it is extremely rare and number of protocols in
131 // class or its extension are very few.
132 llvm::SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
133 for (unsigned i = 0; i < ExtNum; i++) {
134 bool protocolExists = false;
135 ObjCProtocolDecl *ProtoInExtension = ExtList[i];
136 for (protocol_iterator p = protocol_begin(), e = protocol_end();
137 p != e; p++) {
138 ObjCProtocolDecl *Proto = (*p);
139 if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) {
140 protocolExists = true;
141 break;
142 }
143 }
144 // Do we want to warn on a protocol in extension class which
145 // already exist in the class? Probably not.
146 if (!protocolExists)
147 ProtocolRefs.push_back(ProtoInExtension);
148 }
149 if (ProtocolRefs.empty())
150 return;
151
152 for (protocol_iterator p = protocol_begin(), e = protocol_end();
153 p != e; p++)
154 ProtocolRefs.push_back(*p);
155 ReferencedProtocols.Destroy(C);
156 unsigned NumProtoRefs = ProtocolRefs.size();
157 setProtocolList((ObjCProtocolDecl**)&ProtocolRefs[0], NumProtoRefs, C);
158 // Merge ProtocolRefs into class's protocol list;
159
160}
161
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +0000162ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
163 ObjCInterfaceDecl *&clsDeclared) {
Chris Lattner89375192008-03-16 00:19:01 +0000164 ObjCInterfaceDecl* ClassDecl = this;
165 while (ClassDecl != NULL) {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +0000166 if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) {
Fariborz Jahanian68453832009-06-05 18:16:35 +0000167 clsDeclared = ClassDecl;
168 return I;
Chris Lattner89375192008-03-16 00:19:01 +0000169 }
170 ClassDecl = ClassDecl->getSuperClass();
171 }
172 return NULL;
173}
174
Fariborz Jahaniandb3a4c12009-05-22 17:12:32 +0000175/// lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super
176/// class whose name is passed as argument. If it is not one of the super classes
177/// the it returns NULL.
178ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
179 const IdentifierInfo*ICName) {
180 ObjCInterfaceDecl* ClassDecl = this;
181 while (ClassDecl != NULL) {
182 if (ClassDecl->getIdentifier() == ICName)
183 return ClassDecl;
184 ClassDecl = ClassDecl->getSuperClass();
185 }
186 return NULL;
187}
188
Argyrios Kyrtzidis553376b2009-07-25 22:15:51 +0000189/// lookupMethod - This method returns an instance/class method by looking in
Chris Lattner89375192008-03-16 00:19:01 +0000190/// the class, its categories, and its super classes (using a linear search).
Argyrios Kyrtzidis553376b2009-07-25 22:15:51 +0000191ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
192 bool isInstance) const {
193 const ObjCInterfaceDecl* ClassDecl = this;
Chris Lattner89375192008-03-16 00:19:01 +0000194 ObjCMethodDecl *MethodDecl = 0;
Mike Stump11289f42009-09-09 15:08:12 +0000195
Chris Lattner89375192008-03-16 00:19:01 +0000196 while (ClassDecl != NULL) {
Argyrios Kyrtzidis553376b2009-07-25 22:15:51 +0000197 if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance)))
Chris Lattner89375192008-03-16 00:19:01 +0000198 return MethodDecl;
Mike Stump11289f42009-09-09 15:08:12 +0000199
Chris Lattner89375192008-03-16 00:19:01 +0000200 // Didn't find one yet - look through protocols.
Chris Lattnerd0045052008-07-21 18:19:38 +0000201 const ObjCList<ObjCProtocolDecl> &Protocols =
202 ClassDecl->getReferencedProtocols();
203 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
204 E = Protocols.end(); I != E; ++I)
Argyrios Kyrtzidis553376b2009-07-25 22:15:51 +0000205 if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
Chris Lattner89375192008-03-16 00:19:01 +0000206 return MethodDecl;
Mike Stump11289f42009-09-09 15:08:12 +0000207
Chris Lattner89375192008-03-16 00:19:01 +0000208 // Didn't find one yet - now look through categories.
209 ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
210 while (CatDecl) {
Argyrios Kyrtzidis553376b2009-07-25 22:15:51 +0000211 if ((MethodDecl = CatDecl->getMethod(Sel, isInstance)))
Chris Lattner89375192008-03-16 00:19:01 +0000212 return MethodDecl;
Mike Stump11289f42009-09-09 15:08:12 +0000213
Steve Naroff5fd31b12008-12-08 20:57:28 +0000214 // Didn't find one yet - look through protocols.
215 const ObjCList<ObjCProtocolDecl> &Protocols =
216 CatDecl->getReferencedProtocols();
217 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
218 E = Protocols.end(); I != E; ++I)
Argyrios Kyrtzidis553376b2009-07-25 22:15:51 +0000219 if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
Steve Naroff8ec27842009-02-26 11:32:02 +0000220 return MethodDecl;
Chris Lattner89375192008-03-16 00:19:01 +0000221 CatDecl = CatDecl->getNextClassCategory();
222 }
223 ClassDecl = ClassDecl->getSuperClass();
224 }
225 return NULL;
226}
227
Steve Naroffbb69c942009-10-01 23:46:04 +0000228ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateInstanceMethod(
229 const Selector &Sel) {
230 ObjCMethodDecl *Method = 0;
231 if (ObjCImplementationDecl *ImpDecl = getImplementation())
232 Method = ImpDecl->getInstanceMethod(Sel);
233
234 if (!Method && getSuperClass())
235 return getSuperClass()->lookupPrivateInstanceMethod(Sel);
236 return Method;
237}
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000238
239//===----------------------------------------------------------------------===//
240// ObjCMethodDecl
241//===----------------------------------------------------------------------===//
242
243ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
Mike Stump11289f42009-09-09 15:08:12 +0000244 SourceLocation beginLoc,
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000245 SourceLocation endLoc,
246 Selector SelInfo, QualType T,
247 DeclContext *contextDecl,
248 bool isInstance,
249 bool isVariadic,
250 bool isSynthesized,
251 ImplementationControl impControl) {
252 return new (C) ObjCMethodDecl(beginLoc, endLoc,
253 SelInfo, T, contextDecl,
Mike Stump11289f42009-09-09 15:08:12 +0000254 isInstance,
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000255 isVariadic, isSynthesized, impControl);
Chris Lattner89375192008-03-16 00:19:01 +0000256}
257
Chris Lattner22298722009-02-20 21:35:13 +0000258void ObjCMethodDecl::Destroy(ASTContext &C) {
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000259 if (Body) Body->Destroy(C);
260 if (SelfDecl) SelfDecl->Destroy(C);
Mike Stump11289f42009-09-09 15:08:12 +0000261
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000262 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
263 if (*I) (*I)->Destroy(C);
264
Chris Lattner22298722009-02-20 21:35:13 +0000265 ParamInfo.Destroy(C);
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000266
267 Decl::Destroy(C);
Chris Lattner89375192008-03-16 00:19:01 +0000268}
269
Argyrios Kyrtzidisa8cf0be2009-07-21 00:06:36 +0000270/// \brief A definition will return its interface declaration.
271/// An interface declaration will return its definition.
272/// Otherwise it will return itself.
273ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() {
274 ASTContext &Ctx = getASTContext();
275 ObjCMethodDecl *Redecl = 0;
276 Decl *CtxD = cast<Decl>(getDeclContext());
277
278 if (ObjCInterfaceDecl *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) {
279 if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD))
280 Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
281
282 } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) {
283 if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD))
284 Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
285
Argyrios Kyrtzidisa56fa192009-07-28 05:11:05 +0000286 } else if (ObjCImplementationDecl *ImplD =
287 dyn_cast<ObjCImplementationDecl>(CtxD)) {
Argyrios Kyrtzidisa8cf0be2009-07-21 00:06:36 +0000288 if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
289 Redecl = IFD->getMethod(getSelector(), isInstanceMethod());
Argyrios Kyrtzidisa56fa192009-07-28 05:11:05 +0000290
291 } else if (ObjCCategoryImplDecl *CImplD =
292 dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
293 if (ObjCCategoryDecl *CatD = CImplD->getCategoryClass())
294 Redecl = CatD->getMethod(getSelector(), isInstanceMethod());
Argyrios Kyrtzidisa8cf0be2009-07-21 00:06:36 +0000295 }
296
297 return Redecl ? Redecl : this;
298}
299
Argyrios Kyrtzidisf390c432009-07-28 05:11:17 +0000300ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
301 Decl *CtxD = cast<Decl>(getDeclContext());
302
303 if (ObjCImplementationDecl *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
304 if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
305 if (ObjCMethodDecl *MD = IFD->getMethod(getSelector(),
306 isInstanceMethod()))
307 return MD;
308
309 } else if (ObjCCategoryImplDecl *CImplD =
310 dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
311 if (ObjCCategoryDecl *CatD = CImplD->getCategoryClass())
312 if (ObjCMethodDecl *MD = CatD->getMethod(getSelector(),
313 isInstanceMethod()))
314 return MD;
315 }
316
317 return this;
318}
319
Mike Stump11289f42009-09-09 15:08:12 +0000320void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000321 const ObjCInterfaceDecl *OID) {
322 QualType selfTy;
323 if (isInstanceMethod()) {
324 // There may be no interface context due to error in declaration
325 // of the interface (which has been reported). Recover gracefully.
326 if (OID) {
Daniel Dunbaraefc2b92009-04-22 04:34:53 +0000327 selfTy = Context.getObjCInterfaceType(OID);
Steve Naroff7cae42b2009-07-10 23:34:53 +0000328 selfTy = Context.getObjCObjectPointerType(selfTy);
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000329 } else {
330 selfTy = Context.getObjCIdType();
331 }
332 } else // we have a factory method.
333 selfTy = Context.getObjCClassType();
334
Mike Stump11289f42009-09-09 15:08:12 +0000335 setSelfDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(),
Steve Naroff04f2d142009-04-20 15:06:07 +0000336 &Context.Idents.get("self"), selfTy));
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000337
Mike Stump11289f42009-09-09 15:08:12 +0000338 setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(),
339 &Context.Idents.get("_cmd"),
Steve Naroff04f2d142009-04-20 15:06:07 +0000340 Context.getObjCSelType()));
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000341}
342
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000343ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
344 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext()))
345 return ID;
346 if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
347 return CD->getClassInterface();
Argyrios Kyrtzidis2cee40d2009-07-28 05:10:52 +0000348 if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(getDeclContext()))
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000349 return IMD->getClassInterface();
Argyrios Kyrtzidis2cee40d2009-07-28 05:10:52 +0000350
351 assert(!isa<ObjCProtocolDecl>(getDeclContext()) && "It's a protocol method");
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000352 assert(false && "unknown method context");
Fariborz Jahanianfbbaf6a2008-12-05 22:32:48 +0000353 return 0;
354}
355
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000356//===----------------------------------------------------------------------===//
357// ObjCInterfaceDecl
358//===----------------------------------------------------------------------===//
359
360ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C,
361 DeclContext *DC,
362 SourceLocation atLoc,
Mike Stump11289f42009-09-09 15:08:12 +0000363 IdentifierInfo *Id,
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000364 SourceLocation ClassLoc,
365 bool ForwardDecl, bool isInternal){
366 return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, ForwardDecl,
367 isInternal);
368}
369
370ObjCInterfaceDecl::
371ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
372 SourceLocation CLoc, bool FD, bool isInternal)
373 : ObjCContainerDecl(ObjCInterface, DC, atLoc, Id),
374 TypeForDecl(0), SuperClass(0),
375 CategoryList(0), ForwardDecl(FD), InternalInterface(isInternal),
376 ClassLoc(CLoc) {
377}
378
Mike Stump11289f42009-09-09 15:08:12 +0000379void ObjCInterfaceDecl::Destroy(ASTContext &C) {
Chris Lattnerd8a47c42009-03-31 08:36:08 +0000380 for (ivar_iterator I = ivar_begin(), E = ivar_end(); I != E; ++I)
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000381 if (*I) (*I)->Destroy(C);
Mike Stump11289f42009-09-09 15:08:12 +0000382
Chris Lattner22298722009-02-20 21:35:13 +0000383 IVars.Destroy(C);
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000384 // FIXME: CategoryList?
Mike Stump11289f42009-09-09 15:08:12 +0000385
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000386 // FIXME: Because there is no clear ownership
387 // role between ObjCInterfaceDecls and the ObjCPropertyDecls that they
388 // reference, we destroy ObjCPropertyDecls in ~TranslationUnit.
389 Decl::Destroy(C);
390}
391
Argyrios Kyrtzidis6d9fab72009-07-21 00:05:53 +0000392ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
393 return getASTContext().getObjCImplementation(
394 const_cast<ObjCInterfaceDecl*>(this));
395}
396
397void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
398 getASTContext().setObjCImplementation(this, ImplD);
399}
400
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000401
402/// FindCategoryDeclaration - Finds category declaration in the list of
403/// categories for this class and returns it. Name of the category is passed
404/// in 'CategoryId'. If category not found, return 0;
Fariborz Jahanianfbbaf6a2008-12-05 22:32:48 +0000405///
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000406ObjCCategoryDecl *
407ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
408 for (ObjCCategoryDecl *Category = getCategoryList();
409 Category; Category = Category->getNextClassCategory())
410 if (Category->getIdentifier() == CategoryId)
411 return Category;
Fariborz Jahanianfbbaf6a2008-12-05 22:32:48 +0000412 return 0;
413}
414
Argyrios Kyrtzidis1559d67b2009-07-21 00:06:20 +0000415ObjCMethodDecl *
416ObjCInterfaceDecl::getCategoryInstanceMethod(Selector Sel) const {
417 for (ObjCCategoryDecl *Category = getCategoryList();
418 Category; Category = Category->getNextClassCategory())
419 if (ObjCCategoryImplDecl *Impl = Category->getImplementation())
420 if (ObjCMethodDecl *MD = Impl->getInstanceMethod(Sel))
421 return MD;
422 return 0;
423}
424
425ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const {
426 for (ObjCCategoryDecl *Category = getCategoryList();
427 Category; Category = Category->getNextClassCategory())
428 if (ObjCCategoryImplDecl *Impl = Category->getImplementation())
429 if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel))
430 return MD;
431 return 0;
432}
433
Fariborz Jahanian3f8917a2009-08-11 22:02:25 +0000434/// ClassImplementsProtocol - Checks that 'lProto' protocol
435/// has been implemented in IDecl class, its super class or categories (if
436/// lookupCategory is true).
437bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
438 bool lookupCategory,
439 bool RHSIsQualifiedID) {
440 ObjCInterfaceDecl *IDecl = this;
441 // 1st, look up the class.
442 const ObjCList<ObjCProtocolDecl> &Protocols =
443 IDecl->getReferencedProtocols();
Mike Stump11289f42009-09-09 15:08:12 +0000444
Fariborz Jahanian3f8917a2009-08-11 22:02:25 +0000445 for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(),
446 E = Protocols.end(); PI != E; ++PI) {
447 if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI))
448 return true;
449 // This is dubious and is added to be compatible with gcc. In gcc, it is
450 // also allowed assigning a protocol-qualified 'id' type to a LHS object
451 // when protocol in qualified LHS is in list of protocols in the rhs 'id'
452 // object. This IMO, should be a bug.
453 // FIXME: Treat this as an extension, and flag this as an error when GCC
454 // extensions are not enabled.
Mike Stump11289f42009-09-09 15:08:12 +0000455 if (RHSIsQualifiedID &&
Fariborz Jahanian3f8917a2009-08-11 22:02:25 +0000456 getASTContext().ProtocolCompatibleWithProtocol(*PI, lProto))
457 return true;
458 }
Mike Stump11289f42009-09-09 15:08:12 +0000459
Fariborz Jahanian3f8917a2009-08-11 22:02:25 +0000460 // 2nd, look up the category.
461 if (lookupCategory)
462 for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl;
463 CDecl = CDecl->getNextClassCategory()) {
464 for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(),
465 E = CDecl->protocol_end(); PI != E; ++PI)
466 if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI))
467 return true;
468 }
Mike Stump11289f42009-09-09 15:08:12 +0000469
Fariborz Jahanian3f8917a2009-08-11 22:02:25 +0000470 // 3rd, look up the super class(s)
471 if (IDecl->getSuperClass())
472 return
473 IDecl->getSuperClass()->ClassImplementsProtocol(lProto, lookupCategory,
474 RHSIsQualifiedID);
Mike Stump11289f42009-09-09 15:08:12 +0000475
Fariborz Jahanian3f8917a2009-08-11 22:02:25 +0000476 return false;
477}
478
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000479//===----------------------------------------------------------------------===//
480// ObjCIvarDecl
481//===----------------------------------------------------------------------===//
482
483ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, DeclContext *DC,
484 SourceLocation L, IdentifierInfo *Id,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +0000485 QualType T, DeclaratorInfo *DInfo,
486 AccessControl ac, Expr *BW) {
487 return new (C) ObjCIvarDecl(DC, L, Id, T, DInfo, ac, BW);
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000488}
489
490
491
492//===----------------------------------------------------------------------===//
493// ObjCAtDefsFieldDecl
494//===----------------------------------------------------------------------===//
495
496ObjCAtDefsFieldDecl
497*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
498 IdentifierInfo *Id, QualType T, Expr *BW) {
499 return new (C) ObjCAtDefsFieldDecl(DC, L, Id, T, BW);
500}
501
502void ObjCAtDefsFieldDecl::Destroy(ASTContext& C) {
503 this->~ObjCAtDefsFieldDecl();
Mike Stump11289f42009-09-09 15:08:12 +0000504 C.Deallocate((void *)this);
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000505}
506
507//===----------------------------------------------------------------------===//
508// ObjCProtocolDecl
509//===----------------------------------------------------------------------===//
510
511ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
Mike Stump11289f42009-09-09 15:08:12 +0000512 SourceLocation L,
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000513 IdentifierInfo *Id) {
514 return new (C) ObjCProtocolDecl(DC, L, Id);
515}
516
517void ObjCProtocolDecl::Destroy(ASTContext &C) {
Chris Lattner22298722009-02-20 21:35:13 +0000518 ReferencedProtocols.Destroy(C);
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000519 ObjCContainerDecl::Destroy(C);
520}
521
Steve Naroff114aecb2009-03-01 16:12:44 +0000522ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
523 ObjCProtocolDecl *PDecl = this;
524
525 if (Name == getIdentifier())
526 return PDecl;
527
528 for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I)
529 if ((PDecl = (*I)->lookupProtocolNamed(Name)))
530 return PDecl;
Mike Stump11289f42009-09-09 15:08:12 +0000531
Steve Naroff114aecb2009-03-01 16:12:44 +0000532 return NULL;
533}
534
Argyrios Kyrtzidise6ed65b2009-07-25 22:15:38 +0000535// lookupMethod - Lookup a instance/class method in the protocol and protocols
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000536// it inherited.
Argyrios Kyrtzidise6ed65b2009-07-25 22:15:38 +0000537ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
538 bool isInstance) const {
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000539 ObjCMethodDecl *MethodDecl = NULL;
Mike Stump11289f42009-09-09 15:08:12 +0000540
Argyrios Kyrtzidise6ed65b2009-07-25 22:15:38 +0000541 if ((MethodDecl = getMethod(Sel, isInstance)))
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000542 return MethodDecl;
Mike Stump11289f42009-09-09 15:08:12 +0000543
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000544 for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I)
Argyrios Kyrtzidise6ed65b2009-07-25 22:15:38 +0000545 if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000546 return MethodDecl;
547 return NULL;
548}
549
550//===----------------------------------------------------------------------===//
551// ObjCClassDecl
552//===----------------------------------------------------------------------===//
553
Mike Stump11289f42009-09-09 15:08:12 +0000554ObjCClassDecl::ObjCClassDecl(DeclContext *DC, SourceLocation L,
Chris Lattner22298722009-02-20 21:35:13 +0000555 ObjCInterfaceDecl *const *Elts, unsigned nElts,
556 ASTContext &C)
557 : Decl(ObjCClass, DC, L) {
558 ForwardDecls.set(Elts, nElts, C);
559}
560
561
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000562ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C, DeclContext *DC,
563 SourceLocation L,
564 ObjCInterfaceDecl *const *Elts,
565 unsigned nElts) {
Chris Lattner22298722009-02-20 21:35:13 +0000566 return new (C) ObjCClassDecl(DC, L, Elts, nElts, C);
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000567}
568
569void ObjCClassDecl::Destroy(ASTContext &C) {
Mike Stump11289f42009-09-09 15:08:12 +0000570
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000571 // FIXME: There is no clear ownership policy now for referenced
572 // ObjCInterfaceDecls. Some of them can be forward declarations that
573 // are never later defined (in which case the ObjCClassDecl owns them)
574 // or the ObjCInterfaceDecl later becomes a real definition later. Ideally
575 // we should have separate objects for forward declarations and definitions,
576 // obviating this problem. Because of this situation, referenced
577 // ObjCInterfaceDecls are destroyed in ~TranslationUnit.
Mike Stump11289f42009-09-09 15:08:12 +0000578
Chris Lattner22298722009-02-20 21:35:13 +0000579 ForwardDecls.Destroy(C);
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000580 Decl::Destroy(C);
581}
582
583//===----------------------------------------------------------------------===//
584// ObjCForwardProtocolDecl
585//===----------------------------------------------------------------------===//
586
Chris Lattner22298722009-02-20 21:35:13 +0000587ObjCForwardProtocolDecl::
588ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
589 ObjCProtocolDecl *const *Elts, unsigned nElts,
590 ASTContext &C)
Mike Stump11289f42009-09-09 15:08:12 +0000591: Decl(ObjCForwardProtocol, DC, L) {
Chris Lattner22298722009-02-20 21:35:13 +0000592 ReferencedProtocols.set(Elts, nElts, C);
593}
594
595
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000596ObjCForwardProtocolDecl *
597ObjCForwardProtocolDecl::Create(ASTContext &C, DeclContext *DC,
Mike Stump11289f42009-09-09 15:08:12 +0000598 SourceLocation L,
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000599 ObjCProtocolDecl *const *Elts,
600 unsigned NumElts) {
Chris Lattner22298722009-02-20 21:35:13 +0000601 return new (C) ObjCForwardProtocolDecl(DC, L, Elts, NumElts, C);
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000602}
603
604void ObjCForwardProtocolDecl::Destroy(ASTContext &C) {
Chris Lattner22298722009-02-20 21:35:13 +0000605 ReferencedProtocols.Destroy(C);
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000606 Decl::Destroy(C);
607}
608
609//===----------------------------------------------------------------------===//
610// ObjCCategoryDecl
611//===----------------------------------------------------------------------===//
612
613ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
614 SourceLocation L,
615 IdentifierInfo *Id) {
616 return new (C) ObjCCategoryDecl(DC, L, Id);
617}
618
Argyrios Kyrtzidis6d9fab72009-07-21 00:05:53 +0000619ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
620 return getASTContext().getObjCImplementation(
621 const_cast<ObjCCategoryDecl*>(this));
622}
623
624void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
625 getASTContext().setObjCImplementation(this, ImplD);
626}
627
628
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000629//===----------------------------------------------------------------------===//
630// ObjCCategoryImplDecl
631//===----------------------------------------------------------------------===//
632
633ObjCCategoryImplDecl *
634ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
635 SourceLocation L,IdentifierInfo *Id,
636 ObjCInterfaceDecl *ClassInterface) {
637 return new (C) ObjCCategoryImplDecl(DC, L, Id, ClassInterface);
638}
639
Argyrios Kyrtzidisa56fa192009-07-28 05:11:05 +0000640ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryClass() const {
641 return getClassInterface()->FindCategoryDeclaration(getIdentifier());
642}
643
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000644
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +0000645void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) {
Douglas Gregor9a13efd2009-04-23 02:42:49 +0000646 // FIXME: The context should be correct before we get here.
Douglas Gregor29bd76f2009-04-23 01:02:12 +0000647 property->setLexicalDeclContext(this);
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +0000648 addDecl(property);
Douglas Gregor29bd76f2009-04-23 01:02:12 +0000649}
650
Argyrios Kyrtzidis6d9fab72009-07-21 00:05:53 +0000651void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) {
652 ASTContext &Ctx = getASTContext();
653
654 if (ObjCImplementationDecl *ImplD
Duncan Sands49c29ee2009-07-21 07:56:29 +0000655 = dyn_cast_or_null<ObjCImplementationDecl>(this)) {
Argyrios Kyrtzidis6d9fab72009-07-21 00:05:53 +0000656 if (IFace)
657 Ctx.setObjCImplementation(IFace, ImplD);
658
Duncan Sands49c29ee2009-07-21 07:56:29 +0000659 } else if (ObjCCategoryImplDecl *ImplD =
Argyrios Kyrtzidis6d9fab72009-07-21 00:05:53 +0000660 dyn_cast_or_null<ObjCCategoryImplDecl>(this)) {
661 if (ObjCCategoryDecl *CD = IFace->FindCategoryDeclaration(getIdentifier()))
662 Ctx.setObjCImplementation(CD, ImplD);
663 }
664
665 ClassInterface = IFace;
666}
667
Fariborz Jahanianfbbaf6a2008-12-05 22:32:48 +0000668/// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
Chris Lattneraab70d22009-02-16 19:24:31 +0000669/// properties implemented in this category @implementation block and returns
670/// the implemented property that uses it.
Fariborz Jahanianfbbaf6a2008-12-05 22:32:48 +0000671///
Chris Lattnera9ca0522009-02-28 18:42:10 +0000672ObjCPropertyImplDecl *ObjCImplDecl::
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +0000673FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
674 for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i){
Fariborz Jahanianfbbaf6a2008-12-05 22:32:48 +0000675 ObjCPropertyImplDecl *PID = *i;
676 if (PID->getPropertyIvarDecl() &&
677 PID->getPropertyIvarDecl()->getIdentifier() == ivarId)
678 return PID;
679 }
680 return 0;
681}
682
683/// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl
684/// added to the list of those properties @synthesized/@dynamic in this
685/// category @implementation block.
686///
Chris Lattnera9ca0522009-02-28 18:42:10 +0000687ObjCPropertyImplDecl *ObjCImplDecl::
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +0000688FindPropertyImplDecl(IdentifierInfo *Id) const {
689 for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i){
Fariborz Jahanianfbbaf6a2008-12-05 22:32:48 +0000690 ObjCPropertyImplDecl *PID = *i;
691 if (PID->getPropertyDecl()->getIdentifier() == Id)
692 return PID;
693 }
694 return 0;
695}
696
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000697//===----------------------------------------------------------------------===//
698// ObjCImplementationDecl
699//===----------------------------------------------------------------------===//
700
701ObjCImplementationDecl *
Mike Stump11289f42009-09-09 15:08:12 +0000702ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC,
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000703 SourceLocation L,
704 ObjCInterfaceDecl *ClassInterface,
705 ObjCInterfaceDecl *SuperDecl) {
706 return new (C) ObjCImplementationDecl(DC, L, ClassInterface, SuperDecl);
707}
708
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000709//===----------------------------------------------------------------------===//
710// ObjCCompatibleAliasDecl
711//===----------------------------------------------------------------------===//
712
713ObjCCompatibleAliasDecl *
714ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
715 SourceLocation L,
Mike Stump11289f42009-09-09 15:08:12 +0000716 IdentifierInfo *Id,
Chris Lattnerf1ccb0c2009-02-20 20:59:54 +0000717 ObjCInterfaceDecl* AliasedClass) {
718 return new (C) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass);
719}
720
721//===----------------------------------------------------------------------===//
722// ObjCPropertyDecl
723//===----------------------------------------------------------------------===//
724
725ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
726 SourceLocation L,
727 IdentifierInfo *Id,
728 QualType T,
729 PropertyControl propControl) {
730 return new (C) ObjCPropertyDecl(DC, L, Id, T);
731}
732
733
734//===----------------------------------------------------------------------===//
735// ObjCPropertyImplDecl
736//===----------------------------------------------------------------------===//
737
Fariborz Jahanian6efdf1d2008-04-23 00:06:01 +0000738ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C,
Douglas Gregorc25d7a72009-01-09 00:49:46 +0000739 DeclContext *DC,
Fariborz Jahanian6efdf1d2008-04-23 00:06:01 +0000740 SourceLocation atLoc,
741 SourceLocation L,
742 ObjCPropertyDecl *property,
Daniel Dunbar3b4fdb02008-08-26 04:47:31 +0000743 Kind PK,
Fariborz Jahanian6efdf1d2008-04-23 00:06:01 +0000744 ObjCIvarDecl *ivar) {
Steve Naroff13ae6f42009-01-27 21:25:57 +0000745 return new (C) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar);
Fariborz Jahanian6efdf1d2008-04-23 00:06:01 +0000746}
Chris Lattnered0e1642008-03-17 01:19:02 +0000747
Chris Lattnerc5ffed42008-04-04 06:12:32 +0000748