]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / contrib / llvm / tools / clang / include / clang / AST / TypeLoc.h
1 //===--- TypeLoc.h - Type Source Info Wrapper -------------------*- 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 the TypeLoc interface and subclasses.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_CLANG_AST_TYPELOC_H
15 #define LLVM_CLANG_AST_TYPELOC_H
16
17 #include "clang/AST/Type.h"
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/TemplateBase.h"
20 #include "clang/Basic/Specifiers.h"
21
22 namespace clang {
23   class ASTContext;
24   class ParmVarDecl;
25   class TypeSourceInfo;
26   class UnqualTypeLoc;
27
28 // Predeclare all the type nodes.
29 #define ABSTRACT_TYPELOC(Class, Base)
30 #define TYPELOC(Class, Base) \
31   class Class##TypeLoc;
32 #include "clang/AST/TypeLocNodes.def"
33
34 /// \brief Base wrapper for a particular "section" of type source info.
35 ///
36 /// A client should use the TypeLoc subclasses through cast/dyn_cast in order to
37 /// get at the actual information.
38 class TypeLoc {
39 protected:
40   // The correctness of this relies on the property that, for Type *Ty,
41   //   QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty
42   const void *Ty;
43   void *Data;
44
45 public:
46   /// The kinds of TypeLocs.  Equivalent to the Type::TypeClass enum,
47   /// except it also defines a Qualified enum that corresponds to the
48   /// QualifiedLoc class.
49   enum TypeLocClass {
50 #define ABSTRACT_TYPE(Class, Base)
51 #define TYPE(Class, Base) \
52     Class = Type::Class,
53 #include "clang/AST/TypeNodes.def"
54     Qualified
55   };
56
57   TypeLoc() : Ty(0), Data(0) { }
58   TypeLoc(QualType ty, void *opaqueData)
59     : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { }
60   TypeLoc(const Type *ty, void *opaqueData)
61     : Ty(ty), Data(opaqueData) { }
62
63   TypeLocClass getTypeLocClass() const {
64     if (getType().hasLocalQualifiers()) return Qualified;
65     return (TypeLocClass) getType()->getTypeClass();
66   }
67
68   bool isNull() const { return !Ty; }
69   operator bool() const { return Ty; }
70
71   /// \brief Returns the size of type source info data block for the given type.
72   static unsigned getFullDataSizeForType(QualType Ty);
73
74   /// \brief Get the type for which this source info wrapper provides
75   /// information.
76   QualType getType() const {
77     return QualType::getFromOpaquePtr(Ty);
78   }
79
80   const Type *getTypePtr() const {
81     return QualType::getFromOpaquePtr(Ty).getTypePtr();
82   }
83
84   /// \brief Get the pointer where source information is stored.
85   void *getOpaqueData() const {
86     return Data;
87   }
88
89   /// \brief Get the begin source location.
90   SourceLocation getBeginLoc() const;
91
92   /// \brief Get the end source location.
93   SourceLocation getEndLoc() const;
94
95   /// \brief Get the full source range.
96   SourceRange getSourceRange() const {
97     return SourceRange(getBeginLoc(), getEndLoc());
98   }
99
100   /// \brief Get the local source range.
101   SourceRange getLocalSourceRange() const {
102     return getLocalSourceRangeImpl(*this);
103   }
104
105   /// \brief Returns the size of the type source info data block.
106   unsigned getFullDataSize() const {
107     return getFullDataSizeForType(getType());
108   }
109
110   /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
111   /// TypeLoc is a PointerLoc and next TypeLoc is for "int".
112   TypeLoc getNextTypeLoc() const {
113     return getNextTypeLocImpl(*this);
114   }
115
116   /// \brief Skips past any qualifiers, if this is qualified.
117   UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header
118
119   TypeLoc IgnoreParens() const {
120     if (isa<ParenTypeLoc>(this))
121       return IgnoreParensImpl(*this);
122     return *this;
123   }
124
125   /// \brief Initializes this to state that every location in this
126   /// type is the given location.
127   ///
128   /// This method exists to provide a simple transition for code that
129   /// relies on location-less types.
130   void initialize(ASTContext &Context, SourceLocation Loc) const {
131     initializeImpl(Context, *this, Loc);
132   }
133
134   /// \brief Initializes this by copying its information from another
135   /// TypeLoc of the same type.
136   void initializeFullCopy(TypeLoc Other) const {
137     assert(getType() == Other.getType());
138     size_t Size = getFullDataSize();
139     memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
140   }
141
142   /// \brief Initializes this by copying its information from another
143   /// TypeLoc of the same type.  The given size must be the full data
144   /// size.
145   void initializeFullCopy(TypeLoc Other, unsigned Size) const {
146     assert(getType() == Other.getType());
147     assert(getFullDataSize() == Size);
148     memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
149   }
150
151   friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) {
152     return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data;
153   }
154
155   friend bool operator!=(const TypeLoc &LHS, const TypeLoc &RHS) {
156     return !(LHS == RHS);
157   }
158
159   static bool classof(const TypeLoc *TL) { return true; }
160
161 private:
162   static void initializeImpl(ASTContext &Context, TypeLoc TL, SourceLocation Loc);
163   static TypeLoc getNextTypeLocImpl(TypeLoc TL);
164   static TypeLoc IgnoreParensImpl(TypeLoc TL);
165   static SourceRange getLocalSourceRangeImpl(TypeLoc TL);
166 };
167
168 /// \brief Return the TypeLoc for a type source info.
169 inline TypeLoc TypeSourceInfo::getTypeLoc() const {
170   return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1)));
171 }
172
173 /// \brief Wrapper of type source information for a type with
174 /// no direct qualifiers.
175 class UnqualTypeLoc : public TypeLoc {
176 public:
177   UnqualTypeLoc() {}
178   UnqualTypeLoc(const Type *Ty, void *Data) : TypeLoc(Ty, Data) {}
179
180   const Type *getTypePtr() const {
181     return reinterpret_cast<const Type*>(Ty);
182   }
183
184   TypeLocClass getTypeLocClass() const {
185     return (TypeLocClass) getTypePtr()->getTypeClass();
186   }
187
188   static bool classof(const TypeLoc *TL) {
189     return !TL->getType().hasLocalQualifiers();
190   }
191   static bool classof(const UnqualTypeLoc *TL) { return true; }
192 };
193
194 /// \brief Wrapper of type source information for a type with
195 /// non-trivial direct qualifiers.
196 ///
197 /// Currently, we intentionally do not provide source location for
198 /// type qualifiers.
199 class QualifiedTypeLoc : public TypeLoc {
200 public:
201   SourceRange getLocalSourceRange() const {
202     return SourceRange();
203   }
204
205   UnqualTypeLoc getUnqualifiedLoc() const {
206     return UnqualTypeLoc(getTypePtr(), Data);
207   }
208
209   /// Initializes the local data of this type source info block to
210   /// provide no information.
211   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
212     // do nothing
213   }
214
215   TypeLoc getNextTypeLoc() const {
216     return getUnqualifiedLoc();
217   }
218
219   /// \brief Returns the size of the type source info data block that is
220   /// specific to this type.
221   unsigned getLocalDataSize() const {
222     // In fact, we don't currently preserve any location information
223     // for qualifiers.
224     return 0;
225   }
226
227   /// \brief Returns the size of the type source info data block.
228   unsigned getFullDataSize() const {
229     return getLocalDataSize() + 
230       getFullDataSizeForType(getType().getLocalUnqualifiedType());
231   }
232
233   static bool classof(const TypeLoc *TL) {
234     return TL->getType().hasLocalQualifiers();
235   }
236   static bool classof(const QualifiedTypeLoc *TL) { return true; }
237 };
238
239 inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const {
240   if (isa<QualifiedTypeLoc>(this))
241     return cast<QualifiedTypeLoc>(this)->getUnqualifiedLoc();
242   return cast<UnqualTypeLoc>(*this);
243 }
244
245 /// A metaprogramming base class for TypeLoc classes which correspond
246 /// to a particular Type subclass.  It is accepted for a single
247 /// TypeLoc class to correspond to multiple Type classes.
248 ///
249 /// \param Base a class from which to derive
250 /// \param Derived the class deriving from this one
251 /// \param TypeClass the concrete Type subclass associated with this
252 ///   location type
253 /// \param LocalData the structure type of local location data for
254 ///   this type
255 ///
256 /// sizeof(LocalData) needs to be a multiple of sizeof(void*) or
257 /// else the world will end.
258 ///
259 /// TypeLocs with non-constant amounts of local data should override
260 /// getExtraLocalDataSize(); getExtraLocalData() will then point to
261 /// this extra memory.
262 ///
263 /// TypeLocs with an inner type should define
264 ///   QualType getInnerType() const
265 /// and getInnerTypeLoc() will then point to this inner type's
266 /// location data.
267 ///
268 /// A word about hierarchies: this template is not designed to be
269 /// derived from multiple times in a hierarchy.  It is also not
270 /// designed to be used for classes where subtypes might provide
271 /// different amounts of source information.  It should be subclassed
272 /// only at the deepest portion of the hierarchy where all children
273 /// have identical source information; if that's an abstract type,
274 /// then further descendents should inherit from
275 /// InheritingConcreteTypeLoc instead.
276 template <class Base, class Derived, class TypeClass, class LocalData>
277 class ConcreteTypeLoc : public Base {
278
279   const Derived *asDerived() const {
280     return static_cast<const Derived*>(this);
281   }
282
283 public:
284   unsigned getLocalDataSize() const {
285     return sizeof(LocalData) + asDerived()->getExtraLocalDataSize();
286   }
287   // Give a default implementation that's useful for leaf types.
288   unsigned getFullDataSize() const {
289     return asDerived()->getLocalDataSize() + getInnerTypeSize();
290   }
291
292   static bool classofType(const Type *Ty) {
293     return TypeClass::classof(Ty);
294   }
295
296   static bool classof(const TypeLoc *TL) {
297     return Derived::classofType(TL->getTypePtr());
298   }
299   static bool classof(const UnqualTypeLoc *TL) {
300     return Derived::classofType(TL->getTypePtr());
301   }
302   static bool classof(const Derived *TL) {
303     return true;
304   }
305
306   TypeLoc getNextTypeLoc() const {
307     return getNextTypeLoc(asDerived()->getInnerType());
308   }
309
310   const TypeClass *getTypePtr() const {
311     return cast<TypeClass>(Base::getTypePtr());
312   }
313
314 protected:
315   unsigned getExtraLocalDataSize() const {
316     return 0;
317   }
318
319   LocalData *getLocalData() const {
320     return static_cast<LocalData*>(Base::Data);
321   }
322
323   /// Gets a pointer past the Info structure; useful for classes with
324   /// local data that can't be captured in the Info (e.g. because it's
325   /// of variable size).
326   void *getExtraLocalData() const {
327     return getLocalData() + 1;
328   }
329   
330   void *getNonLocalData() const {
331     return static_cast<char*>(Base::Data) + asDerived()->getLocalDataSize();
332   }
333
334   struct HasNoInnerType {};
335   HasNoInnerType getInnerType() const { return HasNoInnerType(); }
336
337   TypeLoc getInnerTypeLoc() const {
338     return TypeLoc(asDerived()->getInnerType(), getNonLocalData());
339   }
340
341 private:
342   unsigned getInnerTypeSize() const {
343     return getInnerTypeSize(asDerived()->getInnerType());
344   }
345
346   unsigned getInnerTypeSize(HasNoInnerType _) const {
347     return 0;
348   }
349
350   unsigned getInnerTypeSize(QualType _) const {
351     return getInnerTypeLoc().getFullDataSize();
352   }
353
354   TypeLoc getNextTypeLoc(HasNoInnerType _) const {
355     return TypeLoc();
356   }
357
358   TypeLoc getNextTypeLoc(QualType T) const {
359     return TypeLoc(T, getNonLocalData());
360   }
361 };
362
363 /// A metaprogramming class designed for concrete subtypes of abstract
364 /// types where all subtypes share equivalently-structured source
365 /// information.  See the note on ConcreteTypeLoc.
366 template <class Base, class Derived, class TypeClass>
367 class InheritingConcreteTypeLoc : public Base {
368 public:
369   static bool classofType(const Type *Ty) {
370     return TypeClass::classof(Ty);
371   }
372
373   static bool classof(const TypeLoc *TL) {
374     return Derived::classofType(TL->getTypePtr());
375   }
376   static bool classof(const UnqualTypeLoc *TL) {
377     return Derived::classofType(TL->getTypePtr());
378   }
379   static bool classof(const Derived *TL) {
380     return true;
381   }
382
383   const TypeClass *getTypePtr() const {
384     return cast<TypeClass>(Base::getTypePtr());
385   }
386 };
387
388
389 struct TypeSpecLocInfo {
390   SourceLocation NameLoc;
391 };
392
393 /// \brief A reasonable base class for TypeLocs that correspond to
394 /// types that are written as a type-specifier.
395 class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, 
396                                                TypeSpecTypeLoc,
397                                                Type,
398                                                TypeSpecLocInfo> {
399 public:
400   enum { LocalDataSize = sizeof(TypeSpecLocInfo) };
401
402   SourceLocation getNameLoc() const {
403     return this->getLocalData()->NameLoc;
404   }
405   void setNameLoc(SourceLocation Loc) {
406     this->getLocalData()->NameLoc = Loc;
407   }
408   SourceRange getLocalSourceRange() const {
409     return SourceRange(getNameLoc(), getNameLoc());
410   }
411   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
412     setNameLoc(Loc);
413   }
414
415   static bool classof(const TypeLoc *TL);
416   static bool classof(const TypeSpecTypeLoc *TL) { return true; }
417 };
418
419
420 struct BuiltinLocInfo {
421   SourceLocation BuiltinLoc;
422 };
423
424 /// \brief Wrapper for source info for builtin types.
425 class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
426                                               BuiltinTypeLoc,
427                                               BuiltinType,
428                                               BuiltinLocInfo> {
429 public:
430   enum { LocalDataSize = sizeof(BuiltinLocInfo) };
431
432   SourceLocation getBuiltinLoc() const {
433     return getLocalData()->BuiltinLoc;
434   }
435   void setBuiltinLoc(SourceLocation Loc) {
436     getLocalData()->BuiltinLoc = Loc;
437   }
438
439   SourceLocation getNameLoc() const { return getBuiltinLoc(); }
440
441   WrittenBuiltinSpecs& getWrittenBuiltinSpecs() {
442     return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData()));
443   }
444   const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
445     return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData()));
446   }
447
448   bool needsExtraLocalData() const {
449     BuiltinType::Kind bk = getTypePtr()->getKind();
450     return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128)
451       || (bk >= BuiltinType::Short && bk <= BuiltinType::LongDouble)
452       || bk == BuiltinType::UChar
453       || bk == BuiltinType::SChar;
454   }
455
456   unsigned getExtraLocalDataSize() const {
457     return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0;
458   }
459
460   SourceRange getLocalSourceRange() const {
461     return SourceRange(getBuiltinLoc(), getBuiltinLoc());
462   }
463
464   TypeSpecifierSign getWrittenSignSpec() const {
465     if (needsExtraLocalData())
466       return static_cast<TypeSpecifierSign>(getWrittenBuiltinSpecs().Sign);
467     else
468       return TSS_unspecified;
469   }
470   bool hasWrittenSignSpec() const {
471     return getWrittenSignSpec() != TSS_unspecified;
472   }
473   void setWrittenSignSpec(TypeSpecifierSign written) {
474     if (needsExtraLocalData())
475       getWrittenBuiltinSpecs().Sign = written;
476   }
477
478   TypeSpecifierWidth getWrittenWidthSpec() const {
479     if (needsExtraLocalData())
480       return static_cast<TypeSpecifierWidth>(getWrittenBuiltinSpecs().Width);
481     else
482       return TSW_unspecified;
483   }
484   bool hasWrittenWidthSpec() const {
485     return getWrittenWidthSpec() != TSW_unspecified;
486   }
487   void setWrittenWidthSpec(TypeSpecifierWidth written) {
488     if (needsExtraLocalData())
489       getWrittenBuiltinSpecs().Width = written;
490   }
491
492   TypeSpecifierType getWrittenTypeSpec() const;
493   bool hasWrittenTypeSpec() const {
494     return getWrittenTypeSpec() != TST_unspecified;
495   }
496   void setWrittenTypeSpec(TypeSpecifierType written) {
497     if (needsExtraLocalData())
498       getWrittenBuiltinSpecs().Type = written;
499   }
500
501   bool hasModeAttr() const {
502     if (needsExtraLocalData())
503       return getWrittenBuiltinSpecs().ModeAttr;
504     else
505       return false;
506   }
507   void setModeAttr(bool written) {
508     if (needsExtraLocalData())
509       getWrittenBuiltinSpecs().ModeAttr = written;
510   }
511
512   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
513     setBuiltinLoc(Loc);
514     if (needsExtraLocalData()) {
515       WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs();
516       wbs.Sign = TSS_unspecified;
517       wbs.Width = TSW_unspecified;
518       wbs.Type = TST_unspecified;
519       wbs.ModeAttr = false;
520     }
521   }
522 };
523
524
525 /// \brief Wrapper for source info for typedefs.
526 class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
527                                                         TypedefTypeLoc,
528                                                         TypedefType> {
529 public:
530   TypedefNameDecl *getTypedefNameDecl() const {
531     return getTypePtr()->getDecl();
532   }
533 };
534
535 /// \brief Wrapper for source info for injected class names of class
536 /// templates.
537 class InjectedClassNameTypeLoc :
538     public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
539                                      InjectedClassNameTypeLoc,
540                                      InjectedClassNameType> {
541 };
542
543 /// \brief Wrapper for source info for unresolved typename using decls.
544 class UnresolvedUsingTypeLoc :
545     public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
546                                      UnresolvedUsingTypeLoc,
547                                      UnresolvedUsingType> {
548 public:
549   UnresolvedUsingTypenameDecl *getDecl() const {
550     return getTypePtr()->getDecl();
551   }
552 };
553
554 /// \brief Wrapper for source info for tag types.  Note that this only
555 /// records source info for the name itself; a type written 'struct foo'
556 /// should be represented as an ElaboratedTypeLoc.  We currently
557 /// only do that when C++ is enabled because of the expense of
558 /// creating an ElaboratedType node for so many type references in C.
559 class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
560                                                     TagTypeLoc,
561                                                     TagType> {
562 public:
563   TagDecl *getDecl() const { return getTypePtr()->getDecl(); }
564 };
565
566 /// \brief Wrapper for source info for record types.
567 class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
568                                                        RecordTypeLoc,
569                                                        RecordType> {
570 public:
571   RecordDecl *getDecl() const { return getTypePtr()->getDecl(); }
572 };
573
574 /// \brief Wrapper for source info for enum types.
575 class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
576                                                      EnumTypeLoc,
577                                                      EnumType> {
578 public:
579   EnumDecl *getDecl() const { return getTypePtr()->getDecl(); }
580 };
581
582 /// \brief Wrapper for template type parameters.
583 class TemplateTypeParmTypeLoc :
584     public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
585                                      TemplateTypeParmTypeLoc,
586                                      TemplateTypeParmType> {
587 public:
588   TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); }
589 };
590
591 /// \brief Wrapper for substituted template type parameters.
592 class SubstTemplateTypeParmTypeLoc :
593     public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
594                                      SubstTemplateTypeParmTypeLoc,
595                                      SubstTemplateTypeParmType> {
596 };
597
598   /// \brief Wrapper for substituted template type parameters.
599 class SubstTemplateTypeParmPackTypeLoc :
600     public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
601                                      SubstTemplateTypeParmPackTypeLoc,
602                                      SubstTemplateTypeParmPackType> {
603 };
604
605 struct AttributedLocInfo {
606   union {
607     Expr *ExprOperand;
608
609     /// A raw SourceLocation.
610     unsigned EnumOperandLoc;
611   };
612
613   SourceRange OperandParens;
614
615   SourceLocation AttrLoc;
616 };
617
618 /// \brief Type source information for an attributed type.
619 class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
620                                                  AttributedTypeLoc,
621                                                  AttributedType,
622                                                  AttributedLocInfo> {
623 public:
624   AttributedType::Kind getAttrKind() const {
625     return getTypePtr()->getAttrKind();
626   }
627
628   bool hasAttrExprOperand() const {
629     return (getAttrKind() >= AttributedType::FirstExprOperandKind &&
630             getAttrKind() <= AttributedType::LastExprOperandKind);
631   }
632
633   bool hasAttrEnumOperand() const {
634     return (getAttrKind() >= AttributedType::FirstEnumOperandKind &&
635             getAttrKind() <= AttributedType::LastEnumOperandKind);
636   }
637
638   bool hasAttrOperand() const {
639     return hasAttrExprOperand() || hasAttrEnumOperand();
640   }
641
642   /// The modified type, which is generally canonically different from
643   /// the attribute type.
644   ///    int main(int, char**) __attribute__((noreturn))
645   ///    ~~~     ~~~~~~~~~~~~~
646   TypeLoc getModifiedLoc() const {
647     return getInnerTypeLoc();
648   }
649
650   /// The location of the attribute name, i.e.
651   ///    __attribute__((regparm(1000)))
652   ///                   ^~~~~~~
653   SourceLocation getAttrNameLoc() const {
654     return getLocalData()->AttrLoc;
655   }
656   void setAttrNameLoc(SourceLocation loc) {
657     getLocalData()->AttrLoc = loc;
658   }
659
660   /// The attribute's expression operand, if it has one.
661   ///    void *cur_thread __attribute__((address_space(21)))
662   ///                                                  ^~
663   Expr *getAttrExprOperand() const {
664     assert(hasAttrExprOperand());
665     return getLocalData()->ExprOperand;
666   }
667   void setAttrExprOperand(Expr *e) {
668     assert(hasAttrExprOperand());
669     getLocalData()->ExprOperand = e;
670   }
671
672   /// The location of the attribute's enumerated operand, if it has one.
673   ///    void * __attribute__((objc_gc(weak)))
674   ///                                  ^~~~
675   SourceLocation getAttrEnumOperandLoc() const {
676     assert(hasAttrEnumOperand());
677     return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc);
678   }
679   void setAttrEnumOperandLoc(SourceLocation loc) {
680     assert(hasAttrEnumOperand());
681     getLocalData()->EnumOperandLoc = loc.getRawEncoding();
682   }
683
684   /// The location of the parentheses around the operand, if there is
685   /// an operand.
686   ///    void * __attribute__((objc_gc(weak)))
687   ///                                 ^    ^
688   SourceRange getAttrOperandParensRange() const {
689     assert(hasAttrOperand());
690     return getLocalData()->OperandParens;
691   }
692   void setAttrOperandParensRange(SourceRange range) {
693     assert(hasAttrOperand());
694     getLocalData()->OperandParens = range;
695   }
696
697   SourceRange getLocalSourceRange() const {
698     // Note that this does *not* include the range of the attribute
699     // enclosure, e.g.:
700     //    __attribute__((foo(bar)))
701     //    ^~~~~~~~~~~~~~~        ~~
702     // or
703     //    [[foo(bar)]]
704     //    ^~        ~~
705     // That enclosure doesn't necessarily belong to a single attribute
706     // anyway.
707     SourceRange range(getAttrNameLoc());
708     if (hasAttrOperand())
709       range.setEnd(getAttrOperandParensRange().getEnd());
710     return range;
711   }
712
713   void initializeLocal(ASTContext &Context, SourceLocation loc) {
714     setAttrNameLoc(loc);
715     if (hasAttrExprOperand()) {
716       setAttrOperandParensRange(SourceRange(loc));
717       setAttrExprOperand(0);
718     } else if (hasAttrEnumOperand()) {
719       setAttrOperandParensRange(SourceRange(loc));
720       setAttrEnumOperandLoc(loc);
721     }
722   }
723
724   QualType getInnerType() const {
725     return getTypePtr()->getModifiedType();
726   }
727 };
728
729
730 struct ObjCProtocolListLocInfo {
731   SourceLocation LAngleLoc;
732   SourceLocation RAngleLoc;
733   bool HasBaseTypeAsWritten;
734 };
735
736 // A helper class for defining ObjC TypeLocs that can qualified with
737 // protocols.
738 //
739 // TypeClass basically has to be either ObjCInterfaceType or
740 // ObjCObjectPointerType.
741 class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
742                                                  ObjCObjectTypeLoc,
743                                                  ObjCObjectType,
744                                                  ObjCProtocolListLocInfo> {
745   // SourceLocations are stored after Info, one for each Protocol.
746   SourceLocation *getProtocolLocArray() const {
747     return (SourceLocation*) this->getExtraLocalData();
748   }
749
750 public:
751   SourceLocation getLAngleLoc() const {
752     return this->getLocalData()->LAngleLoc;
753   }
754   void setLAngleLoc(SourceLocation Loc) {
755     this->getLocalData()->LAngleLoc = Loc;
756   }
757
758   SourceLocation getRAngleLoc() const {
759     return this->getLocalData()->RAngleLoc;
760   }
761   void setRAngleLoc(SourceLocation Loc) {
762     this->getLocalData()->RAngleLoc = Loc;
763   }
764
765   unsigned getNumProtocols() const {
766     return this->getTypePtr()->getNumProtocols();
767   }
768
769   SourceLocation getProtocolLoc(unsigned i) const {
770     assert(i < getNumProtocols() && "Index is out of bounds!");
771     return getProtocolLocArray()[i];
772   }
773   void setProtocolLoc(unsigned i, SourceLocation Loc) {
774     assert(i < getNumProtocols() && "Index is out of bounds!");
775     getProtocolLocArray()[i] = Loc;
776   }
777
778   ObjCProtocolDecl *getProtocol(unsigned i) const {
779     assert(i < getNumProtocols() && "Index is out of bounds!");
780     return *(this->getTypePtr()->qual_begin() + i);
781   }
782   
783   bool hasBaseTypeAsWritten() const {
784     return getLocalData()->HasBaseTypeAsWritten;
785   }
786
787   void setHasBaseTypeAsWritten(bool HasBaseType) {
788     getLocalData()->HasBaseTypeAsWritten = HasBaseType;
789   }
790
791   TypeLoc getBaseLoc() const {
792     return getInnerTypeLoc();
793   }
794
795   SourceRange getLocalSourceRange() const {
796     return SourceRange(getLAngleLoc(), getRAngleLoc());
797   }
798
799   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
800     setHasBaseTypeAsWritten(true);
801     setLAngleLoc(Loc);
802     setRAngleLoc(Loc);
803     for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
804       setProtocolLoc(i, Loc);
805   }
806
807   unsigned getExtraLocalDataSize() const {
808     return this->getNumProtocols() * sizeof(SourceLocation);
809   }
810
811   QualType getInnerType() const {
812     return getTypePtr()->getBaseType();
813   }
814 };
815
816
817 struct ObjCInterfaceLocInfo {
818   SourceLocation NameLoc;
819 };
820
821 /// \brief Wrapper for source info for ObjC interfaces.
822 class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<ObjCObjectTypeLoc,
823                                                     ObjCInterfaceTypeLoc,
824                                                     ObjCInterfaceType,
825                                                     ObjCInterfaceLocInfo> {
826 public:
827   ObjCInterfaceDecl *getIFaceDecl() const {
828     return getTypePtr()->getDecl();
829   }
830
831   SourceLocation getNameLoc() const {
832     return getLocalData()->NameLoc;
833   }
834
835   void setNameLoc(SourceLocation Loc) {
836     getLocalData()->NameLoc = Loc;
837   }
838
839   SourceRange getLocalSourceRange() const {
840     return SourceRange(getNameLoc());
841   }
842
843   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
844     setNameLoc(Loc);
845   }
846 };
847
848 struct ParenLocInfo {
849   SourceLocation LParenLoc;
850   SourceLocation RParenLoc;
851 };
852
853 class ParenTypeLoc
854   : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType,
855                            ParenLocInfo> {
856 public:
857   SourceLocation getLParenLoc() const {
858     return this->getLocalData()->LParenLoc;
859   }
860   SourceLocation getRParenLoc() const {
861     return this->getLocalData()->RParenLoc;
862   }
863   void setLParenLoc(SourceLocation Loc) {
864     this->getLocalData()->LParenLoc = Loc;
865   }
866   void setRParenLoc(SourceLocation Loc) {
867     this->getLocalData()->RParenLoc = Loc;
868   }
869
870   SourceRange getLocalSourceRange() const {
871     return SourceRange(getLParenLoc(), getRParenLoc());
872   }
873
874   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
875     setLParenLoc(Loc);
876     setRParenLoc(Loc);
877   }
878
879   TypeLoc getInnerLoc() const {
880     return getInnerTypeLoc();
881   }
882
883   QualType getInnerType() const {
884     return this->getTypePtr()->getInnerType();
885   }
886 };
887
888
889 struct PointerLikeLocInfo {
890   SourceLocation StarLoc;
891 };
892
893 /// A base class for 
894 template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo>
895 class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived,
896                                                   TypeClass, LocalData> {
897 public:  
898   SourceLocation getSigilLoc() const {
899     return this->getLocalData()->StarLoc;
900   }
901   void setSigilLoc(SourceLocation Loc) {
902     this->getLocalData()->StarLoc = Loc;
903   }
904
905   TypeLoc getPointeeLoc() const {
906     return this->getInnerTypeLoc();
907   }
908
909   SourceRange getLocalSourceRange() const {
910     return SourceRange(getSigilLoc(), getSigilLoc());
911   }
912
913   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
914     setSigilLoc(Loc);
915   }
916
917   QualType getInnerType() const {
918     return this->getTypePtr()->getPointeeType();
919   }
920 };
921
922
923 /// \brief Wrapper for source info for pointers.
924 class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc,
925                                                  PointerType> {
926 public:
927   SourceLocation getStarLoc() const {
928     return getSigilLoc();
929   }
930   void setStarLoc(SourceLocation Loc) {
931     setSigilLoc(Loc);
932   }
933 };
934
935
936 /// \brief Wrapper for source info for block pointers.
937 class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
938                                                       BlockPointerType> {
939 public:
940   SourceLocation getCaretLoc() const {
941     return getSigilLoc();
942   }
943   void setCaretLoc(SourceLocation Loc) {
944     setSigilLoc(Loc);
945   }
946 };
947
948 struct MemberPointerLocInfo : public PointerLikeLocInfo {
949   TypeSourceInfo *ClassTInfo;
950 };
951
952 /// \brief Wrapper for source info for member pointers.
953 class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
954                                                        MemberPointerType,
955                                                        MemberPointerLocInfo> {
956 public:
957   SourceLocation getStarLoc() const {
958     return getSigilLoc();
959   }
960   void setStarLoc(SourceLocation Loc) {
961     setSigilLoc(Loc);
962   }
963
964   const Type *getClass() const {
965     return getTypePtr()->getClass();
966   }
967   TypeSourceInfo *getClassTInfo() const {
968     return getLocalData()->ClassTInfo;
969   }
970   void setClassTInfo(TypeSourceInfo* TI) {
971     getLocalData()->ClassTInfo = TI;
972   }
973
974   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
975     setSigilLoc(Loc);
976     setClassTInfo(0);
977   }
978
979   SourceRange getLocalSourceRange() const {
980     if (TypeSourceInfo *TI = getClassTInfo())
981       return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc());
982     else
983       return SourceRange(getStarLoc());
984   }
985 };
986
987 /// Wraps an ObjCPointerType with source location information.
988 class ObjCObjectPointerTypeLoc :
989     public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc,
990                               ObjCObjectPointerType> {
991 public:
992   SourceLocation getStarLoc() const {
993     return getSigilLoc();
994   }
995
996   void setStarLoc(SourceLocation Loc) {
997     setSigilLoc(Loc);
998   }
999 };
1000
1001
1002 class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc,
1003                                                    ReferenceType> {
1004 public:
1005   QualType getInnerType() const {
1006     return getTypePtr()->getPointeeTypeAsWritten();
1007   }
1008 };
1009
1010 class LValueReferenceTypeLoc :
1011     public InheritingConcreteTypeLoc<ReferenceTypeLoc,
1012                                      LValueReferenceTypeLoc,
1013                                      LValueReferenceType> {
1014 public:
1015   SourceLocation getAmpLoc() const {
1016     return getSigilLoc();
1017   }
1018   void setAmpLoc(SourceLocation Loc) {
1019     setSigilLoc(Loc);
1020   }
1021 };
1022
1023 class RValueReferenceTypeLoc :
1024     public InheritingConcreteTypeLoc<ReferenceTypeLoc,
1025                                      RValueReferenceTypeLoc,
1026                                      RValueReferenceType> {
1027 public:
1028   SourceLocation getAmpAmpLoc() const {
1029     return getSigilLoc();
1030   }
1031   void setAmpAmpLoc(SourceLocation Loc) {
1032     setSigilLoc(Loc);
1033   }
1034 };
1035
1036
1037 struct FunctionLocInfo {
1038   SourceLocation LocalRangeBegin;
1039   SourceLocation LocalRangeEnd;
1040   bool TrailingReturn;
1041 };
1042
1043 /// \brief Wrapper for source info for functions.
1044 class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1045                                                FunctionTypeLoc,
1046                                                FunctionType,
1047                                                FunctionLocInfo> {
1048 public:
1049   SourceLocation getLocalRangeBegin() const {
1050     return getLocalData()->LocalRangeBegin;
1051   }
1052   void setLocalRangeBegin(SourceLocation L) {
1053     getLocalData()->LocalRangeBegin = L;
1054   }
1055
1056   SourceLocation getLocalRangeEnd() const {
1057     return getLocalData()->LocalRangeEnd;
1058   }
1059   void setLocalRangeEnd(SourceLocation L) {
1060     getLocalData()->LocalRangeEnd = L;
1061   }
1062
1063   bool getTrailingReturn() const {
1064     return getLocalData()->TrailingReturn;
1065   }
1066   void setTrailingReturn(bool Trailing) {
1067     getLocalData()->TrailingReturn = Trailing;
1068   }
1069
1070   // ParmVarDecls* are stored after Info, one for each argument.
1071   ParmVarDecl **getParmArray() const {
1072     return (ParmVarDecl**) getExtraLocalData();
1073   }
1074
1075   unsigned getNumArgs() const {
1076     if (isa<FunctionNoProtoType>(getTypePtr()))
1077       return 0;
1078     return cast<FunctionProtoType>(getTypePtr())->getNumArgs();
1079   }
1080   ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; }
1081   void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; }
1082
1083   TypeLoc getResultLoc() const {
1084     return getInnerTypeLoc();
1085   }
1086
1087   SourceRange getLocalSourceRange() const {
1088     return SourceRange(getLocalRangeBegin(), getLocalRangeEnd());
1089   }
1090
1091   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1092     setLocalRangeBegin(Loc);
1093     setLocalRangeEnd(Loc);
1094     setTrailingReturn(false);
1095     for (unsigned i = 0, e = getNumArgs(); i != e; ++i)
1096       setArg(i, NULL);
1097   }
1098
1099   /// \brief Returns the size of the type source info data block that is
1100   /// specific to this type.
1101   unsigned getExtraLocalDataSize() const {
1102     return getNumArgs() * sizeof(ParmVarDecl*);
1103   }
1104
1105   QualType getInnerType() const { return getTypePtr()->getResultType(); }
1106 };
1107
1108 class FunctionProtoTypeLoc :
1109     public InheritingConcreteTypeLoc<FunctionTypeLoc,
1110                                      FunctionProtoTypeLoc,
1111                                      FunctionProtoType> {
1112 };
1113
1114 class FunctionNoProtoTypeLoc :
1115     public InheritingConcreteTypeLoc<FunctionTypeLoc,
1116                                      FunctionNoProtoTypeLoc,
1117                                      FunctionNoProtoType> {
1118 };
1119
1120
1121 struct ArrayLocInfo {
1122   SourceLocation LBracketLoc, RBracketLoc;
1123   Expr *Size;
1124 };
1125
1126 /// \brief Wrapper for source info for arrays.
1127 class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1128                                             ArrayTypeLoc,
1129                                             ArrayType,
1130                                             ArrayLocInfo> {
1131 public:
1132   SourceLocation getLBracketLoc() const {
1133     return getLocalData()->LBracketLoc;
1134   }
1135   void setLBracketLoc(SourceLocation Loc) {
1136     getLocalData()->LBracketLoc = Loc;
1137   }
1138
1139   SourceLocation getRBracketLoc() const {
1140     return getLocalData()->RBracketLoc;
1141   }
1142   void setRBracketLoc(SourceLocation Loc) {
1143     getLocalData()->RBracketLoc = Loc;
1144   }
1145
1146   SourceRange getBracketsRange() const {
1147     return SourceRange(getLBracketLoc(), getRBracketLoc());
1148   }
1149
1150   Expr *getSizeExpr() const {
1151     return getLocalData()->Size;
1152   }
1153   void setSizeExpr(Expr *Size) {
1154     getLocalData()->Size = Size;
1155   }
1156
1157   TypeLoc getElementLoc() const {
1158     return getInnerTypeLoc();
1159   }
1160
1161   SourceRange getLocalSourceRange() const {
1162     return SourceRange(getLBracketLoc(), getRBracketLoc());
1163   }
1164
1165   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1166     setLBracketLoc(Loc);
1167     setRBracketLoc(Loc);
1168     setSizeExpr(NULL);
1169   }
1170
1171   QualType getInnerType() const { return getTypePtr()->getElementType(); }
1172 };
1173
1174 class ConstantArrayTypeLoc :
1175     public InheritingConcreteTypeLoc<ArrayTypeLoc,
1176                                      ConstantArrayTypeLoc,
1177                                      ConstantArrayType> {
1178 };
1179
1180 class IncompleteArrayTypeLoc :
1181     public InheritingConcreteTypeLoc<ArrayTypeLoc,
1182                                      IncompleteArrayTypeLoc,
1183                                      IncompleteArrayType> {
1184 };
1185
1186 class DependentSizedArrayTypeLoc :
1187     public InheritingConcreteTypeLoc<ArrayTypeLoc,
1188                                      DependentSizedArrayTypeLoc,
1189                                      DependentSizedArrayType> {
1190
1191 };
1192
1193 class VariableArrayTypeLoc :
1194     public InheritingConcreteTypeLoc<ArrayTypeLoc,
1195                                      VariableArrayTypeLoc,
1196                                      VariableArrayType> {
1197 };
1198
1199
1200 // Location information for a TemplateName.  Rudimentary for now.
1201 struct TemplateNameLocInfo {
1202   SourceLocation NameLoc;
1203 };
1204
1205 struct TemplateSpecializationLocInfo : TemplateNameLocInfo {
1206   SourceLocation LAngleLoc;
1207   SourceLocation RAngleLoc;
1208 };
1209
1210 class TemplateSpecializationTypeLoc :
1211     public ConcreteTypeLoc<UnqualTypeLoc,
1212                            TemplateSpecializationTypeLoc,
1213                            TemplateSpecializationType,
1214                            TemplateSpecializationLocInfo> {
1215 public:
1216   SourceLocation getLAngleLoc() const {
1217     return getLocalData()->LAngleLoc;
1218   }
1219   void setLAngleLoc(SourceLocation Loc) {
1220     getLocalData()->LAngleLoc = Loc;
1221   }
1222
1223   SourceLocation getRAngleLoc() const {
1224     return getLocalData()->RAngleLoc;
1225   }
1226   void setRAngleLoc(SourceLocation Loc) {
1227     getLocalData()->RAngleLoc = Loc;
1228   }
1229
1230   unsigned getNumArgs() const {
1231     return getTypePtr()->getNumArgs();
1232   }
1233   void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
1234     getArgInfos()[i] = AI;
1235   }
1236   TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
1237     return getArgInfos()[i];
1238   }
1239
1240   TemplateArgumentLoc getArgLoc(unsigned i) const {
1241     return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
1242   }
1243
1244   SourceLocation getTemplateNameLoc() const {
1245     return getLocalData()->NameLoc;
1246   }
1247   void setTemplateNameLoc(SourceLocation Loc) {
1248     getLocalData()->NameLoc = Loc;
1249   }
1250
1251   /// \brief - Copy the location information from the given info.
1252   void copy(TemplateSpecializationTypeLoc Loc) {
1253     unsigned size = getFullDataSize();
1254     assert(size == Loc.getFullDataSize());
1255
1256     // We're potentially copying Expr references here.  We don't
1257     // bother retaining them because TypeSourceInfos live forever, so
1258     // as long as the Expr was retained when originally written into
1259     // the TypeLoc, we're okay.
1260     memcpy(Data, Loc.Data, size);
1261   }
1262
1263   SourceRange getLocalSourceRange() const {
1264     return SourceRange(getTemplateNameLoc(), getRAngleLoc());
1265   }
1266
1267   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1268     setLAngleLoc(Loc);
1269     setRAngleLoc(Loc);
1270     setTemplateNameLoc(Loc);
1271     initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(),
1272                       getArgInfos(), Loc);
1273   }
1274
1275   static void initializeArgLocs(ASTContext &Context, unsigned NumArgs,
1276                                 const TemplateArgument *Args,
1277                                 TemplateArgumentLocInfo *ArgInfos,
1278                                 SourceLocation Loc);
1279
1280   unsigned getExtraLocalDataSize() const {
1281     return getNumArgs() * sizeof(TemplateArgumentLocInfo);
1282   }
1283
1284 private:
1285   TemplateArgumentLocInfo *getArgInfos() const {
1286     return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
1287   }
1288 };
1289
1290 //===----------------------------------------------------------------------===//
1291 //
1292 //  All of these need proper implementations.
1293 //
1294 //===----------------------------------------------------------------------===//
1295
1296 // FIXME: size expression and attribute locations (or keyword if we
1297 // ever fully support altivec syntax).
1298 class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1299                                                        VectorTypeLoc,
1300                                                        VectorType> {
1301 };
1302
1303 // FIXME: size expression and attribute locations.
1304 class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc,
1305                                                           ExtVectorTypeLoc,
1306                                                           ExtVectorType> {
1307 };
1308
1309 // FIXME: attribute locations.
1310 // For some reason, this isn't a subtype of VectorType.
1311 class DependentSizedExtVectorTypeLoc :
1312     public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1313                                      DependentSizedExtVectorTypeLoc,
1314                                      DependentSizedExtVectorType> {
1315 };
1316
1317 // FIXME: location of the '_Complex' keyword.
1318 class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1319                                                         ComplexTypeLoc,
1320                                                         ComplexType> {
1321 };
1322
1323 struct TypeofLocInfo {
1324   SourceLocation TypeofLoc;
1325   SourceLocation LParenLoc;
1326   SourceLocation RParenLoc;
1327 };
1328
1329 struct TypeOfExprTypeLocInfo : public TypeofLocInfo {
1330 };
1331
1332 struct TypeOfTypeLocInfo : public TypeofLocInfo {
1333   TypeSourceInfo* UnderlyingTInfo;
1334 };
1335
1336 template <class Derived, class TypeClass, class LocalData = TypeofLocInfo>
1337 class TypeofLikeTypeLoc
1338   : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> {
1339 public:
1340   SourceLocation getTypeofLoc() const {
1341     return this->getLocalData()->TypeofLoc;
1342   }
1343   void setTypeofLoc(SourceLocation Loc) {
1344     this->getLocalData()->TypeofLoc = Loc;
1345   }
1346
1347   SourceLocation getLParenLoc() const {
1348     return this->getLocalData()->LParenLoc;
1349   }
1350   void setLParenLoc(SourceLocation Loc) {
1351     this->getLocalData()->LParenLoc = Loc;
1352   }
1353
1354   SourceLocation getRParenLoc() const {
1355     return this->getLocalData()->RParenLoc;
1356   }
1357   void setRParenLoc(SourceLocation Loc) {
1358     this->getLocalData()->RParenLoc = Loc;
1359   }
1360
1361   SourceRange getParensRange() const {
1362     return SourceRange(getLParenLoc(), getRParenLoc());
1363   }
1364   void setParensRange(SourceRange range) {
1365       setLParenLoc(range.getBegin());
1366       setRParenLoc(range.getEnd());
1367   }
1368
1369   SourceRange getLocalSourceRange() const {
1370     return SourceRange(getTypeofLoc(), getRParenLoc());
1371   }
1372
1373   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1374     setTypeofLoc(Loc);
1375     setLParenLoc(Loc);
1376     setRParenLoc(Loc);
1377   }
1378 };
1379
1380 class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc,
1381                                                    TypeOfExprType,
1382                                                    TypeOfExprTypeLocInfo> {
1383 public:
1384   Expr* getUnderlyingExpr() const {
1385     return getTypePtr()->getUnderlyingExpr();
1386   }
1387   // Reimplemented to account for GNU/C++ extension
1388   //     typeof unary-expression
1389   // where there are no parentheses.
1390   SourceRange getLocalSourceRange() const;
1391 };
1392
1393 class TypeOfTypeLoc
1394   : public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> {
1395 public:
1396   QualType getUnderlyingType() const {
1397     return this->getTypePtr()->getUnderlyingType();
1398   }
1399   TypeSourceInfo* getUnderlyingTInfo() const {
1400     return this->getLocalData()->UnderlyingTInfo;
1401   }
1402   void setUnderlyingTInfo(TypeSourceInfo* TI) const {
1403     this->getLocalData()->UnderlyingTInfo = TI;
1404   }
1405 };
1406
1407 // FIXME: location of the 'decltype' and parens.
1408 class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1409                                                          DecltypeTypeLoc,
1410                                                          DecltypeType> {
1411 };
1412
1413 struct UnaryTransformTypeLocInfo {
1414   // FIXME: While there's only one unary transform right now, future ones may
1415   // need different representations
1416   SourceLocation KWLoc, LParenLoc, RParenLoc;
1417   TypeSourceInfo *UnderlyingTInfo;
1418 };
1419
1420 class UnaryTransformTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1421                                                     UnaryTransformTypeLoc,
1422                                                     UnaryTransformType,
1423                                                     UnaryTransformTypeLocInfo> {
1424 public:
1425   SourceLocation getKWLoc() const { return getLocalData()->KWLoc; }
1426   void setKWLoc(SourceLocation Loc) { getLocalData()->KWLoc = Loc; }
1427
1428   SourceLocation getLParenLoc() const { return getLocalData()->LParenLoc; }
1429   void setLParenLoc(SourceLocation Loc) { getLocalData()->LParenLoc = Loc; }
1430
1431   SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; }
1432   void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; }
1433
1434   TypeSourceInfo* getUnderlyingTInfo() const {
1435     return getLocalData()->UnderlyingTInfo;
1436   }
1437   void setUnderlyingTInfo(TypeSourceInfo *TInfo) {
1438     getLocalData()->UnderlyingTInfo = TInfo;
1439   }
1440
1441   SourceRange getLocalSourceRange() const {
1442     return SourceRange(getKWLoc(), getRParenLoc());
1443   }
1444
1445   SourceRange getParensRange() const {
1446     return SourceRange(getLParenLoc(), getRParenLoc());
1447   }
1448   void setParensRange(SourceRange Range) {
1449     setLParenLoc(Range.getBegin());
1450     setRParenLoc(Range.getEnd());
1451   }
1452
1453   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1454     setKWLoc(Loc);
1455     setRParenLoc(Loc);
1456     setLParenLoc(Loc);
1457   }
1458 };
1459
1460 class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1461                                                         AutoTypeLoc,
1462                                                         AutoType> {
1463 };
1464
1465 struct ElaboratedLocInfo {
1466   SourceLocation KeywordLoc;
1467   
1468   /// \brief Opaque data pointer used to reconstruct a nested-name-specifier
1469   /// from 
1470   void *QualifierData;
1471 };
1472
1473 class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1474                                                  ElaboratedTypeLoc,
1475                                                  ElaboratedType,
1476                                                  ElaboratedLocInfo> {
1477 public:
1478   SourceLocation getKeywordLoc() const {
1479     return this->getLocalData()->KeywordLoc;
1480   }
1481   void setKeywordLoc(SourceLocation Loc) {
1482     this->getLocalData()->KeywordLoc = Loc;
1483   }
1484
1485   NestedNameSpecifierLoc getQualifierLoc() const {
1486     return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), 
1487                                   getLocalData()->QualifierData);
1488   }
1489  
1490   void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
1491     assert(QualifierLoc.getNestedNameSpecifier() 
1492                                             == getTypePtr()->getQualifier() &&
1493            "Inconsistent nested-name-specifier pointer");
1494     getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
1495   }
1496
1497   SourceRange getLocalSourceRange() const {
1498     if (getKeywordLoc().isValid())
1499       if (getQualifierLoc())
1500         return SourceRange(getKeywordLoc(), getQualifierLoc().getEndLoc());
1501       else
1502         return SourceRange(getKeywordLoc());
1503     else
1504       return getQualifierLoc().getSourceRange();
1505   }
1506
1507   void initializeLocal(ASTContext &Context, SourceLocation Loc);
1508
1509   TypeLoc getNamedTypeLoc() const {
1510     return getInnerTypeLoc();
1511   }
1512
1513   QualType getInnerType() const {
1514     return getTypePtr()->getNamedType();
1515   }
1516
1517   void copy(ElaboratedTypeLoc Loc) {
1518     unsigned size = getFullDataSize();
1519     assert(size == Loc.getFullDataSize());
1520     memcpy(Data, Loc.Data, size);
1521   }
1522 };
1523
1524 // This is exactly the structure of an ElaboratedTypeLoc whose inner
1525 // type is some sort of TypeDeclTypeLoc.
1526 struct DependentNameLocInfo : ElaboratedLocInfo {
1527   SourceLocation NameLoc;
1528   
1529   /// \brief Data associated with the nested-name-specifier location.
1530   void *QualifierData;
1531 };
1532
1533 class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1534                                                     DependentNameTypeLoc,
1535                                                     DependentNameType,
1536                                                     DependentNameLocInfo> {
1537 public:
1538   SourceLocation getKeywordLoc() const {
1539     return this->getLocalData()->KeywordLoc;
1540   }
1541   void setKeywordLoc(SourceLocation Loc) {
1542     this->getLocalData()->KeywordLoc = Loc;
1543   }
1544
1545   NestedNameSpecifierLoc getQualifierLoc() const {
1546     return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), 
1547                                   getLocalData()->QualifierData);
1548   }
1549       
1550   void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
1551     assert(QualifierLoc.getNestedNameSpecifier() 
1552                                             == getTypePtr()->getQualifier() &&
1553            "Inconsistent nested-name-specifier pointer");
1554     getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
1555   }
1556                                                       
1557   SourceLocation getNameLoc() const {
1558     return this->getLocalData()->NameLoc;
1559   }
1560   void setNameLoc(SourceLocation Loc) {
1561     this->getLocalData()->NameLoc = Loc;
1562   }
1563
1564   SourceRange getLocalSourceRange() const {
1565     if (getKeywordLoc().isValid())
1566       return SourceRange(getKeywordLoc(), getNameLoc());
1567     else
1568       return SourceRange(getQualifierLoc().getBeginLoc(), getNameLoc());
1569   }
1570
1571   void copy(DependentNameTypeLoc Loc) {
1572     unsigned size = getFullDataSize();
1573     assert(size == Loc.getFullDataSize());
1574     memcpy(Data, Loc.Data, size);
1575   }
1576
1577   void initializeLocal(ASTContext &Context, SourceLocation Loc);
1578 };
1579
1580 struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo {
1581   SourceLocation KeywordLoc;
1582   SourceLocation LAngleLoc;
1583   SourceLocation RAngleLoc;
1584   // followed by a TemplateArgumentLocInfo[]
1585 };
1586
1587 class DependentTemplateSpecializationTypeLoc :
1588     public ConcreteTypeLoc<UnqualTypeLoc,
1589                            DependentTemplateSpecializationTypeLoc,
1590                            DependentTemplateSpecializationType,
1591                            DependentTemplateSpecializationLocInfo> {
1592 public:
1593   SourceLocation getKeywordLoc() const {
1594     return this->getLocalData()->KeywordLoc;
1595   }
1596   void setKeywordLoc(SourceLocation Loc) {
1597     this->getLocalData()->KeywordLoc = Loc;
1598   }
1599
1600   NestedNameSpecifierLoc getQualifierLoc() const {
1601     if (!getLocalData()->QualifierData)
1602       return NestedNameSpecifierLoc();
1603     
1604     return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), 
1605                                   getLocalData()->QualifierData);
1606   }
1607    
1608   void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
1609     if (!QualifierLoc) {
1610       // Even if we have a nested-name-specifier in the dependent 
1611       // template specialization type, we won't record the nested-name-specifier
1612       // location information when this type-source location information is
1613       // part of a nested-name-specifier.
1614       getLocalData()->QualifierData = 0;
1615       return;
1616     }
1617     
1618     assert(QualifierLoc.getNestedNameSpecifier() 
1619                                         == getTypePtr()->getQualifier() &&
1620            "Inconsistent nested-name-specifier pointer");
1621     getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
1622   }
1623
1624   SourceLocation getNameLoc() const {
1625     return this->getLocalData()->NameLoc;
1626   }
1627   void setNameLoc(SourceLocation Loc) {
1628     this->getLocalData()->NameLoc = Loc;
1629   }
1630
1631   SourceLocation getLAngleLoc() const {
1632     return this->getLocalData()->LAngleLoc;
1633   }
1634   void setLAngleLoc(SourceLocation Loc) {
1635     this->getLocalData()->LAngleLoc = Loc;
1636   }
1637
1638   SourceLocation getRAngleLoc() const {
1639     return this->getLocalData()->RAngleLoc;
1640   }
1641   void setRAngleLoc(SourceLocation Loc) {
1642     this->getLocalData()->RAngleLoc = Loc;
1643   }
1644
1645   unsigned getNumArgs() const {
1646     return getTypePtr()->getNumArgs();
1647   }
1648
1649   void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
1650     getArgInfos()[i] = AI;
1651   }
1652   TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
1653     return getArgInfos()[i];
1654   }
1655
1656   TemplateArgumentLoc getArgLoc(unsigned i) const {
1657     return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
1658   }
1659
1660   SourceRange getLocalSourceRange() const {
1661     if (getKeywordLoc().isValid())
1662       return SourceRange(getKeywordLoc(), getRAngleLoc());
1663     else if (getQualifierLoc())
1664       return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc());
1665     else
1666       return SourceRange(getNameLoc(), getRAngleLoc());
1667   }
1668
1669   void copy(DependentTemplateSpecializationTypeLoc Loc) {
1670     unsigned size = getFullDataSize();
1671     assert(size == Loc.getFullDataSize());
1672     memcpy(Data, Loc.Data, size);
1673   }
1674
1675   void initializeLocal(ASTContext &Context, SourceLocation Loc);
1676
1677   unsigned getExtraLocalDataSize() const {
1678     return getNumArgs() * sizeof(TemplateArgumentLocInfo);
1679   }
1680
1681 private:
1682   TemplateArgumentLocInfo *getArgInfos() const {
1683     return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
1684   }
1685 };
1686
1687
1688 struct PackExpansionTypeLocInfo {
1689   SourceLocation EllipsisLoc;
1690 };
1691
1692 class PackExpansionTypeLoc
1693   : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc, 
1694                            PackExpansionType, PackExpansionTypeLocInfo> {
1695 public:
1696   SourceLocation getEllipsisLoc() const {
1697     return this->getLocalData()->EllipsisLoc;
1698   }
1699
1700   void setEllipsisLoc(SourceLocation Loc) {
1701     this->getLocalData()->EllipsisLoc = Loc;
1702   }
1703
1704   SourceRange getLocalSourceRange() const {
1705     return SourceRange(getEllipsisLoc(), getEllipsisLoc());
1706   }
1707
1708   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1709     setEllipsisLoc(Loc);
1710   }
1711
1712   TypeLoc getPatternLoc() const {
1713     return getInnerTypeLoc();
1714   }
1715
1716   QualType getInnerType() const {
1717     return this->getTypePtr()->getPattern();
1718   }
1719 };
1720
1721 }
1722
1723 #endif