Decl.h revision d664ff7beb054a2f2f56ec438ff3ce65be96eddc
1//===--- Decl.h - Classes for representing declarations ---------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner 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 Decl interface and subclasses.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_DECL_H
15#define LLVM_CLANG_AST_DECL_H
16
17#include "clang/Basic/SourceLocation.h"
18#include "clang/AST/Type.h"
19#include "llvm/ADT/APSInt.h"
20#include "clang/Lex/IdentifierTable.h" // FIXME: should be in Basic, not Lex.
21
22namespace clang {
23class Expr;
24class Stmt;
25class FunctionDecl;
26class AttributeList;
27class ObjcIvarDecl;
28class ObjcMethodDecl;
29class ObjcProtocolDecl;
30class ObjcCategoryDecl;
31
32/// Decl - This represents one declaration (or definition), e.g. a variable,
33/// typedef, function, struct, etc.
34///
35class Decl {
36public:
37  enum Kind {
38    // Concrete sub-classes of ValueDecl
39    Function, BlockVariable, FileVariable, ParmVariable, EnumConstant,
40    // Concrete sub-classes of TypeDecl
41    Typedef, Struct, Union, Class, Enum, ObjcInterface, ObjcClass, ObjcMethod,
42    ObjcProtocol, ObjcForwardProtocol, ObjcCategory,
43    ObjcImplementation,
44    // Concrete sub-class of Decl
45    Field, ObjcIvar
46  };
47
48  /// IdentifierNamespace - According to C99 6.2.3, there are four namespaces,
49  /// labels, tags, members and ordinary identifiers.
50  /// Objective-c protocols have their own namespace, so a protocol can have
51  /// the same name as category, class, struct, typedef, etc.
52  enum IdentifierNamespace {
53    IDNS_Label,
54    IDNS_Tag,
55    IDNS_Member,
56    IDNS_Protocol,
57    IDNS_Ordinary
58  };
59
60  enum ImplementationControl { None, Required, Optional };
61
62private:
63  /// DeclKind - This indicates which class this is.
64  Kind DeclKind   :  8;
65
66  /// InvalidDecl - This indicates a semantic error occurred.
67  unsigned int InvalidDecl :  1;
68
69  /// instance (true) or class (false) method.
70  bool IsInstance : 1;
71  /// @required/@optional
72  ImplementationControl DeclImplementation : 2;
73
74protected:
75  Decl(Kind DK) : DeclKind(DK), InvalidDecl(0),
76  IsInstance(false), DeclImplementation(None) {
77    if (Decl::CollectingStats()) addDeclKind(DK);
78  }
79
80  Decl(Kind DK, bool isInstance, ImplementationControl implControl)
81  : DeclKind(DK), InvalidDecl(0),
82  IsInstance(isInstance), DeclImplementation(implControl) {
83    if (Decl::CollectingStats()) addDeclKind(DK);
84  }
85  virtual ~Decl();
86
87public:
88
89  Kind getKind() const { return DeclKind; }
90  const char *getDeclKindName() const;
91
92  /// setInvalidDecl - Indicates the Decl had a semantic error. This
93  /// allows for graceful error recovery.
94  void setInvalidDecl() { InvalidDecl = 1; }
95  int isInvalidDecl() const { return InvalidDecl; }
96  bool isInstance() const { return IsInstance; }
97  ImplementationControl  getImplementationControl() const
98  { return DeclImplementation; }
99
100  IdentifierNamespace getIdentifierNamespace() const {
101    switch (DeclKind) {
102    default: assert(0 && "Unknown decl kind!");
103    case Typedef:
104    case Function:
105    case BlockVariable:
106    case FileVariable:
107    case ParmVariable:
108    case EnumConstant:
109    case ObjcInterface:
110      return IDNS_Ordinary;
111    case Struct:
112    case Union:
113    case Class:
114    case Enum:
115      return IDNS_Tag;
116    case ObjcProtocol:
117      return IDNS_Protocol;
118    }
119  }
120  // global temp stats (until we have a per-module visitor)
121  static void addDeclKind(const Kind k);
122  static bool CollectingStats(bool enable=false);
123  static void PrintStats();
124
125  // Implement isa/cast/dyncast/etc.
126  static bool classof(const Decl *) { return true; }
127};
128
129/// ScopedDecl - Represent lexically scoped names, used for all ValueDecl's
130/// and TypeDecl's.
131class ScopedDecl : public Decl {
132  /// Identifier - The identifier for this declaration (e.g. the name for the
133  /// variable, the tag for a struct).
134  IdentifierInfo *Identifier;
135
136  /// Loc - The location that this decl.
137  SourceLocation Loc;
138
139  /// NextDeclarator - If this decl was part of a multi-declarator declaration,
140  /// such as "int X, Y, *Z;" this indicates Decl for the next declarator.
141  ScopedDecl *NextDeclarator;
142
143  /// When this decl is in scope while parsing, the Next field contains a
144  /// pointer to the shadowed decl of the same name.  When the scope is popped,
145  /// Decls are relinked onto a containing decl object.
146  ///
147  ScopedDecl *Next;
148protected:
149  ScopedDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, ScopedDecl *PrevDecl)
150    : Decl(DK), Identifier(Id), Loc(L), NextDeclarator(PrevDecl), Next(0) {}
151public:
152  IdentifierInfo *getIdentifier() const { return Identifier; }
153  SourceLocation getLocation() const { return Loc; }
154  void setLocation(SourceLocation L) { Loc = L; }
155  const char *getName() const;
156
157  ScopedDecl *getNext() const { return Next; }
158  void setNext(ScopedDecl *N) { Next = N; }
159
160  /// getNextDeclarator - If this decl was part of a multi-declarator
161  /// declaration, such as "int X, Y, *Z;" this returns the decl for the next
162  /// declarator.  Otherwise it returns null.
163  ScopedDecl *getNextDeclarator() { return NextDeclarator; }
164  const ScopedDecl *getNextDeclarator() const { return NextDeclarator; }
165  void setNextDeclarator(ScopedDecl *N) { NextDeclarator = N; }
166
167  // Implement isa/cast/dyncast/etc. - true for all ValueDecl's and TypeDecl's.
168  static bool classof(const Decl *D) {
169    return (D->getKind() >= Function && D->getKind() <= EnumConstant) ||
170           (D->getKind() >= Typedef && D->getKind() <= Enum);
171  }
172  static bool classof(const ScopedDecl *D) { return true; }
173};
174
175/// ValueDecl - Represent the declaration of a variable (in which case it is
176/// an lvalue) a function (in which case it is a function designator) or
177/// an enum constant.
178class ValueDecl : public ScopedDecl {
179  QualType DeclType;
180protected:
181  ValueDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, QualType T,
182            ScopedDecl *PrevDecl) : ScopedDecl(DK, L, Id, PrevDecl), DeclType(T) {}
183public:
184  QualType getType() const { return DeclType; }
185  void setType(QualType newType) { DeclType = newType; }
186  QualType getCanonicalType() const { return DeclType.getCanonicalType(); }
187
188  // Implement isa/cast/dyncast/etc.
189  static bool classof(const Decl *D) {
190    return D->getKind() >= Function && D->getKind() <= EnumConstant;
191  }
192  static bool classof(const ValueDecl *D) { return true; }
193};
194
195/// VarDecl - An instance of this class is created to represent a variable
196/// declaration or definition.
197class VarDecl : public ValueDecl {
198public:
199  enum StorageClass {
200    None, Extern, Static, Auto, Register
201  };
202  StorageClass getStorageClass() const { return SClass; }
203
204  const Expr *getInit() const { return Init; }
205  Expr *getInit() { return Init; }
206  void setInit(Expr *I) { Init = I; }
207
208  // hasAutoStorage - Returns true if either the implicit or explicit
209  //  storage class of a variable is "auto."  In particular, variables
210  //  declared within a function that lack a storage keyword are
211  //  implicitly "auto", but are represented internally with a storage
212  //  class of None.
213  bool hasAutoStorage() {
214    return (SClass == Auto || (SClass == None && getKind() != FileVariable));
215  }
216
217  // hasStaticStorage - Returns true if either the implicit or
218  //  explicit storage class of a variable is "static."  In
219  //  particular, variables declared within a file (outside of a
220  //  function) that lack a storage keyword are implicitly "static,"
221  //  but are represented internally with a storage class of "None".
222  bool hasStaticStorage() {
223    return (SClass == Static || (SClass == None && getKind() == FileVariable));
224  }
225
226  // hasLocalStorage - Returns true if a variable with function scope
227  //  is a non-static local variable.
228  bool hasLocalStorage() { return (hasAutoStorage() || SClass == Register); }
229
230  // hasGlobalStorage - Returns true for all variables that do not
231  //  have local storage.  This includs all global variables as well
232  //  as static variables declared within a function.
233  bool hasGlobalStorage() { return !hasAutoStorage(); }
234
235  // Implement isa/cast/dyncast/etc.
236  static bool classof(const Decl *D) {
237    return D->getKind() >= BlockVariable && D->getKind() <= ParmVariable;
238  }
239  static bool classof(const VarDecl *D) { return true; }
240protected:
241  VarDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, QualType T,
242          StorageClass SC, ScopedDecl *PrevDecl)
243    : ValueDecl(DK, L, Id, T, PrevDecl), Init(0) { SClass = SC; }
244private:
245  StorageClass SClass;
246  Expr *Init;
247};
248
249/// BlockVarDecl - Represent a local variable declaration.
250class BlockVarDecl : public VarDecl {
251public:
252  BlockVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S,
253               ScopedDecl *PrevDecl)
254    : VarDecl(BlockVariable, L, Id, T, S, PrevDecl) {}
255
256  // Implement isa/cast/dyncast/etc.
257  static bool classof(const Decl *D) { return D->getKind() == BlockVariable; }
258  static bool classof(const BlockVarDecl *D) { return true; }
259};
260
261/// FileVarDecl - Represent a file scoped variable declaration. This
262/// will allow us to reason about external variable declarations and tentative
263/// definitions (C99 6.9.2p2) using our type system (without storing a
264/// pointer to the decl's scope, which is transient).
265class FileVarDecl : public VarDecl {
266public:
267  FileVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S,
268              ScopedDecl *PrevDecl)
269    : VarDecl(FileVariable, L, Id, T, S, PrevDecl) {}
270
271  // Implement isa/cast/dyncast/etc.
272  static bool classof(const Decl *D) { return D->getKind() == FileVariable; }
273  static bool classof(const FileVarDecl *D) { return true; }
274};
275
276/// ParmVarDecl - Represent a parameter to a function.
277class ParmVarDecl : public VarDecl {
278public:
279  ParmVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S,
280              ScopedDecl *PrevDecl)
281    : VarDecl(ParmVariable, L, Id, T, S, PrevDecl) {}
282
283  // Implement isa/cast/dyncast/etc.
284  static bool classof(const Decl *D) { return D->getKind() == ParmVariable; }
285  static bool classof(const ParmVarDecl *D) { return true; }
286};
287
288/// FunctionDecl - An instance of this class is created to represent a function
289/// declaration or definition.
290class FunctionDecl : public ValueDecl {
291public:
292  enum StorageClass {
293    None, Extern, Static
294  };
295  FunctionDecl(SourceLocation L, IdentifierInfo *Id, QualType T,
296               StorageClass S = None, bool isInline = false,
297               ScopedDecl *PrevDecl = 0)
298    : ValueDecl(Function, L, Id, T, PrevDecl),
299      ParamInfo(0), Body(0), DeclChain(0), SClass(S), IsInline(isInline) {}
300  virtual ~FunctionDecl();
301
302  Stmt *getBody() const { return Body; }
303  void setBody(Stmt *B) { Body = B; }
304
305  ScopedDecl *getDeclChain() const { return DeclChain; }
306  void setDeclChain(ScopedDecl *D) { DeclChain = D; }
307
308  unsigned getNumParams() const;
309  const ParmVarDecl *getParamDecl(unsigned i) const {
310    assert(i < getNumParams() && "Illegal param #");
311    return ParamInfo[i];
312  }
313  ParmVarDecl *getParamDecl(unsigned i) {
314    assert(i < getNumParams() && "Illegal param #");
315    return ParamInfo[i];
316  }
317  void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
318
319  QualType getResultType() const {
320    return cast<FunctionType>(getType())->getResultType();
321  }
322  StorageClass getStorageClass() const { return SClass; }
323  bool isInline() const { return IsInline; }
324
325  // Implement isa/cast/dyncast/etc.
326  static bool classof(const Decl *D) { return D->getKind() == Function; }
327  static bool classof(const FunctionDecl *D) { return true; }
328private:
329  /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
330  /// parameters of this function.  This is null if a prototype or if there are
331  /// no formals.  TODO: we could allocate this space immediately after the
332  /// FunctionDecl object to save an allocation like FunctionType does.
333  ParmVarDecl **ParamInfo;
334
335  Stmt *Body;  // Null if a prototype.
336
337  /// DeclChain - Linked list of declarations that are defined inside this
338  /// function.
339  ScopedDecl *DeclChain;
340
341  StorageClass SClass : 2;
342  bool IsInline : 1;
343};
344
345
346/// FieldDecl - An instance of this class is created by Sema::ActOnField to
347/// represent a member of a struct/union/class.
348class FieldDecl : public Decl {
349  /// Identifier - The identifier for this declaration (e.g. the name for the
350  /// variable, the tag for a struct).
351  IdentifierInfo *Identifier;
352
353  /// Loc - The location that this decl.
354  SourceLocation Loc;
355
356  QualType DeclType;
357public:
358  FieldDecl(SourceLocation L, IdentifierInfo *Id, QualType T)
359    : Decl(Field), Identifier(Id), Loc(L), DeclType(T) {}
360  FieldDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, QualType T)
361    : Decl(DK), Identifier(Id), Loc(L), DeclType(T) {}
362
363  IdentifierInfo *getIdentifier() const { return Identifier; }
364  SourceLocation getLocation() const { return Loc; }
365  void setLocation(SourceLocation L) { Loc = L; }
366  const char *getName() const;
367
368  QualType getType() const { return DeclType; }
369  QualType getCanonicalType() const { return DeclType.getCanonicalType(); }
370
371  // Implement isa/cast/dyncast/etc.
372  static bool classof(const Decl *D) {
373    return D->getKind() == Field || D->getKind() == ObjcIvar;
374  }
375  static bool classof(const FieldDecl *D) { return true; }
376};
377
378/// EnumConstantDecl - An instance of this object exists for each enum constant
379/// that is defined.  For example, in "enum X {a,b}", each of a/b are
380/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a
381/// TagType for the X EnumDecl.
382class EnumConstantDecl : public ValueDecl {
383  Expr *Init; // an integer constant expression
384  llvm::APSInt Val; // The value.
385public:
386  EnumConstantDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E,
387                   const llvm::APSInt &V, ScopedDecl *PrevDecl)
388    : ValueDecl(EnumConstant, L, Id, T, PrevDecl), Init(E), Val(V) {}
389
390  const Expr *getInitExpr() const { return Init; }
391  Expr *getInitExpr() { return Init; }
392  const llvm::APSInt &getInitVal() const { return Val; }
393
394  void setInitExpr(Expr *E) { Init = E; }
395  void setInitVal(llvm::APSInt &V) { Val = V; }
396
397  // Implement isa/cast/dyncast/etc.
398  static bool classof(const Decl *D) {
399    return D->getKind() == EnumConstant;
400  }
401  static bool classof(const EnumConstantDecl *D) { return true; }
402};
403
404
405/// TypeDecl - Represents a declaration of a type.
406///
407class TypeDecl : public ScopedDecl {
408  /// TypeForDecl - This indicates the Type object that represents this
409  /// TypeDecl.  It is a cache maintained by ASTContext::getTypedefType and
410  /// ASTContext::getTagDeclType.
411  Type *TypeForDecl;
412  friend class ASTContext;
413protected:
414  TypeDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, ScopedDecl *PrevDecl)
415    : ScopedDecl(DK, L, Id, PrevDecl), TypeForDecl(0) {}
416public:
417  // Implement isa/cast/dyncast/etc.
418  static bool classof(const Decl *D) {
419    return D->getKind() >= Typedef && D->getKind() <= Enum;
420  }
421  static bool classof(const TypeDecl *D) { return true; }
422};
423
424
425class TypedefDecl : public TypeDecl {
426  /// UnderlyingType - This is the type the typedef is set to.
427  QualType UnderlyingType;
428public:
429  TypedefDecl(SourceLocation L, IdentifierInfo *Id, QualType T, ScopedDecl *PD)
430    : TypeDecl(Typedef, L, Id, PD), UnderlyingType(T) {}
431
432  QualType getUnderlyingType() const { return UnderlyingType; }
433  void setUnderlyingType(QualType newType) { UnderlyingType = newType; }
434
435  // Implement isa/cast/dyncast/etc.
436  static bool classof(const Decl *D) { return D->getKind() == Typedef; }
437  static bool classof(const TypedefDecl *D) { return true; }
438};
439
440
441/// TagDecl - Represents the declaration of a struct/union/class/enum.
442class TagDecl : public TypeDecl {
443  /// IsDefinition - True if this is a definition ("struct foo {};"), false if
444  /// it is a declaration ("struct foo;").
445  bool IsDefinition : 1;
446protected:
447  TagDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, ScopedDecl *PrevDecl)
448    : TypeDecl(DK, L, Id, PrevDecl) {
449    IsDefinition = false;
450  }
451public:
452
453  /// isDefinition - Return true if this decl has its body specified.
454  bool isDefinition() const {
455    return IsDefinition;
456  }
457
458  const char *getKindName() const {
459    switch (getKind()) {
460    default: assert(0 && "Unknown TagDecl!");
461    case Struct: return "struct";
462    case Union:  return "union";
463    case Class:  return "class";
464    case Enum:   return "enum";
465    }
466  }
467
468  // Implement isa/cast/dyncast/etc.
469  static bool classof(const Decl *D) {
470    return D->getKind() == Struct || D->getKind() == Union ||
471           D->getKind() == Class || D->getKind() == Enum;
472  }
473  static bool classof(const TagDecl *D) { return true; }
474protected:
475  void setDefinition(bool V) { IsDefinition = V; }
476};
477
478/// EnumDecl - Represents an enum.  As an extension, we allow forward-declared
479/// enums.
480class EnumDecl : public TagDecl {
481  /// ElementList - this is a linked list of EnumConstantDecl's which are linked
482  /// together through their getNextDeclarator pointers.
483  EnumConstantDecl *ElementList;
484
485  /// IntegerType - This represent the integer type that the enum corresponds
486  /// to for code generation purposes.  Note that the enumerator constants may
487  /// have a different type than this does.
488  QualType IntegerType;
489public:
490  EnumDecl(SourceLocation L, IdentifierInfo *Id, ScopedDecl *PrevDecl)
491    : TagDecl(Enum, L, Id, PrevDecl) {
492    ElementList = 0;
493  }
494
495  /// defineElements - When created, EnumDecl correspond to a forward declared
496  /// enum.  This method is used to mark the decl as being defined, with the
497  /// specified list of enums.
498  void defineElements(EnumConstantDecl *ListHead, QualType NewType) {
499    assert(!isDefinition() && "Cannot redefine enums!");
500    ElementList = ListHead;
501    setDefinition(true);
502
503    IntegerType = NewType;
504  }
505
506  /// getIntegerType - Return the integer type this enum decl corresponds to.
507  /// This returns a null qualtype for an enum forward definition.
508  QualType getIntegerType() const { return IntegerType; }
509
510  /// getEnumConstantList - Return the first EnumConstantDecl in the enum.
511  ///
512  EnumConstantDecl *getEnumConstantList() { return ElementList; }
513  const EnumConstantDecl *getEnumConstantList() const { return ElementList; }
514
515  static bool classof(const Decl *D) {
516    return D->getKind() == Enum;
517  }
518  static bool classof(const EnumDecl *D) { return true; }
519};
520
521
522/// RecordDecl - Represents a struct/union/class.  For example:
523///   struct X;                  // Forward declaration, no "body".
524///   union Y { int A, B; };     // Has body with members A and B (FieldDecls).
525///
526class RecordDecl : public TagDecl {
527  /// HasFlexibleArrayMember - This is true if this struct ends with a flexible
528  /// array member (e.g. int X[]) or if this union contains a struct that does.
529  /// If so, this cannot be contained in arrays or other structs as a member.
530  bool HasFlexibleArrayMember : 1;
531
532  /// Members/NumMembers - This is a new[]'d array of pointers to Decls.
533  FieldDecl **Members;   // Null if not defined.
534  int NumMembers;   // -1 if not defined.
535public:
536  RecordDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, ScopedDecl*PrevDecl)
537    : TagDecl(DK, L, Id, PrevDecl) {
538    HasFlexibleArrayMember = false;
539    assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
540    Members = 0;
541    NumMembers = -1;
542  }
543
544  bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
545  void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
546
547  /// getNumMembers - Return the number of members, or -1 if this is a forward
548  /// definition.
549  int getNumMembers() const { return NumMembers; }
550  const FieldDecl *getMember(unsigned i) const { return Members[i]; }
551  FieldDecl *getMember(unsigned i) { return Members[i]; }
552
553  /// defineBody - When created, RecordDecl's correspond to a forward declared
554  /// record.  This method is used to mark the decl as being defined, with the
555  /// specified contents.
556  void defineBody(FieldDecl **Members, unsigned numMembers);
557
558  /// getMember - If the member doesn't exist, or there are no members, this
559  /// function will return 0;
560  FieldDecl *getMember(IdentifierInfo *name);
561
562  static bool classof(const Decl *D) {
563    return D->getKind() == Struct || D->getKind() == Union ||
564           D->getKind() == Class;
565  }
566  static bool classof(const RecordDecl *D) { return true; }
567};
568
569class ObjcInterfaceDecl : public TypeDecl {
570
571  /// Class's super class.
572  ObjcInterfaceDecl *SuperClass;
573
574  /// Protocols referenced in interface header declaration
575  ObjcProtocolDecl **IntfRefProtocols;  // Null if no referenced protocols
576  int NumIntfRefProtocols;  // -1 if no referenced protocols
577
578  /// Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
579  ObjcIvarDecl **Ivars;   // Null if class has no ivars
580  int NumIvars;   // -1 if class has no ivars
581
582  /// instance methods
583  ObjcMethodDecl **InsMethods;  // Null if class has no instance methods
584  int NumInsMethods;  // -1 if class has no instance methods
585
586  /// class methods
587  ObjcMethodDecl **ClsMethods;  // Null if class has no class methods
588  int NumClsMethods;  // -1 if class has no class methods
589
590  /// List of categories defined for this class.
591  ObjcCategoryDecl *ListCategories;
592
593  bool isForwardDecl; // declared with @class.
594public:
595  ObjcInterfaceDecl(SourceLocation L, unsigned numRefProtos,
596                    IdentifierInfo *Id, bool FD = false)
597    : TypeDecl(ObjcInterface, L, Id, 0),
598      SuperClass(0),
599      IntfRefProtocols(0), NumIntfRefProtocols(-1),
600      Ivars(0), NumIvars(-1),
601      InsMethods(0), NumInsMethods(-1), ClsMethods(0), NumClsMethods(-1),
602      ListCategories(0),
603      isForwardDecl(FD) {
604        AllocIntfRefProtocols(numRefProtos);
605      }
606
607  void AllocIntfRefProtocols(unsigned numRefProtos) {
608    if (numRefProtos) {
609      IntfRefProtocols = new ObjcProtocolDecl*[numRefProtos];
610      memset(IntfRefProtocols, '\0',
611             numRefProtos*sizeof(ObjcProtocolDecl*));
612      NumIntfRefProtocols = numRefProtos;
613    }
614  }
615
616  ObjcProtocolDecl **getIntfRefProtocols() const { return IntfRefProtocols; }
617  int getNumIntfRefProtocols() const { return NumIntfRefProtocols; }
618
619  ObjcIvarDecl **getIntfDeclIvars() const { return Ivars; }
620  int getIntfDeclNumIvars() const { return NumIvars; }
621
622  ObjcMethodDecl** getInsMethods() const { return InsMethods; }
623  int getNumInsMethods() const { return NumInsMethods; }
624
625  ObjcMethodDecl** getClsMethods() const { return ClsMethods; }
626  int getNumClsMethods() const { return NumClsMethods; }
627
628  void ObjcAddInstanceVariablesToClass(ObjcIvarDecl **ivars,
629				       unsigned numIvars);
630
631  void ObjcAddMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
632                      ObjcMethodDecl **clsMethods, unsigned numClsMembers);
633
634  bool getIsForwardDecl() const { return isForwardDecl; }
635  void setIsForwardDecl(bool val) { isForwardDecl = val; }
636
637  void setIntfRefProtocols(int idx, ObjcProtocolDecl *OID) {
638    assert((idx < NumIntfRefProtocols) && "index out of range");
639    IntfRefProtocols[idx] = OID;
640  }
641
642  ObjcInterfaceDecl *getSuperClass() const { return SuperClass; }
643  void setSuperClass(ObjcInterfaceDecl * superCls) { SuperClass = superCls; }
644
645  ObjcCategoryDecl* getListCategories() const { return ListCategories; }
646  void setListCategories(ObjcCategoryDecl *category) {
647         ListCategories = category;
648  }
649
650  static bool classof(const Decl *D) {
651    return D->getKind() == ObjcInterface;
652  }
653  static bool classof(const ObjcInterfaceDecl *D) { return true; }
654};
655
656class ObjcIvarDecl : public FieldDecl {
657public:
658  ObjcIvarDecl(SourceLocation L, IdentifierInfo *Id, QualType T)
659    : FieldDecl(ObjcIvar, L, Id, T) {}
660
661  enum AccessControl {
662    None, Private, Protected, Public, Package
663  };
664  void setAccessControl(AccessControl ac) { DeclAccess = ac; }
665  AccessControl getAccessControl() const { return DeclAccess; }
666
667  // Implement isa/cast/dyncast/etc.
668  static bool classof(const Decl *D) { return D->getKind() == ObjcIvar; }
669  static bool classof(const ObjcIvarDecl *D) { return true; }
670private:
671  AccessControl DeclAccess : 3;
672};
673
674class ObjcClassDecl : public TypeDecl {
675  ObjcInterfaceDecl **ForwardDecls;   // Null if not defined.
676  int NumForwardDecls;               // -1 if not defined.
677public:
678  ObjcClassDecl(SourceLocation L, unsigned nElts)
679    : TypeDecl(ObjcClass, L, 0, 0) {
680    if (nElts) {
681      ForwardDecls = new ObjcInterfaceDecl*[nElts];
682      memset(ForwardDecls, '\0', nElts*sizeof(ObjcInterfaceDecl*));
683    }
684    NumForwardDecls = nElts;
685  }
686  void setInterfaceDecl(int idx, ObjcInterfaceDecl *OID) {
687    assert((idx < NumForwardDecls) && "index out of range");
688    ForwardDecls[idx] = OID;
689  }
690  static bool classof(const Decl *D) {
691    return D->getKind() == ObjcClass;
692  }
693  static bool classof(const ObjcClassDecl *D) { return true; }
694};
695
696/// ObjcMethodDecl - An instance of this class is created to represent an instance
697/// or class method declaration.
698class ObjcMethodDecl : public Decl {
699private:
700  // A unigue name for this method.
701  Selector SelName;
702
703  // Type of this method.
704  QualType MethodDeclType;
705  /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
706  /// parameters of this Method.  This is null if there are no formals.
707  ParmVarDecl **ParamInfo;
708  int NumMethodParams;  // -1 if no parameters
709
710  /// List of attributes for this method declaration.
711  AttributeList *MethodAttrs;
712
713  /// Loc - location of this declaration.
714  SourceLocation Loc;
715
716public:
717  ObjcMethodDecl(SourceLocation L, Selector SelInfo, QualType T,
718		 ParmVarDecl **paramInfo = 0, int numParams=-1,
719		 AttributeList *M = 0, bool isInstance = true,
720                 ImplementationControl impControl = None,
721		 Decl *PrevDecl = 0)
722    : Decl(ObjcMethod, isInstance, impControl),
723      SelName(SelInfo), MethodDeclType(T),
724      ParamInfo(paramInfo), NumMethodParams(numParams),
725      MethodAttrs(M), Loc(L) {}
726#if 0
727  ObjcMethodDecl(Kind DK, SourceLocation L, IdentifierInfo &SelId, QualType T,
728		 ParmVarDecl **paramInfo = 0, int numParams=-1,
729		 AttributeList *M = 0, bool isInstance = true,
730		 Decl *PrevDecl = 0)
731    : Decl(DK), Selector(SelId), MethodDeclType(T),
732      ParamInfo(paramInfo), NumMethodParams(numParams),
733      MethodAttrs(M), IsInstance(isInstance) {}
734#endif
735  virtual ~ObjcMethodDecl();
736  Selector getSelector() const { return SelName; }
737  QualType getMethodType() const { return MethodDeclType; }
738  unsigned getNumMethodParams() const { return NumMethodParams; }
739  ParmVarDecl *getMethodParamDecl(unsigned i) {
740    assert(i < getNumMethodParams() && "Illegal param #");
741    return ParamInfo[i];
742  }
743  void setMethodParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
744
745  AttributeList *getMethodAttrs() const {return MethodAttrs;}
746  SourceLocation getLocation() const { return Loc; }
747
748  // Implement isa/cast/dyncast/etc.
749  static bool classof(const Decl *D) {
750    return D->getKind() == ObjcMethod;
751  }
752  static bool classof(const ObjcMethodDecl *D) { return true; }
753};
754
755class ObjcProtocolDecl : public TypeDecl {
756  /// referenced protocols
757  ObjcProtocolDecl **ReferencedProtocols;  // Null if none
758  int NumReferencedProtocols;  // -1 if none
759
760  /// protocol instance methods
761  ObjcMethodDecl **ProtoInsMethods;  // Null if not defined
762  int NumProtoInsMethods;  // -1 if not defined
763
764  /// protocol class methods
765  ObjcMethodDecl **ProtoClsMethods;  // Null if not defined
766  int NumProtoClsMethods;  // -1 if not defined
767
768  bool isForwardProtoDecl; // declared with @protocol.
769public:
770  ObjcProtocolDecl(SourceLocation L, unsigned numRefProtos,
771                   IdentifierInfo *Id, bool FD = false)
772    : TypeDecl(ObjcProtocol, L, Id, 0),
773      ReferencedProtocols(0), NumReferencedProtocols(-1),
774      ProtoInsMethods(0), NumProtoInsMethods(-1),
775      ProtoClsMethods(0), NumProtoClsMethods(-1),
776      isForwardProtoDecl(FD) {
777        AllocReferencedProtocols(numRefProtos);
778      }
779  void AllocReferencedProtocols(unsigned numRefProtos) {
780    if (numRefProtos) {
781      ReferencedProtocols = new ObjcProtocolDecl*[numRefProtos];
782      memset(ReferencedProtocols, '\0',
783             numRefProtos*sizeof(ObjcProtocolDecl*));
784      NumReferencedProtocols = numRefProtos;
785    }
786  }
787  void ObjcAddProtoMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
788                           ObjcMethodDecl **clsMethods, unsigned numClsMembers);
789
790  void setReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
791    assert((idx < NumReferencedProtocols) && "index out of range");
792    ReferencedProtocols[idx] = OID;
793  }
794
795  ObjcProtocolDecl** getReferencedProtocols() const {
796    return ReferencedProtocols;
797  }
798  int getNumReferencedProtocols() const { return NumReferencedProtocols; }
799
800  ObjcMethodDecl** getInsMethods() const { return ProtoInsMethods; }
801  int getNumInsMethods() const { return NumProtoInsMethods; }
802
803  ObjcMethodDecl** getClsMethods() const { return ProtoClsMethods; }
804  int getNumClsMethods() const { return NumProtoClsMethods; }
805
806  bool getIsForwardProtoDecl() const { return isForwardProtoDecl; }
807  void setIsForwardProtoDecl(bool val) { isForwardProtoDecl = val; }
808
809  static bool classof(const Decl *D) {
810    return D->getKind() == ObjcProtocol;
811  }
812  static bool classof(const ObjcProtocolDecl *D) { return true; }
813};
814
815class ObjcForwardProtocolDecl : public TypeDecl {
816    ObjcProtocolDecl **ForwardProtocolDecls;   // Null if not defined.
817    int NumForwardProtocolDecls;               // -1 if not defined.
818  public:
819    ObjcForwardProtocolDecl(SourceLocation L, unsigned nElts)
820    : TypeDecl(ObjcForwardProtocol, L, 0, 0) {
821      if (nElts) {
822        ForwardProtocolDecls = new ObjcProtocolDecl*[nElts];
823        memset(ForwardProtocolDecls, '\0', nElts*sizeof(ObjcProtocolDecl*));
824        NumForwardProtocolDecls = nElts;
825      }
826    }
827    void setForwardProtocolDecl(int idx, ObjcProtocolDecl *OID) {
828      assert((idx < NumForwardProtocolDecls) && "index out of range");
829      ForwardProtocolDecls[idx] = OID;
830    }
831    static bool classof(const Decl *D) {
832      return D->getKind() == ObjcForwardProtocol;
833    }
834    static bool classof(const ObjcForwardProtocolDecl *D) { return true; }
835};
836
837class ObjcCategoryDecl : public ScopedDecl {
838  /// Interface belonging to this category
839  ObjcInterfaceDecl *ClassInterface;
840
841  /// Category name
842  IdentifierInfo *ObjcCatName;
843
844  /// referenced protocols in this category
845  ObjcProtocolDecl **CatReferencedProtocols;  // Null if none
846  int NumCatReferencedProtocols;  // -1 if none
847
848  /// category instance methods
849  ObjcMethodDecl **CatInsMethods;  // Null if not defined
850  int NumCatInsMethods;  // -1 if not defined
851
852  /// category class methods
853  ObjcMethodDecl **CatClsMethods;  // Null if not defined
854  int NumCatClsMethods;  // -1 if not defined
855
856  /// Next category belonging to this class
857  ObjcCategoryDecl *NextClassCategory;
858
859public:
860  ObjcCategoryDecl(SourceLocation L, unsigned numRefProtocol,
861                   IdentifierInfo *Id)
862    : ScopedDecl(ObjcCategory, L, Id, 0),
863      ClassInterface(0), ObjcCatName(0),
864      CatReferencedProtocols(0), NumCatReferencedProtocols(-1),
865      CatInsMethods(0), NumCatInsMethods(-1),
866      CatClsMethods(0), NumCatClsMethods(-1),
867      NextClassCategory(0) {
868        if (numRefProtocol) {
869          CatReferencedProtocols = new ObjcProtocolDecl*[numRefProtocol];
870          memset(CatReferencedProtocols, '\0',
871                 numRefProtocol*sizeof(ObjcProtocolDecl*));
872          NumCatReferencedProtocols = numRefProtocol;
873        }
874      }
875
876  ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; }
877  void setClassInterface(ObjcInterfaceDecl *IDecl) { ClassInterface = IDecl; }
878
879  void setCatReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
880    assert((idx < NumCatReferencedProtocols) && "index out of range");
881    CatReferencedProtocols[idx] = OID;
882  }
883
884  void ObjcAddCatMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
885                         ObjcMethodDecl **clsMethods, unsigned numClsMembers);
886
887  IdentifierInfo *getCatName() const { return ObjcCatName; }
888  void setCatName(IdentifierInfo *catName) { ObjcCatName = catName; }
889
890  ObjcCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
891  void insertNextClassCategory() {
892    NextClassCategory = ClassInterface->getListCategories();
893    ClassInterface->setListCategories(this);
894  }
895
896  static bool classof(const Decl *D) {
897    return D->getKind() == ObjcCategory;
898  }
899  static bool classof(const ObjcCategoryDecl *D) { return true; }
900};
901
902class ObjcImplementationDecl : public TypeDecl {
903
904  /// Implementation Class's super class.
905  ObjcInterfaceDecl *SuperClass;
906
907  /// Optional Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
908  ObjcIvarDecl **Ivars;   // Null if not specified
909  int NumIvars;   // -1 if not defined.
910
911  /// implemented instance methods
912  ObjcMethodDecl **InsMethods;  // Null if not defined
913  int NumInsMethods;  // -1 if not defined
914
915  /// implemented class methods
916  ObjcMethodDecl **ClsMethods;  // Null if not defined
917  int NumClsMethods;  // -1 if not defined
918
919  public:
920  ObjcImplementationDecl(SourceLocation L, IdentifierInfo *Id,
921                         ObjcInterfaceDecl* superDecl)
922    : TypeDecl(ObjcImplementation, L, Id, 0),
923      SuperClass(superDecl),
924      Ivars(0), NumIvars(-1),
925      InsMethods(0), NumInsMethods(-1), ClsMethods(0), NumClsMethods(-1) {}
926
927  void ObjcAddInstanceVariablesToClassImpl(ObjcIvarDecl **ivars,
928                                           unsigned numIvars);
929
930  void ObjcAddImplMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
931                          ObjcMethodDecl **clsMethods, unsigned numClsMembers);
932
933  ObjcInterfaceDecl *getImplSuperClass() const { return SuperClass; }
934
935  void setImplSuperClass(ObjcInterfaceDecl * superCls)
936         { SuperClass = superCls; }
937
938  ObjcMethodDecl **getInsMethods() const { return InsMethods; }
939  int getNumInsMethods() const { return NumInsMethods; }
940
941  ObjcMethodDecl **getClsMethods() const { return ClsMethods; }
942  int getNumClsMethods() const { return NumClsMethods; }
943
944  static bool classof(const Decl *D) {
945    return D->getKind() == ObjcImplementation;
946  }
947  static bool classof(const ObjcImplementationDecl *D) { return true; }
948};
949
950
951}  // end namespace clang
952#endif
953