]> granicus.if.org Git - clang/blob - include/clang/Parse/DeclSpec.h
move type attribute processing into the creatively named ProcessTypeAttributes method.
[clang] / include / clang / Parse / DeclSpec.h
1 //===--- SemaDeclSpec.h - Declaration Specifier Semantic Analys -*- C++ -*-===//
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 defines interfaces used for Declaration Specifiers and Declarators.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_CLANG_PARSE_SEMADECLSPEC_H
15 #define LLVM_CLANG_PARSE_SEMADECLSPEC_H
16
17 #include "clang/Basic/Diagnostic.h"
18 #include "clang/Parse/Action.h"
19 #include "clang/Parse/AttributeList.h"
20 #include "llvm/ADT/SmallVector.h"
21
22 namespace clang {
23   struct LangOptions;
24   class IdentifierInfo;
25   
26 /// DeclSpec - This class captures information about "declaration specifiers",
27 /// which encompasses storage-class-specifiers, type-specifiers,
28 /// type-qualifiers, and function-specifiers.
29 class DeclSpec {
30 public:
31   SourceRange Range;
32   const SourceRange &getSourceRange() const { return Range; }
33   
34   // storage-class-specifier
35   enum SCS {
36     SCS_unspecified,
37     SCS_typedef,
38     SCS_extern,
39     SCS_static,
40     SCS_auto,
41     SCS_register,
42     SCS_private_extern
43   };
44   
45   // type-specifier
46   enum TSW {
47     TSW_unspecified,
48     TSW_short,
49     TSW_long,
50     TSW_longlong
51   };
52   
53   enum TSC {
54     TSC_unspecified,
55     TSC_imaginary,
56     TSC_complex
57   };
58   
59   enum TSS {
60     TSS_unspecified,
61     TSS_signed,
62     TSS_unsigned
63   };
64   
65   enum TST {
66     TST_unspecified,
67     TST_void,
68     TST_char,
69     TST_int,
70     TST_float,
71     TST_double,
72     TST_bool,         // _Bool
73     TST_decimal32,    // _Decimal32
74     TST_decimal64,    // _Decimal64
75     TST_decimal128,   // _Decimal128
76     TST_enum,
77     TST_union,
78     TST_struct,
79     TST_typedef,
80     TST_typeofType,
81     TST_typeofExpr
82   };
83   
84   // type-qualifiers
85   enum TQ {   // NOTE: These flags must be kept in sync with QualType::TQ.
86     TQ_unspecified = 0,
87     TQ_const       = 1,
88     TQ_restrict    = 2,
89     TQ_volatile    = 4
90   };
91
92   /// ParsedSpecifiers - Flags to query which specifiers were applied.  This is
93   /// returned by getParsedSpecifiers.
94   enum ParsedSpecifiers {
95     PQ_None                  = 0,
96     PQ_StorageClassSpecifier = 1,
97     PQ_TypeSpecifier         = 2,
98     PQ_TypeQualifier         = 4,
99     PQ_FunctionSpecifier     = 8
100   };
101   
102 private:
103     
104   // storage-class-specifier
105   /*SCS*/unsigned StorageClassSpec : 3;
106   bool SCS_thread_specified : 1;
107
108   // type-specifier
109   /*TSW*/unsigned TypeSpecWidth : 2;
110   /*TSC*/unsigned TypeSpecComplex : 2;
111   /*TSS*/unsigned TypeSpecSign : 2;
112   /*TST*/unsigned TypeSpecType : 4;
113   
114   // type-qualifiers
115   unsigned TypeQualifiers : 3;  // Bitwise OR of TQ.
116   
117   // function-specifier
118   bool FS_inline_specified : 1;
119   
120   /// TypeRep - This contains action-specific information about a specific TST.
121   /// For example, for a typedef or struct, it might contain the declaration for
122   /// these.
123   void *TypeRep;  
124   
125   // attributes.
126   AttributeList *AttrList;
127   
128   // List of protocol qualifiers for objective-c classes.
129   llvm::SmallVector<Action::DeclTy *, 8> *ProtocolQualifiers;
130   
131   // SourceLocation info.  These are null if the item wasn't specified or if
132   // the setting was synthesized.
133   SourceLocation StorageClassSpecLoc, SCS_threadLoc;
134   SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc;
135   SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc;
136   SourceLocation FS_inlineLoc;
137   
138   bool BadSpecifier(TST T, const char *&PrevSpec);
139   bool BadSpecifier(TQ T, const char *&PrevSpec);
140   bool BadSpecifier(TSS T, const char *&PrevSpec);
141   bool BadSpecifier(TSC T, const char *&PrevSpec);
142   bool BadSpecifier(TSW T, const char *&PrevSpec);
143   bool BadSpecifier(SCS T, const char *&PrevSpec);
144 public:  
145   
146   DeclSpec()
147     : StorageClassSpec(SCS_unspecified),
148       SCS_thread_specified(false),
149       TypeSpecWidth(TSW_unspecified),
150       TypeSpecComplex(TSC_unspecified),
151       TypeSpecSign(TSS_unspecified),
152       TypeSpecType(TST_unspecified),
153       TypeQualifiers(TSS_unspecified),
154       FS_inline_specified(false),
155       TypeRep(0),
156       AttrList(0),
157       ProtocolQualifiers(0) {
158   }
159   ~DeclSpec() {
160     delete AttrList;
161     delete ProtocolQualifiers;
162   }
163   // storage-class-specifier
164   SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
165   bool isThreadSpecified() const { return SCS_thread_specified; }
166   
167   SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; }
168   SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; }
169   
170   void ClearStorageClassSpecs() {
171     StorageClassSpec     = DeclSpec::SCS_unspecified;
172     SCS_thread_specified = false;
173     StorageClassSpecLoc  = SourceLocation();
174     SCS_threadLoc        = SourceLocation();
175   }
176   
177   // type-specifier
178   TSW getTypeSpecWidth() const { return (TSW)TypeSpecWidth; }
179   TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; }
180   TSS getTypeSpecSign() const { return (TSS)TypeSpecSign; }
181   TST getTypeSpecType() const { return (TST)TypeSpecType; }
182   void *getTypeRep() const { return TypeRep; }
183   
184   SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; }
185   SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; }
186   SourceLocation getTypeSpecSignLoc() const { return TSSLoc; }
187   SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; }
188   
189   /// getSpecifierName - Turn a type-specifier-type into a string like "_Bool"
190   /// or "union".
191   static const char *getSpecifierName(DeclSpec::TST T);
192   static const char *getSpecifierName(DeclSpec::SCS S);
193   
194   // type-qualifiers
195
196   /// getTypeQualifiers - Return a set of TQs.
197   unsigned getTypeQualifiers() const { return TypeQualifiers; }
198   SourceLocation getConstSpecLoc() const { return TQ_constLoc; }
199   SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
200   SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
201
202   
203   // function-specifier
204   bool isInlineSpecified() const { return FS_inline_specified; }
205   SourceLocation getInlineSpecLoc() const { return FS_inlineLoc; }
206   void ClearFunctionSpecs() {
207     FS_inline_specified = false;
208     FS_inlineLoc = SourceLocation();
209   }
210   
211   /// hasTypeSpecifier - Return true if any type-specifier has been found.
212   bool hasTypeSpecifier() const {
213     return getTypeSpecType() != DeclSpec::TST_unspecified ||
214            getTypeSpecWidth() != DeclSpec::TSW_unspecified ||
215            getTypeSpecComplex() != DeclSpec::TSC_unspecified ||
216            getTypeSpecSign() != DeclSpec::TSS_unspecified;
217   }
218   
219   
220   /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
221   /// DeclSpec includes.
222   ///
223   unsigned getParsedSpecifiers() const;
224   
225   /// These methods set the specified attribute of the DeclSpec, but return true
226   /// and ignore the request if invalid (e.g. "extern" then "auto" is
227   /// specified).  The name of the previous specifier is returned in prevspec.
228   bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec);
229   bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec);
230   bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec);
231   bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec);
232   bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec);
233   bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
234                        void *TypeRep = 0);
235   
236   bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
237                    const LangOptions &Lang);
238   
239   bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec);
240   
241   /// AddAttributes - contatenates two attribute lists. 
242   /// The GCC attribute syntax allows for the following:
243   ///
244   /// short __attribute__(( unused, deprecated )) 
245   /// int __attribute__(( may_alias, aligned(16) )) var;
246   ///
247   /// This declares 4 attributes using 2 lists. The following syntax is
248   /// also allowed and equivalent to the previous declaration.
249   ///
250   /// short __attribute__((unused)) __attribute__((deprecated)) 
251   /// int __attribute__((may_alias)) __attribute__((aligned(16))) var;
252   /// 
253   void AddAttributes(AttributeList *alist) {
254     if (!alist)
255       return; // we parsed __attribute__(()) or had a syntax error
256       
257     if (AttrList) 
258       alist->addAttributeList(AttrList); 
259     AttrList = alist;
260   }
261   void SetAttributes(AttributeList *AL) { AttrList = AL; }
262   AttributeList *getAttributes() const { return AttrList; }
263   void clearAttributes() { AttrList = 0; }
264   
265   llvm::SmallVector<Action::DeclTy *, 8> *getProtocolQualifiers() const {
266     return ProtocolQualifiers;
267   }
268   void setProtocolQualifiers(llvm::SmallVector<Action::DeclTy *, 8> *protos) {
269     ProtocolQualifiers = protos;
270   }
271   unsigned NumProtocolQualifiers() const {
272     return ProtocolQualifiers ?  ProtocolQualifiers->size() : 0;
273   }
274   /// Finish - This does final analysis of the declspec, issuing diagnostics for
275   /// things like "_Imaginary" (lacking an FP type).  After calling this method,
276   /// DeclSpec is guaranteed self-consistent, even if an error occurred.
277   void Finish(Diagnostic &D, SourceManager& SrcMgr, const LangOptions &Lang);
278   
279 private:
280   void Diag(Diagnostic &D, SourceLocation Loc, SourceManager& SrcMgr, 
281             unsigned DiagID) {
282     D.Report(FullSourceLoc(Loc,SrcMgr), DiagID);
283   }
284   
285   void Diag(Diagnostic &D, SourceLocation Loc, SourceManager& SrcMgr,
286             unsigned DiagID, const std::string &info) {
287     D.Report(FullSourceLoc(Loc,SrcMgr), DiagID, &info, 1);
288   }
289 };
290
291 /// ObjCDeclSpec - This class captures information about 
292 /// "declaration specifiers" specific to objective-c
293 class ObjCDeclSpec {
294 public:
295   /// ObjCDeclQualifier - Qualifier used on types in method declarations
296   enum ObjCDeclQualifier {
297     DQ_None = 0x0,
298     DQ_In = 0x1,
299     DQ_Inout = 0x2,
300     DQ_Out = 0x4,
301     DQ_Bycopy = 0x8,
302     DQ_Byref = 0x10,
303     DQ_Oneway = 0x20
304   };
305   
306   /// PropertyAttributeKind - list of property attributes.
307   enum ObjCPropertyAttributeKind { DQ_PR_noattr = 0x0, 
308     DQ_PR_readonly = 0x01, 
309     DQ_PR_getter = 0x02, 
310     DQ_PR_assign = 0x04, 
311     DQ_PR_readwrite = 0x08, 
312     DQ_PR_retain = 0x10,
313     DQ_PR_copy = 0x20, 
314     DQ_PR_nonatomic = 0x40,
315     DQ_PR_setter = 0x80
316   };
317   
318   
319   ObjCDeclSpec() : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr) 
320   {}
321   ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; }
322   void setObjCDeclQualifier(ObjCDeclQualifier DQVal) 
323     { objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); }
324   
325   const ObjCPropertyAttributeKind getPropertyAttributes() const 
326     { return PropertyAttributes; }
327   void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) { 
328     PropertyAttributes = 
329       (ObjCPropertyAttributeKind) (PropertyAttributes | PRVal);
330   }
331   
332   const IdentifierInfo *getGetterName() const { return GetterName; }
333   IdentifierInfo *getGetterName() { return GetterName; }
334   void setGetterName(IdentifierInfo *name) { GetterName = name; }
335   
336   const IdentifierInfo *getSetterName() const { return SetterName; }
337   IdentifierInfo *getSetterName() { return SetterName; }
338   void setSetterName(IdentifierInfo *name) { SetterName = name; }
339 private:
340   // FIXME: These two are unrelated and mutially exclusive. So perhaps 
341   // we can put them in a union to reflect their mutual exclusiveness
342   // (space saving is negligible).
343   ObjCDeclQualifier objcDeclQualifier : 6;
344   
345   ObjCPropertyAttributeKind PropertyAttributes : 8;
346   IdentifierInfo *GetterName;    // getter name of NULL if no getter
347   IdentifierInfo *SetterName;    // setter name of NULL if no setter
348 };
349   
350 /// DeclaratorChunk - One instance of this struct is used for each type in a
351 /// declarator that is parsed.
352 ///
353 /// This is intended to be a small value object.
354 struct DeclaratorChunk {
355   enum {
356     Pointer, Reference, Array, Function
357   } Kind;
358   
359   /// Loc - The place where this type was defined.
360   SourceLocation Loc;
361   
362   struct PointerTypeInfo {
363     /// The type qualifiers: const/volatile/restrict.
364     unsigned TypeQuals : 3;
365     void destroy() {}
366   };
367
368   struct ReferenceTypeInfo {
369     /// The type qualifier: restrict. [GNU] C++ extension
370     bool HasRestrict;
371     void destroy() {}
372   };
373
374   struct ArrayTypeInfo {
375     /// The type qualifiers for the array: const/volatile/restrict.
376     unsigned TypeQuals : 3;
377     
378     /// True if this dimension included the 'static' keyword.
379     bool hasStatic : 1;
380     
381     /// True if this dimension was [*].  In this case, NumElts is null.
382     bool isStar : 1;
383     
384     /// This is the size of the array, or null if [] or [*] was specified.
385     /// Since the parser is multi-purpose, and we don't want to impose a root
386     /// expression class on all clients, NumElts is untyped.
387     Action::ExprTy *NumElts;
388     void destroy() {}
389   };
390   
391   /// ParamInfo - An array of paraminfo objects is allocated whenever a function
392   /// declarator is parsed.  There are two interesting styles of arguments here:
393   /// K&R-style identifier lists and parameter type lists.  K&R-style identifier
394   /// lists will have information about the identifier, but no type information.
395   /// Parameter type lists will have type info (if the actions module provides
396   /// it), but may have null identifier info: e.g. for 'void foo(int X, int)'.
397   struct ParamInfo {
398     IdentifierInfo *Ident;
399     SourceLocation IdentLoc;
400     Action::TypeTy *TypeInfo;
401     bool InvalidType;
402     AttributeList *AttrList;
403     ParamInfo() {}
404     ParamInfo(IdentifierInfo *ident, SourceLocation iloc, Action::TypeTy *typ,
405               bool flag = false, AttributeList *AL = 0)
406       : Ident(ident), IdentLoc(iloc), TypeInfo(typ), InvalidType(flag),
407         AttrList(AL) {}
408   };
409   
410   struct FunctionTypeInfo {
411     /// hasPrototype - This is true if the function had at least one typed
412     /// argument.  If the function is () or (a,b,c), then it has no prototype,
413     /// and is treated as a K&R-style function.
414     bool hasPrototype : 1;
415     
416     /// isVariadic - If this function has a prototype, and if that proto ends
417     /// with ',...)', this is true.
418     bool isVariadic : 1;
419
420     /// NumArgs - This is the number of formal arguments provided for the
421     /// declarator.
422     unsigned NumArgs;
423
424     /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that
425     /// describe the arguments for this function declarator.  This is null if
426     /// there are no arguments specified.
427     ParamInfo *ArgInfo;
428     
429     void destroy() {
430       delete[] ArgInfo;
431     }
432   };
433   
434   union {
435     PointerTypeInfo   Ptr;
436     ReferenceTypeInfo Ref;
437     ArrayTypeInfo     Arr;
438     FunctionTypeInfo  Fun;
439   };
440   
441   
442   /// getPointer - Return a DeclaratorChunk for a pointer.
443   ///
444   static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc) {
445     DeclaratorChunk I;
446     I.Kind          = Pointer;
447     I.Loc           = Loc;
448     I.Ptr.TypeQuals = TypeQuals;
449     return I;
450   }
451   
452   /// getReference - Return a DeclaratorChunk for a reference.
453   ///
454   static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc) {
455     DeclaratorChunk I;
456     I.Kind            = Reference;
457     I.Loc             = Loc;
458     I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0;
459     return I;
460   }
461   
462   /// getArray - Return a DeclaratorChunk for an array.
463   ///
464   static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic,
465                                   bool isStar, void *NumElts,
466                                   SourceLocation Loc) {
467     DeclaratorChunk I;
468     I.Kind          = Array;
469     I.Loc           = Loc;
470     I.Arr.TypeQuals = TypeQuals;
471     I.Arr.hasStatic = isStatic;
472     I.Arr.isStar    = isStar;
473     I.Arr.NumElts   = NumElts;
474     return I;
475   }
476   
477   /// getFunction - Return a DeclaratorChunk for a function.
478   static DeclaratorChunk getFunction(bool hasProto, bool isVariadic,
479                                      ParamInfo *ArgInfo, unsigned NumArgs,
480                                      SourceLocation Loc) {
481     DeclaratorChunk I;
482     I.Kind             = Function;
483     I.Loc              = Loc;
484     I.Fun.hasPrototype = hasProto;
485     I.Fun.isVariadic   = isVariadic;
486     I.Fun.NumArgs      = NumArgs;
487     I.Fun.ArgInfo      = 0;
488     
489     // new[] an argument array if needed.
490     if (NumArgs) {
491       I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs];
492       memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
493     }
494     return I;
495   }
496 };
497
498
499 /// Declarator - Information about one declarator, including the parsed type
500 /// information and the identifier.  When the declarator is fully formed, this
501 /// is turned into the appropriate Decl object.
502 ///
503 /// Declarators come in two types: normal declarators and abstract declarators.
504 /// Abstract declarators are used when parsing types, and don't have an
505 /// identifier.  Normal declarators do have ID's.
506 ///
507 /// Instances of this class should be a transient object that lives on the
508 /// stack, not objects that are allocated in large quantities on the heap.
509 class Declarator {
510   DeclSpec &DS;
511   IdentifierInfo *Identifier;
512   SourceLocation IdentifierLoc;
513   
514 public:
515   enum TheContext {
516     FileContext,         // File scope declaration.
517     PrototypeContext,    // Within a function prototype.
518     KNRTypeListContext,  // K&R type definition list for formals.
519     TypeNameContext,     // Abstract declarator for types.
520     MemberContext,       // Struct/Union field.
521     BlockContext,        // Declaration within a block in a function.
522     ForContext           // Declaration within first part of a for loop.
523   };
524 private:
525   /// Context - Where we are parsing this declarator.
526   ///
527   TheContext Context;
528   
529   /// DeclTypeInfo - This holds each type that the declarator includes as it is
530   /// parsed.  This is pushed from the identifier out, which means that element
531   /// #0 will be the most closely bound to the identifier, and
532   /// DeclTypeInfo.back() will be the least closely bound.
533   llvm::SmallVector<DeclaratorChunk, 8> DeclTypeInfo;
534
535   // InvalidType - Set by Sema::GetTypeForDeclarator().
536   bool InvalidType;
537
538   // attributes.
539   AttributeList *AttrList;
540 public:
541   Declarator(DeclSpec &ds, TheContext C)
542     : DS(ds), Identifier(0), Context(C), InvalidType(false), AttrList(0) {
543   }
544   
545   ~Declarator() {
546     clear();
547   }
548
549   /// getDeclSpec - Return the declaration-specifier that this declarator was
550   /// declared with.
551   DeclSpec &getDeclSpec() const { return DS; }
552   
553   TheContext getContext() const { return Context; }
554   
555   // getSourceRange - FIXME: This should be implemented.
556   const SourceRange getSourceRange() const { return SourceRange(); }
557   
558   /// clear - Reset the contents of this Declarator.
559   void clear() {
560     Identifier = 0;
561     IdentifierLoc = SourceLocation();
562     
563     for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) {
564       if (DeclTypeInfo[i].Kind == DeclaratorChunk::Function)
565         DeclTypeInfo[i].Fun.destroy();
566       else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Pointer)
567         DeclTypeInfo[i].Ptr.destroy();
568       else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Reference)
569         DeclTypeInfo[i].Ref.destroy();
570       else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Array)
571         DeclTypeInfo[i].Arr.destroy();
572       else
573         assert(0 && "Unknown decl type!");
574     }
575     DeclTypeInfo.clear();
576     delete AttrList;
577     AttrList = 0;
578   }
579   
580   /// mayOmitIdentifier - Return true if the identifier is either optional or
581   /// not allowed.  This is true for typenames and prototypes.
582   bool mayOmitIdentifier() const {
583     return Context == TypeNameContext || Context == PrototypeContext;
584   }
585
586   /// mayHaveIdentifier - Return true if the identifier is either optional or
587   /// required.  This is true for normal declarators and prototypes, but not
588   /// typenames.
589   bool mayHaveIdentifier() const {
590     return Context != TypeNameContext;
591   }
592   
593   /// isPastIdentifier - Return true if we have parsed beyond the point where
594   /// the
595   bool isPastIdentifier() const { return IdentifierLoc.isValid(); }
596   
597   IdentifierInfo *getIdentifier() const { return Identifier; }
598   SourceLocation getIdentifierLoc() const { return IdentifierLoc; }
599   
600   void SetIdentifier(IdentifierInfo *ID, SourceLocation Loc) {
601     Identifier = ID;
602     IdentifierLoc = Loc;
603   }
604   
605   void AddTypeInfo(const DeclaratorChunk &TI) {
606     DeclTypeInfo.push_back(TI);
607   }
608   
609   /// getNumTypeObjects() - Return the number of types applied to this
610   /// declarator.
611   unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); }
612   
613   /// Return the specified TypeInfo from this declarator.  TypeInfo #0 is
614   /// closest to the identifier.
615   const DeclaratorChunk &getTypeObject(unsigned i) const {
616     assert(i < DeclTypeInfo.size() && "Invalid type chunk");
617     return DeclTypeInfo[i];
618   }
619   DeclaratorChunk &getTypeObject(unsigned i) {
620     assert(i < DeclTypeInfo.size() && "Invalid type chunk");
621     return DeclTypeInfo[i];
622   }
623   
624   /// isFunctionDeclarator - Once this declarator is fully parsed and formed,
625   /// this method returns true if the identifier is a function declarator.
626   bool isFunctionDeclarator() const {
627     return !DeclTypeInfo.empty() &&
628            DeclTypeInfo[0].Kind == DeclaratorChunk::Function;
629   }
630   
631   /// AddAttributes - simply adds the attribute list to the Declarator.
632   /// Unlike AddAttributes on DeclSpec, this routine should never have to
633   /// concatenate two lists. The following syntax adds 3 attributes to "var":
634   ///
635   /// short int var __attribute__((aligned(16),common,deprecated));
636   ///
637   void AddAttributes(AttributeList *alist) { 
638     if (!alist)
639       return; // we parsed __attribute__(()) or had a syntax error
640     assert((AttrList == 0) && "Declarator already has an attribute list");
641     AttrList = alist;
642   }
643   AttributeList *getAttributes() const { return AttrList; }
644   
645   void setInvalidType(bool flag) { InvalidType = flag; }
646   bool getInvalidType() { return InvalidType; }
647 };
648
649 } // end namespace clang
650
651 #endif