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