DeclObjC.h revision d57f635d520e8cb5b93d3d770ff58db06c62de54
1//===--- DeclObjC.h - Classes for representing declarations -----*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by Steve Naroff and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file defines the DeclObjC interface and subclasses.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_DECLOBJC_H
15#define LLVM_CLANG_AST_DECLOBJC_H
16
17#include "clang/AST/Decl.h"
18#include "clang/Basic/IdentifierTable.h"
19
20namespace clang {
21class Expr;
22class Stmt;
23class FunctionDecl;
24class AttributeList;
25class ObjcIvarDecl;
26class ObjcMethodDecl;
27class ObjcProtocolDecl;
28class ObjcCategoryDecl;
29class ObjcPropertyDecl;
30
31/// ObjcMethodDecl - Represents an instance or class method declaration.
32/// ObjC methods can be declared within 4 contexts: class interfaces,
33/// categories, protocols, and class implementations. While C++ member
34/// functions leverage C syntax, Objective-C method syntax is modeled after
35/// Smalltalk (using colons to specify argument types/expressions).
36/// Here are some brief examples:
37///
38/// Setter/getter instance methods:
39/// - (void)setMenu:(NSMenu *)menu;
40/// - (NSMenu *)menu;
41///
42/// Instance method that takes 2 NSView arguments:
43/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView;
44///
45/// Getter class method:
46/// + (NSMenu *)defaultMenu;
47///
48/// A selector represents a unique name for a method. The selector names for
49/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
50///
51class ObjcMethodDecl : public Decl {
52public:
53  enum ImplementationControl { None, Required, Optional };
54private:
55  /// Bitfields must be first fields in this class so they pack with those
56  /// declared in class Decl.
57  /// instance (true) or class (false) method.
58  bool IsInstance : 1;
59  bool IsVariadic : 1;
60
61  /// @required/@optional
62  ImplementationControl DeclImplementation : 2;
63
64  /// in, inout, etc.
65  ObjcDeclQualifier objcDeclQualifier : 6;
66
67  // Context this method is declared in.
68  NamedDecl *MethodContext;
69
70  // A unigue name for this method.
71  Selector SelName;
72
73  // Type of this method.
74  QualType MethodDeclType;
75  /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
76  /// parameters of this Method.  This is null if there are no formals.
77  ParmVarDecl **ParamInfo;
78  int NumMethodParams;  // -1 if no parameters
79
80  /// List of attributes for this method declaration.
81  AttributeList *MethodAttrs;
82
83  SourceLocation EndLoc; // the location of the ';' or '{'.
84
85  // The following are only used for method definitions, null otherwise.
86  // FIXME: space savings opportunity, consider a sub-class.
87  Stmt *Body;
88  ParmVarDecl *SelfDecl;
89public:
90  ObjcMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
91                 Selector SelInfo, QualType T,
92                 Decl *contextDecl,
93                 ParmVarDecl **paramInfo = 0, int numParams=-1,
94                 AttributeList *M = 0, bool isInstance = true,
95                 bool isVariadic = false,
96                 ImplementationControl impControl = None,
97                 Decl *PrevDecl = 0)
98  : Decl(ObjcMethod, beginLoc),
99    IsInstance(isInstance), IsVariadic(isVariadic),
100    DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
101    MethodContext(static_cast<NamedDecl*>(contextDecl)),
102    SelName(SelInfo), MethodDeclType(T),
103    ParamInfo(paramInfo), NumMethodParams(numParams),
104    MethodAttrs(M), EndLoc(endLoc), Body(0), SelfDecl(0) {}
105  virtual ~ObjcMethodDecl();
106
107  ObjcDeclQualifier getObjcDeclQualifier() const { return objcDeclQualifier; }
108  void setObjcDeclQualifier(ObjcDeclQualifier QV) { objcDeclQualifier = QV; }
109
110  // Location information, modeled after the Stmt API.
111  SourceLocation getLocStart() const { return getLocation(); }
112  SourceLocation getLocEnd() const { return EndLoc; }
113
114  NamedDecl *getMethodContext() const { return MethodContext; }
115
116  ObjcInterfaceDecl *const getClassInterface() const;
117
118  Selector getSelector() const { return SelName; }
119  QualType getResultType() const { return MethodDeclType; }
120
121  // Iterator access to formal parameters.
122  unsigned param_size() const {
123    return NumMethodParams == -1 ? 0 : NumMethodParams;
124  }
125  typedef ParmVarDecl **param_iterator;
126  typedef ParmVarDecl * const *param_const_iterator;
127  param_iterator param_begin() { return ParamInfo; }
128  param_iterator param_end() { return ParamInfo+param_size(); }
129  param_const_iterator param_begin() const { return ParamInfo; }
130  param_const_iterator param_end() const { return ParamInfo+param_size(); }
131
132  int getNumParams() const { return NumMethodParams; }
133  ParmVarDecl *getParamDecl(int i) const {
134    assert(i < getNumParams() && "Illegal param #");
135    return ParamInfo[i];
136  }
137  void setMethodParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
138
139  AttributeList *getMethodAttrs() const {return MethodAttrs;}
140  bool isInstance() const { return IsInstance; }
141  bool isVariadic() const { return IsVariadic; }
142
143  // Related to protocols declared in  @protocol
144  void setDeclImplementation(ImplementationControl ic) {
145    DeclImplementation = ic;
146  }
147  ImplementationControl getImplementationControl() const {
148    return DeclImplementation;
149  }
150  Stmt *const getBody() const { return Body; }
151  void setBody(Stmt *B) { Body = B; }
152
153  ParmVarDecl *const getSelfDecl() const { return SelfDecl; }
154  void setSelfDecl(ParmVarDecl *PVD) { SelfDecl = PVD; }
155
156  // Implement isa/cast/dyncast/etc.
157  static bool classof(const Decl *D) { return D->getKind() == ObjcMethod; }
158  static bool classof(const ObjcMethodDecl *D) { return true; }
159};
160
161/// ObjcInterfaceDecl - Represents an ObjC class declaration. For example:
162///
163///   // MostPrimitive declares no super class (not particularly useful).
164///   @interface MostPrimitive
165///     // no instance variables or methods.
166///   @end
167///
168///   // NSResponder inherits from NSObject & implements NSCoding (a protocol).
169///   @interface NSResponder : NSObject <NSCoding>
170///   { // instance variables are represented by ObjcIvarDecl.
171///     id nextResponder; // nextResponder instance variable.
172///   }
173///   - (NSResponder *)nextResponder; // return a pointer to NSResponder.
174///   - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer
175///   @end                                    // to an NSEvent.
176///
177///   Unlike C/C++, forward class declarations are accomplished with @class.
178///   Unlike C/C++, @class allows for a list of classes to be forward declared.
179///   Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes
180///   typically inherit from NSObject (an exception is NSProxy).
181///
182class ObjcInterfaceDecl : public TypeDecl {
183
184  /// Class's super class.
185  ObjcInterfaceDecl *SuperClass;
186
187  /// Protocols referenced in interface header declaration
188  ObjcProtocolDecl **ReferencedProtocols;  // Null if none
189  int NumReferencedProtocols;  // -1 if none
190
191  /// Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
192  ObjcIvarDecl **Ivars;   // Null if not defined.
193  int NumIvars;   // -1 if not defined.
194
195  /// instance methods
196  ObjcMethodDecl **InstanceMethods;  // Null if not defined
197  int NumInstanceMethods;  // -1 if not defined
198
199  /// class methods
200  ObjcMethodDecl **ClassMethods;  // Null if not defined
201  int NumClassMethods;  // -1 if not defined
202
203  /// List of categories defined for this class.
204  ObjcCategoryDecl *CategoryList;
205
206  /// class properties
207  ObjcPropertyDecl **PropertyDecl;  // Null if no property
208  int NumPropertyDecl;  // -1 if no property
209
210  bool ForwardDecl:1; // declared with @class.
211  bool InternalInterface:1; // true - no @interface for @implementation
212
213  SourceLocation EndLoc; // marks the '>', '}', or identifier.
214  SourceLocation AtEndLoc; // marks the end of the entire interface.
215public:
216  ObjcInterfaceDecl(SourceLocation atLoc, unsigned numRefProtos,
217                    IdentifierInfo *Id, bool FD = false,
218                    bool isInternal = false)
219    : TypeDecl(ObjcInterface, atLoc, Id, 0), SuperClass(0),
220      ReferencedProtocols(0), NumReferencedProtocols(-1), Ivars(0),
221      NumIvars(-1),
222      InstanceMethods(0), NumInstanceMethods(-1),
223      ClassMethods(0), NumClassMethods(-1),
224      CategoryList(0), PropertyDecl(0), NumPropertyDecl(-1),
225      ForwardDecl(FD), InternalInterface(isInternal) {
226        AllocIntfRefProtocols(numRefProtos);
227      }
228
229  // This is necessary when converting a forward declaration to a definition.
230  void AllocIntfRefProtocols(unsigned numRefProtos) {
231    if (numRefProtos) {
232      ReferencedProtocols = new ObjcProtocolDecl*[numRefProtos];
233      memset(ReferencedProtocols, '\0',
234             numRefProtos*sizeof(ObjcProtocolDecl*));
235      NumReferencedProtocols = numRefProtos;
236    }
237  }
238
239  ObjcProtocolDecl **getReferencedProtocols() const {
240    return ReferencedProtocols;
241  }
242  int getNumIntfRefProtocols() const { return NumReferencedProtocols; }
243
244  int getNumInstanceVariables() const { return NumIvars; }
245
246  typedef ObjcIvarDecl * const *ivar_iterator;
247  unsigned ivar_size() const { return NumIvars == -1 ?0 : NumIvars; }
248  ivar_iterator ivar_begin() const { return Ivars; }
249  ivar_iterator ivar_end() const { return Ivars + ivar_size();}
250
251  int getNumInstanceMethods() const { return NumInstanceMethods; }
252  int getNumClassMethods() const { return NumClassMethods; }
253
254  typedef ObjcMethodDecl * const * instmeth_iterator;
255  instmeth_iterator instmeth_begin() const { return InstanceMethods; }
256  instmeth_iterator instmeth_end() const {
257    return InstanceMethods+(NumInstanceMethods == -1 ? 0 : NumInstanceMethods);
258  }
259
260  typedef ObjcMethodDecl * const * classmeth_iterator;
261  classmeth_iterator classmeth_begin() const { return ClassMethods; }
262  classmeth_iterator classmeth_end() const {
263    return ClassMethods+(NumClassMethods == -1 ? 0 : NumClassMethods);
264  }
265
266  void addInstanceVariablesToClass(ObjcIvarDecl **ivars, unsigned numIvars,
267                                   SourceLocation RBracLoc);
268
269  void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
270                  ObjcMethodDecl **clsMethods, unsigned numClsMembers,
271                  SourceLocation AtEnd);
272
273  bool isForwardDecl() const { return ForwardDecl; }
274  void setForwardDecl(bool val) { ForwardDecl = val; }
275
276  void setIntfRefProtocols(int idx, ObjcProtocolDecl *OID) {
277    assert((idx < NumReferencedProtocols) && "index out of range");
278    ReferencedProtocols[idx] = OID;
279  }
280
281  ObjcInterfaceDecl *getSuperClass() const { return SuperClass; }
282  void setSuperClass(ObjcInterfaceDecl * superCls) { SuperClass = superCls; }
283
284  ObjcCategoryDecl* getCategoryList() const { return CategoryList; }
285  void setCategoryList(ObjcCategoryDecl *category) {
286         CategoryList = category;
287  }
288  ObjcIvarDecl *lookupInstanceVariable(IdentifierInfo *ivarName,
289                                       ObjcInterfaceDecl *&clsDeclared);
290
291  // Get the local instance method declared in this interface.
292  ObjcMethodDecl *getInstanceMethod(Selector &Sel) {
293    for (instmeth_iterator I = instmeth_begin(), E = instmeth_end();
294	     I != E; ++I) {
295      if ((*I)->getSelector() == Sel)
296        return *I;
297    }
298	return 0;
299  }
300  // Get the local class method declared in this interface.
301  ObjcMethodDecl *getClassMethod(Selector &Sel) {
302    for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
303	     I != E; ++I) {
304      if ((*I)->getSelector() == Sel)
305        return *I;
306    }
307	return 0;
308  }
309  // Lookup a method. First, we search locally. If a method isn't
310  // found, we search referenced protocols and class categories.
311  ObjcMethodDecl *lookupInstanceMethod(Selector Sel);
312  ObjcMethodDecl *lookupClassMethod(Selector Sel);
313
314  // Location information, modeled after the Stmt API.
315  SourceLocation getLocStart() const { return getLocation(); } // '@'interface
316  SourceLocation getLocEnd() const { return EndLoc; }
317  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
318
319  // We also need to record the @end location.
320  SourceLocation getAtEndLoc() const { return AtEndLoc; }
321
322  int getNumPropertyDecl() const { return NumPropertyDecl; }
323  void setNumPropertyDecl(int num) { NumPropertyDecl = num; }
324
325  ObjcPropertyDecl **const getPropertyDecl() const { return PropertyDecl; }
326  ObjcPropertyDecl **getPropertyDecl() { return PropertyDecl; }
327  void setPropertyDecls(ObjcPropertyDecl **properties) {
328    PropertyDecl = properties;
329  }
330
331  /// ImplicitInterfaceDecl - check that this is an implicitely declared
332  /// ObjcInterfaceDecl node. This is for legacy objective-c @implementation
333  /// declaration without an @interface declaration.
334  bool ImplicitInterfaceDecl() const { return InternalInterface; }
335
336  static bool classof(const Decl *D) { return D->getKind() == ObjcInterface; }
337  static bool classof(const ObjcInterfaceDecl *D) { return true; }
338};
339
340/// ObjcIvarDecl - Represents an ObjC instance variable. In general, ObjC
341/// instance variables are identical to C. The only exception is Objective-C
342/// supports C++ style access control. For example:
343///
344///   @interface IvarExample : NSObject
345///   {
346///     id defaultToPrivate; // same as C++.
347///   @public:
348///     id canBePublic; // same as C++.
349///   @protected:
350///     id canBeProtected; // same as C++.
351///   @package:
352///     id canBePackage; // framework visibility (not available in C++).
353///   }
354///
355class ObjcIvarDecl : public FieldDecl {
356public:
357  ObjcIvarDecl(SourceLocation L, IdentifierInfo *Id, QualType T)
358    : FieldDecl(ObjcIvar, L, Id, T) {}
359
360  enum AccessControl {
361    None, Private, Protected, Public, Package
362  };
363  void setAccessControl(AccessControl ac) { DeclAccess = ac; }
364  AccessControl getAccessControl() const { return DeclAccess; }
365
366  // Implement isa/cast/dyncast/etc.
367  static bool classof(const Decl *D) { return D->getKind() == ObjcIvar; }
368  static bool classof(const ObjcIvarDecl *D) { return true; }
369private:
370  AccessControl DeclAccess : 3;
371};
372
373
374/// ObjcProtocolDecl - Represents a protocol declaration. ObjC protocols
375/// declare a pure abstract type (i.e no instance variables are permitted).
376/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++
377/// feature with nice semantics and lousy syntax:-). Here is an example:
378///
379/// @protocol NSDraggingInfo
380/// - (NSWindow *)draggingDestinationWindow;
381/// - (NSImage *)draggedImage;
382/// @end
383///
384/// @interface ImplementsNSDraggingInfo : NSObject <NSDraggingInfo>
385/// @end
386///
387/// Objc protocols inspired Java interfaces. Unlike Java, ObjC classes and
388/// protocols are in distinct namespaces. For example, Cocoa defines both
389/// an NSObject protocol and class (which isn't allowed in Java). As a result,
390/// protocols are referenced using angle brackets as follows:
391///
392/// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
393///
394class ObjcProtocolDecl : public NamedDecl {
395  /// referenced protocols
396  ObjcProtocolDecl **ReferencedProtocols;  // Null if none
397  int NumReferencedProtocols;  // -1 if none
398
399  /// protocol instance methods
400  ObjcMethodDecl **InstanceMethods;  // Null if not defined
401  int NumInstanceMethods;  // -1 if not defined
402
403  /// protocol class methods
404  ObjcMethodDecl **ClassMethods;  // Null if not defined
405  int NumClassMethods;  // -1 if not defined
406
407  bool isForwardProtoDecl; // declared with @protocol.
408
409  SourceLocation EndLoc; // marks the '>' or identifier.
410  SourceLocation AtEndLoc; // marks the end of the entire interface.
411public:
412  ObjcProtocolDecl(SourceLocation L, unsigned numRefProtos,
413                   IdentifierInfo *Id, bool FD = false)
414    : NamedDecl(ObjcProtocol, L, Id),
415      ReferencedProtocols(0), NumReferencedProtocols(-1),
416      InstanceMethods(0), NumInstanceMethods(-1),
417      ClassMethods(0), NumClassMethods(-1),
418      isForwardProtoDecl(FD) {
419        AllocReferencedProtocols(numRefProtos);
420      }
421  void AllocReferencedProtocols(unsigned numRefProtos) {
422    if (numRefProtos) {
423      ReferencedProtocols = new ObjcProtocolDecl*[numRefProtos];
424      memset(ReferencedProtocols, '\0',
425             numRefProtos*sizeof(ObjcProtocolDecl*));
426      NumReferencedProtocols = numRefProtos;
427    }
428  }
429  void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
430                  ObjcMethodDecl **clsMethods, unsigned numClsMembers,
431                  SourceLocation AtEndLoc);
432
433  void setReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
434    assert((idx < NumReferencedProtocols) && "index out of range");
435    ReferencedProtocols[idx] = OID;
436  }
437
438  ObjcProtocolDecl** getReferencedProtocols() const {
439    return ReferencedProtocols;
440  }
441  int getNumReferencedProtocols() const { return NumReferencedProtocols; }
442  int getNumInstanceMethods() const { return NumInstanceMethods; }
443  int getNumClassMethods() const { return NumClassMethods; }
444
445  typedef ObjcMethodDecl * const * instmeth_iterator;
446  instmeth_iterator instmeth_begin() const { return InstanceMethods; }
447  instmeth_iterator instmeth_end() const {
448    return InstanceMethods+(NumInstanceMethods == -1 ? 0 : NumInstanceMethods);
449  }
450
451  typedef ObjcMethodDecl * const * classmeth_iterator;
452  classmeth_iterator classmeth_begin() const { return ClassMethods; }
453  classmeth_iterator classmeth_end() const {
454    return ClassMethods+(NumClassMethods == -1 ? 0 : NumClassMethods);
455  }
456
457  // Get the local instance method declared in this interface.
458  ObjcMethodDecl *getInstanceMethod(Selector &Sel) {
459    for (instmeth_iterator I = instmeth_begin(), E = instmeth_end();
460	     I != E; ++I) {
461      if ((*I)->getSelector() == Sel)
462        return *I;
463    }
464	return 0;
465  }
466  // Get the local class method declared in this interface.
467  ObjcMethodDecl *getClassMethod(Selector &Sel) {
468    for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
469	     I != E; ++I) {
470      if ((*I)->getSelector() == Sel)
471        return *I;
472    }
473	return 0;
474  }
475
476  // Lookup a method. First, we search locally. If a method isn't
477  // found, we search referenced protocols and class categories.
478  ObjcMethodDecl *lookupInstanceMethod(Selector Sel);
479  ObjcMethodDecl *lookupClassMethod(Selector Sel);
480
481  bool isForwardDecl() const { return isForwardProtoDecl; }
482  void setForwardDecl(bool val) { isForwardProtoDecl = val; }
483
484  // Location information, modeled after the Stmt API.
485  SourceLocation getLocStart() const { return getLocation(); } // '@'protocol
486  SourceLocation getLocEnd() const { return EndLoc; }
487  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
488
489  // We also need to record the @end location.
490  SourceLocation getAtEndLoc() const { return AtEndLoc; }
491
492  static bool classof(const Decl *D) { return D->getKind() == ObjcProtocol; }
493  static bool classof(const ObjcProtocolDecl *D) { return true; }
494};
495
496/// ObjcClassDecl - Specifies a list of forward class declarations. For example:
497///
498/// @class NSCursor, NSImage, NSPasteboard, NSWindow;
499///
500class ObjcClassDecl : public Decl {
501  ObjcInterfaceDecl **ForwardDecls;
502  unsigned NumForwardDecls;
503public:
504  ObjcClassDecl(SourceLocation L, ObjcInterfaceDecl **Elts, unsigned nElts)
505    : Decl(ObjcClass, L) {
506    if (nElts) {
507      ForwardDecls = new ObjcInterfaceDecl*[nElts];
508      memcpy(ForwardDecls, Elts, nElts*sizeof(ObjcInterfaceDecl*));
509    } else {
510      ForwardDecls = 0;
511    }
512    NumForwardDecls = nElts;
513  }
514  void setInterfaceDecl(unsigned idx, ObjcInterfaceDecl *OID) {
515    assert(idx < NumForwardDecls && "index out of range");
516    ForwardDecls[idx] = OID;
517  }
518  ObjcInterfaceDecl** getForwardDecls() const { return ForwardDecls; }
519  int getNumForwardDecls() const { return NumForwardDecls; }
520
521  static bool classof(const Decl *D) { return D->getKind() == ObjcClass; }
522  static bool classof(const ObjcClassDecl *D) { return true; }
523};
524
525/// ObjcForwardProtocolDecl - Specifies a list of forward protocol declarations.
526/// For example:
527///
528/// @protocol NSTextInput, NSChangeSpelling, NSDraggingInfo;
529///
530class ObjcForwardProtocolDecl : public Decl {
531  ObjcProtocolDecl **ReferencedProtocols;
532  unsigned NumReferencedProtocols;
533public:
534  ObjcForwardProtocolDecl(SourceLocation L,
535                          ObjcProtocolDecl **Elts, unsigned nElts)
536  : Decl(ObjcForwardProtocol, L) {
537    NumReferencedProtocols = nElts;
538    if (nElts) {
539      ReferencedProtocols = new ObjcProtocolDecl*[nElts];
540      memcpy(ReferencedProtocols, Elts, nElts*sizeof(ObjcProtocolDecl*));
541    } else {
542      ReferencedProtocols = 0;
543    }
544  }
545  void setForwardProtocolDecl(unsigned idx, ObjcProtocolDecl *OID) {
546    assert(idx < NumReferencedProtocols && "index out of range");
547    ReferencedProtocols[idx] = OID;
548  }
549
550  unsigned getNumForwardDecls() const { return NumReferencedProtocols; }
551
552  ObjcProtocolDecl *getForwardProtocolDecl(unsigned idx) {
553    assert(idx < NumReferencedProtocols && "index out of range");
554    return ReferencedProtocols[idx];
555  }
556  const ObjcProtocolDecl *getForwardProtocolDecl(unsigned idx) const {
557    assert(idx < NumReferencedProtocols && "index out of range");
558    return ReferencedProtocols[idx];
559  }
560
561  static bool classof(const Decl *D) {
562    return D->getKind() == ObjcForwardProtocol;
563  }
564  static bool classof(const ObjcForwardProtocolDecl *D) { return true; }
565};
566
567/// ObjcCategoryDecl - Represents a category declaration. A category allows
568/// you to add methods to an existing class (without subclassing or modifying
569/// the original class interface or implementation:-). Categories don't allow
570/// you to add instance data. The following example adds "myMethod" to all
571/// NSView's within a process:
572///
573/// @interface NSView (MyViewMethods)
574/// - myMethod;
575/// @end
576///
577/// Cateogries also allow you to split the implementation of a class across
578/// several files (a feature more naturally supported in C++).
579///
580/// Categories were originally inspired by dynamic languages such as Common
581/// Lisp and Smalltalk. More traditional class-based languages (C++, Java)
582/// don't support this level of dynamism, which is both powerful and dangerous.
583///
584class ObjcCategoryDecl : public NamedDecl {
585  /// Interface belonging to this category
586  ObjcInterfaceDecl *ClassInterface;
587
588  /// referenced protocols in this category
589  ObjcProtocolDecl **ReferencedProtocols;  // Null if none
590  int NumReferencedProtocols;  // -1 if none
591
592  /// category instance methods
593  ObjcMethodDecl **InstanceMethods;  // Null if not defined
594  int NumInstanceMethods;  // -1 if not defined
595
596  /// category class methods
597  ObjcMethodDecl **ClassMethods;  // Null if not defined
598  int NumClassMethods;  // -1 if not defined
599
600  /// Next category belonging to this class
601  ObjcCategoryDecl *NextClassCategory;
602
603  SourceLocation EndLoc; // marks the '>' or identifier.
604  SourceLocation AtEndLoc; // marks the end of the entire interface.
605public:
606  ObjcCategoryDecl(SourceLocation L, unsigned numRefProtocol,IdentifierInfo *Id)
607    : NamedDecl(ObjcCategory, L, Id),
608      ClassInterface(0), ReferencedProtocols(0), NumReferencedProtocols(-1),
609      InstanceMethods(0), NumInstanceMethods(-1),
610      ClassMethods(0), NumClassMethods(-1),
611      NextClassCategory(0) {
612        if (numRefProtocol) {
613          ReferencedProtocols = new ObjcProtocolDecl*[numRefProtocol];
614          memset(ReferencedProtocols, '\0',
615                 numRefProtocol*sizeof(ObjcProtocolDecl*));
616          NumReferencedProtocols = numRefProtocol;
617        }
618      }
619
620  ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; }
621  void setClassInterface(ObjcInterfaceDecl *IDecl) { ClassInterface = IDecl; }
622
623  void setCatReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
624    assert((idx < NumReferencedProtocols) && "index out of range");
625    ReferencedProtocols[idx] = OID;
626  }
627
628  ObjcProtocolDecl **getReferencedProtocols() const {
629    return ReferencedProtocols;
630  }
631  int getNumReferencedProtocols() const { return NumReferencedProtocols; }
632  int getNumInstanceMethods() const { return NumInstanceMethods; }
633  int getNumClassMethods() const { return NumClassMethods; }
634
635  typedef ObjcMethodDecl * const * instmeth_iterator;
636  instmeth_iterator instmeth_begin() const { return InstanceMethods; }
637  instmeth_iterator instmeth_end() const {
638    return InstanceMethods+(NumInstanceMethods == -1 ? 0 : NumInstanceMethods);
639  }
640
641  typedef ObjcMethodDecl * const * classmeth_iterator;
642  classmeth_iterator classmeth_begin() const { return ClassMethods; }
643  classmeth_iterator classmeth_end() const {
644    return ClassMethods+(NumClassMethods == -1 ? 0 : NumClassMethods);
645  }
646
647  // Get the local instance method declared in this interface.
648  ObjcMethodDecl *getInstanceMethod(Selector &Sel) {
649    for (instmeth_iterator I = instmeth_begin(), E = instmeth_end();
650	     I != E; ++I) {
651      if ((*I)->getSelector() == Sel)
652        return *I;
653    }
654	return 0;
655  }
656  // Get the local class method declared in this interface.
657  ObjcMethodDecl *getClassMethod(Selector &Sel) {
658    for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
659	     I != E; ++I) {
660      if ((*I)->getSelector() == Sel)
661        return *I;
662    }
663	return 0;
664  }
665
666  void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
667                  ObjcMethodDecl **clsMethods, unsigned numClsMembers,
668                  SourceLocation AtEndLoc);
669
670  ObjcCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
671  void insertNextClassCategory() {
672    NextClassCategory = ClassInterface->getCategoryList();
673    ClassInterface->setCategoryList(this);
674  }
675  // Location information, modeled after the Stmt API.
676  SourceLocation getLocStart() const { return getLocation(); } // '@'interface
677  SourceLocation getLocEnd() const { return EndLoc; }
678  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
679
680  // We also need to record the @end location.
681  SourceLocation getAtEndLoc() const { return AtEndLoc; }
682
683  static bool classof(const Decl *D) { return D->getKind() == ObjcCategory; }
684  static bool classof(const ObjcCategoryDecl *D) { return true; }
685};
686
687/// ObjcCategoryImplDecl - An object of this class encapsulates a category
688/// @implementation declaration.
689class ObjcCategoryImplDecl : public NamedDecl {
690  /// Class interface for this category implementation
691  ObjcInterfaceDecl *ClassInterface;
692
693  /// implemented instance methods
694  llvm::SmallVector<ObjcMethodDecl*, 32> InstanceMethods;
695
696  /// implemented class methods
697  llvm::SmallVector<ObjcMethodDecl*, 32> ClassMethods;
698
699  SourceLocation EndLoc;
700public:
701  ObjcCategoryImplDecl(SourceLocation L, IdentifierInfo *Id,
702                       ObjcInterfaceDecl *classInterface)
703    : NamedDecl(ObjcCategoryImpl, L, Id), ClassInterface(classInterface) {}
704
705  ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; }
706
707  unsigned getNumInstanceMethods() const { return InstanceMethods.size(); }
708  unsigned getNumClassMethods() const { return ClassMethods.size(); }
709
710  void addInstanceMethod(ObjcMethodDecl *method) {
711    InstanceMethods.push_back(method);
712  }
713  void addClassMethod(ObjcMethodDecl *method) {
714    ClassMethods.push_back(method);
715  }
716  // Get the instance method definition for this implementation.
717  ObjcMethodDecl *getInstanceMethod(Selector Sel);
718
719  // Get the class method definition for this implementation.
720  ObjcMethodDecl *getClassMethod(Selector Sel);
721
722  typedef llvm::SmallVector<ObjcMethodDecl*, 32>::const_iterator
723    instmeth_iterator;
724  instmeth_iterator instmeth_begin() const { return InstanceMethods.begin(); }
725  instmeth_iterator instmeth_end() const { return InstanceMethods.end(); }
726
727  typedef llvm::SmallVector<ObjcMethodDecl*, 32>::const_iterator
728    classmeth_iterator;
729  classmeth_iterator classmeth_begin() const { return ClassMethods.begin(); }
730  classmeth_iterator classmeth_end() const { return ClassMethods.end(); }
731
732
733  // Location information, modeled after the Stmt API.
734  SourceLocation getLocStart() const { return getLocation(); }
735  SourceLocation getLocEnd() const { return EndLoc; }
736  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
737
738  static bool classof(const Decl *D) { return D->getKind() == ObjcCategoryImpl;}
739  static bool classof(const ObjcCategoryImplDecl *D) { return true; }
740};
741
742/// ObjcImplementationDecl - Represents a class definition - this is where
743/// method definitions are specified. For example:
744///
745/// @implementation MyClass
746/// - (void)myMethod { /* do something */ }
747/// @end
748///
749/// Typically, instance variables are specified in the class interface,
750/// *not* in the implemenentation. Nevertheless (for legacy reasons), we
751/// allow instance variables to be specified in the implementation. When
752/// specified, they need to be *identical* to the interface. Now that we
753/// have support for non-fragile ivars in ObjC 2.0, we can consider removing
754/// the legacy semantics and allow developers to move private ivar declarations
755/// from the class interface to the class implementation (but I digress:-)
756///
757class ObjcImplementationDecl : public NamedDecl {
758  /// Class interface for this category implementation
759  ObjcInterfaceDecl *ClassInterface;
760
761  /// Implementation Class's super class.
762  ObjcInterfaceDecl *SuperClass;
763
764  /// Optional Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
765  ObjcIvarDecl **Ivars;   // Null if not specified
766  int NumIvars;   // -1 if not defined.
767
768  /// implemented instance methods
769  llvm::SmallVector<ObjcMethodDecl*, 32> InstanceMethods;
770
771  /// implemented class methods
772  llvm::SmallVector<ObjcMethodDecl*, 32> ClassMethods;
773
774  SourceLocation EndLoc;
775public:
776  ObjcImplementationDecl(SourceLocation L, IdentifierInfo *Id,
777                         ObjcInterfaceDecl *classInterface,
778                         ObjcInterfaceDecl *superDecl)
779    : NamedDecl(ObjcImplementation, L, Id),
780      ClassInterface(classInterface), SuperClass(superDecl),
781      Ivars(0), NumIvars(-1) {}
782
783  void ObjcAddInstanceVariablesToClassImpl(ObjcIvarDecl **ivars,
784                                           unsigned numIvars);
785
786  void addInstanceMethod(ObjcMethodDecl *method) {
787    InstanceMethods.push_back(method);
788  }
789  void addClassMethod(ObjcMethodDecl *method) {
790    ClassMethods.push_back(method);
791  }
792  // Location information, modeled after the Stmt API.
793  SourceLocation getLocStart() const { return getLocation(); }
794  SourceLocation getLocEnd() const { return EndLoc; }
795  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
796
797  ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; }
798  ObjcInterfaceDecl *getSuperClass() const { return SuperClass; }
799
800  void setSuperClass(ObjcInterfaceDecl * superCls)
801         { SuperClass = superCls; }
802
803  int getNumInstanceMethods() const { return InstanceMethods.size(); }
804  int getNumClassMethods() const { return ClassMethods.size(); }
805
806  int getImplDeclNumIvars() const { return NumIvars; }
807
808
809  typedef llvm::SmallVector<ObjcMethodDecl*, 32>::const_iterator
810       instmeth_iterator;
811  instmeth_iterator instmeth_begin() const { return InstanceMethods.begin(); }
812  instmeth_iterator instmeth_end() const { return InstanceMethods.end(); }
813
814  typedef llvm::SmallVector<ObjcMethodDecl*, 32>::const_iterator
815    classmeth_iterator;
816  classmeth_iterator classmeth_begin() const { return ClassMethods.begin(); }
817  classmeth_iterator classmeth_end() const { return ClassMethods.end(); }
818
819  // Get the instance method definition for this implementation.
820  ObjcMethodDecl *getInstanceMethod(Selector Sel);
821
822  // Get the class method definition for this implementation.
823  ObjcMethodDecl *getClassMethod(Selector Sel);
824
825  typedef ObjcIvarDecl * const *ivar_iterator;
826  ivar_iterator ivar_begin() const { return Ivars; }
827  ivar_iterator ivar_end() const {return Ivars+(NumIvars == -1 ? 0 : NumIvars);}
828
829  static bool classof(const Decl *D) {
830    return D->getKind() == ObjcImplementation;
831  }
832  static bool classof(const ObjcImplementationDecl *D) { return true; }
833};
834
835/// ObjcCompatibleAliasDecl - Represents alias of a class. This alias is
836/// declared as @compatibility_alias alias class.
837class ObjcCompatibleAliasDecl : public ScopedDecl {
838  /// Class that this is an alias of.
839  ObjcInterfaceDecl *AliasedClass;
840
841public:
842  ObjcCompatibleAliasDecl(SourceLocation L, IdentifierInfo *Id,
843                         ObjcInterfaceDecl* aliasedClass)
844  : ScopedDecl(CompatibleAlias, L, Id, 0),
845  AliasedClass(aliasedClass) {}
846
847  ObjcInterfaceDecl *getClassInterface() const { return AliasedClass; }
848
849  static bool classof(const Decl *D) {
850    return D->getKind() == CompatibleAlias;
851  }
852  static bool classof(const ObjcCompatibleAliasDecl *D) { return true; }
853
854};
855
856class ObjcPropertyDecl : public Decl {
857public:
858  enum PropertyAttributeKind { OBJC_PR_noattr = 0x0,
859                       OBJC_PR_readonly = 0x01,
860                       OBJC_PR_getter = 0x02,
861                       OBJC_PR_assign = 0x04,
862                       OBJC_PR_readwrite = 0x08,
863                       OBJC_PR_retain = 0x10,
864                       OBJC_PR_copy = 0x20,
865                       OBJC_PR_nonatomic = 0x40,
866                       OBJC_PR_setter = 0x80 };
867private:
868  // List of property name declarations
869  // FIXME: Property is not an ivar.
870  ObjcIvarDecl **PropertyDecls;
871  int NumPropertyDecls;
872
873  PropertyAttributeKind PropertyAttributes : 8;
874
875  IdentifierInfo *GetterName;    // getter name of NULL if no getter
876  IdentifierInfo *SetterName;    // setter name of NULL if no setter
877
878public:
879  ObjcPropertyDecl(SourceLocation L)
880  : Decl(PropertyDecl, L),
881  PropertyDecls(0), NumPropertyDecls(-1), PropertyAttributes(OBJC_PR_noattr),
882  GetterName(0), SetterName(0) {}
883
884  ObjcIvarDecl **const getPropertyDecls() const { return PropertyDecls; }
885  void setPropertyDecls(ObjcIvarDecl **property) { PropertyDecls = property; }
886
887  const int getNumPropertyDecls() const { return NumPropertyDecls; }
888  void setNumPropertyDecls(int num) { NumPropertyDecls = num; }
889
890  const PropertyAttributeKind getPropertyAttributes() const
891    { return PropertyAttributes; }
892  void setPropertyAttributes(PropertyAttributeKind PRVal) {
893    PropertyAttributes =
894    (PropertyAttributeKind) (PropertyAttributes | PRVal);
895  }
896
897  const IdentifierInfo *getGetterName() const { return GetterName; }
898  IdentifierInfo *getGetterName() { return GetterName; }
899  void setGetterName(IdentifierInfo *Id) { GetterName = Id; }
900
901  const IdentifierInfo *getSetterName() const { return SetterName; }
902  IdentifierInfo *getSetterName() { return SetterName; }
903  void setSetterName(IdentifierInfo *Id) { SetterName = Id; }
904
905  static bool classof(const Decl *D) {
906    return D->getKind() == PropertyDecl;
907  }
908  static bool classof(const ObjcPropertyDecl *D) { return true; }
909};
910
911}  // end namespace clang
912#endif
913