]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.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 public:
542   CXXRecordDecl *getDecl() const {
543     return getTypePtr()->getDecl();
544   }
545 };
546
547 /// \brief Wrapper for source info for unresolved typename using decls.
548 class UnresolvedUsingTypeLoc :
549     public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
550                                      UnresolvedUsingTypeLoc,
551                                      UnresolvedUsingType> {
552 public:
553   UnresolvedUsingTypenameDecl *getDecl() const {
554     return getTypePtr()->getDecl();
555   }
556 };
557
558 /// \brief Wrapper for source info for tag types.  Note that this only
559 /// records source info for the name itself; a type written 'struct foo'
560 /// should be represented as an ElaboratedTypeLoc.  We currently
561 /// only do that when C++ is enabled because of the expense of
562 /// creating an ElaboratedType node for so many type references in C.
563 class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
564                                                     TagTypeLoc,
565                                                     TagType> {
566 public:
567   TagDecl *getDecl() const { return getTypePtr()->getDecl(); }
568
569   /// \brief True if the tag was defined in this type specifier. 
570   bool isDefinition() const {
571     return getDecl()->isCompleteDefinition() &&
572          (getNameLoc().isInvalid() || getNameLoc() == getDecl()->getLocation());
573   }
574 };
575
576 /// \brief Wrapper for source info for record types.
577 class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
578                                                        RecordTypeLoc,
579                                                        RecordType> {
580 public:
581   RecordDecl *getDecl() const { return getTypePtr()->getDecl(); }
582 };
583
584 /// \brief Wrapper for source info for enum types.
585 class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
586                                                      EnumTypeLoc,
587                                                      EnumType> {
588 public:
589   EnumDecl *getDecl() const { return getTypePtr()->getDecl(); }
590 };
591
592 /// \brief Wrapper for template type parameters.
593 class TemplateTypeParmTypeLoc :
594     public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
595                                      TemplateTypeParmTypeLoc,
596                                      TemplateTypeParmType> {
597 public:
598   TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); }
599 };
600
601 /// \brief Wrapper for substituted template type parameters.
602 class SubstTemplateTypeParmTypeLoc :
603     public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
604                                      SubstTemplateTypeParmTypeLoc,
605                                      SubstTemplateTypeParmType> {
606 };
607
608   /// \brief Wrapper for substituted template type parameters.
609 class SubstTemplateTypeParmPackTypeLoc :
610     public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
611                                      SubstTemplateTypeParmPackTypeLoc,
612                                      SubstTemplateTypeParmPackType> {
613 };
614
615 struct AttributedLocInfo {
616   union {
617     Expr *ExprOperand;
618
619     /// A raw SourceLocation.
620     unsigned EnumOperandLoc;
621   };
622
623   SourceRange OperandParens;
624
625   SourceLocation AttrLoc;
626 };
627
628 /// \brief Type source information for an attributed type.
629 class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
630                                                  AttributedTypeLoc,
631                                                  AttributedType,
632                                                  AttributedLocInfo> {
633 public:
634   AttributedType::Kind getAttrKind() const {
635     return getTypePtr()->getAttrKind();
636   }
637
638   bool hasAttrExprOperand() const {
639     return (getAttrKind() >= AttributedType::FirstExprOperandKind &&
640             getAttrKind() <= AttributedType::LastExprOperandKind);
641   }
642
643   bool hasAttrEnumOperand() const {
644     return (getAttrKind() >= AttributedType::FirstEnumOperandKind &&
645             getAttrKind() <= AttributedType::LastEnumOperandKind);
646   }
647
648   bool hasAttrOperand() const {
649     return hasAttrExprOperand() || hasAttrEnumOperand();
650   }
651
652   /// The modified type, which is generally canonically different from
653   /// the attribute type.
654   ///    int main(int, char**) __attribute__((noreturn))
655   ///    ~~~     ~~~~~~~~~~~~~
656   TypeLoc getModifiedLoc() const {
657     return getInnerTypeLoc();
658   }
659
660   /// The location of the attribute name, i.e.
661   ///    __attribute__((regparm(1000)))
662   ///                   ^~~~~~~
663   SourceLocation getAttrNameLoc() const {
664     return getLocalData()->AttrLoc;
665   }
666   void setAttrNameLoc(SourceLocation loc) {
667     getLocalData()->AttrLoc = loc;
668   }
669
670   /// The attribute's expression operand, if it has one.
671   ///    void *cur_thread __attribute__((address_space(21)))
672   ///                                                  ^~
673   Expr *getAttrExprOperand() const {
674     assert(hasAttrExprOperand());
675     return getLocalData()->ExprOperand;
676   }
677   void setAttrExprOperand(Expr *e) {
678     assert(hasAttrExprOperand());
679     getLocalData()->ExprOperand = e;
680   }
681
682   /// The location of the attribute's enumerated operand, if it has one.
683   ///    void * __attribute__((objc_gc(weak)))
684   ///                                  ^~~~
685   SourceLocation getAttrEnumOperandLoc() const {
686     assert(hasAttrEnumOperand());
687     return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc);
688   }
689   void setAttrEnumOperandLoc(SourceLocation loc) {
690     assert(hasAttrEnumOperand());
691     getLocalData()->EnumOperandLoc = loc.getRawEncoding();
692   }
693
694   /// The location of the parentheses around the operand, if there is
695   /// an operand.
696   ///    void * __attribute__((objc_gc(weak)))
697   ///                                 ^    ^
698   SourceRange getAttrOperandParensRange() const {
699     assert(hasAttrOperand());
700     return getLocalData()->OperandParens;
701   }
702   void setAttrOperandParensRange(SourceRange range) {
703     assert(hasAttrOperand());
704     getLocalData()->OperandParens = range;
705   }
706
707   SourceRange getLocalSourceRange() const {
708     // Note that this does *not* include the range of the attribute
709     // enclosure, e.g.:
710     //    __attribute__((foo(bar)))
711     //    ^~~~~~~~~~~~~~~        ~~
712     // or
713     //    [[foo(bar)]]
714     //    ^~        ~~
715     // That enclosure doesn't necessarily belong to a single attribute
716     // anyway.
717     SourceRange range(getAttrNameLoc());
718     if (hasAttrOperand())
719       range.setEnd(getAttrOperandParensRange().getEnd());
720     return range;
721   }
722
723   void initializeLocal(ASTContext &Context, SourceLocation loc) {
724     setAttrNameLoc(loc);
725     if (hasAttrExprOperand()) {
726       setAttrOperandParensRange(SourceRange(loc));
727       setAttrExprOperand(0);
728     } else if (hasAttrEnumOperand()) {
729       setAttrOperandParensRange(SourceRange(loc));
730       setAttrEnumOperandLoc(loc);
731     }
732   }
733
734   QualType getInnerType() const {
735     return getTypePtr()->getModifiedType();
736   }
737 };
738
739
740 struct ObjCProtocolListLocInfo {
741   SourceLocation LAngleLoc;
742   SourceLocation RAngleLoc;
743   bool HasBaseTypeAsWritten;
744 };
745
746 // A helper class for defining ObjC TypeLocs that can qualified with
747 // protocols.
748 //
749 // TypeClass basically has to be either ObjCInterfaceType or
750 // ObjCObjectPointerType.
751 class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
752                                                  ObjCObjectTypeLoc,
753                                                  ObjCObjectType,
754                                                  ObjCProtocolListLocInfo> {
755   // SourceLocations are stored after Info, one for each Protocol.
756   SourceLocation *getProtocolLocArray() const {
757     return (SourceLocation*) this->getExtraLocalData();
758   }
759
760 public:
761   SourceLocation getLAngleLoc() const {
762     return this->getLocalData()->LAngleLoc;
763   }
764   void setLAngleLoc(SourceLocation Loc) {
765     this->getLocalData()->LAngleLoc = Loc;
766   }
767
768   SourceLocation getRAngleLoc() const {
769     return this->getLocalData()->RAngleLoc;
770   }
771   void setRAngleLoc(SourceLocation Loc) {
772     this->getLocalData()->RAngleLoc = Loc;
773   }
774
775   unsigned getNumProtocols() const {
776     return this->getTypePtr()->getNumProtocols();
777   }
778
779   SourceLocation getProtocolLoc(unsigned i) const {
780     assert(i < getNumProtocols() && "Index is out of bounds!");
781     return getProtocolLocArray()[i];
782   }
783   void setProtocolLoc(unsigned i, SourceLocation Loc) {
784     assert(i < getNumProtocols() && "Index is out of bounds!");
785     getProtocolLocArray()[i] = Loc;
786   }
787
788   ObjCProtocolDecl *getProtocol(unsigned i) const {
789     assert(i < getNumProtocols() && "Index is out of bounds!");
790     return *(this->getTypePtr()->qual_begin() + i);
791   }
792   
793   bool hasBaseTypeAsWritten() const {
794     return getLocalData()->HasBaseTypeAsWritten;
795   }
796
797   void setHasBaseTypeAsWritten(bool HasBaseType) {
798     getLocalData()->HasBaseTypeAsWritten = HasBaseType;
799   }
800
801   TypeLoc getBaseLoc() const {
802     return getInnerTypeLoc();
803   }
804
805   SourceRange getLocalSourceRange() const {
806     return SourceRange(getLAngleLoc(), getRAngleLoc());
807   }
808
809   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
810     setHasBaseTypeAsWritten(true);
811     setLAngleLoc(Loc);
812     setRAngleLoc(Loc);
813     for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
814       setProtocolLoc(i, Loc);
815   }
816
817   unsigned getExtraLocalDataSize() const {
818     return this->getNumProtocols() * sizeof(SourceLocation);
819   }
820
821   QualType getInnerType() const {
822     return getTypePtr()->getBaseType();
823   }
824 };
825
826
827 struct ObjCInterfaceLocInfo {
828   SourceLocation NameLoc;
829 };
830
831 /// \brief Wrapper for source info for ObjC interfaces.
832 class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<ObjCObjectTypeLoc,
833                                                     ObjCInterfaceTypeLoc,
834                                                     ObjCInterfaceType,
835                                                     ObjCInterfaceLocInfo> {
836 public:
837   ObjCInterfaceDecl *getIFaceDecl() const {
838     return getTypePtr()->getDecl();
839   }
840
841   SourceLocation getNameLoc() const {
842     return getLocalData()->NameLoc;
843   }
844
845   void setNameLoc(SourceLocation Loc) {
846     getLocalData()->NameLoc = Loc;
847   }
848
849   SourceRange getLocalSourceRange() const {
850     return SourceRange(getNameLoc());
851   }
852
853   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
854     setNameLoc(Loc);
855   }
856 };
857
858 struct ParenLocInfo {
859   SourceLocation LParenLoc;
860   SourceLocation RParenLoc;
861 };
862
863 class ParenTypeLoc
864   : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType,
865                            ParenLocInfo> {
866 public:
867   SourceLocation getLParenLoc() const {
868     return this->getLocalData()->LParenLoc;
869   }
870   SourceLocation getRParenLoc() const {
871     return this->getLocalData()->RParenLoc;
872   }
873   void setLParenLoc(SourceLocation Loc) {
874     this->getLocalData()->LParenLoc = Loc;
875   }
876   void setRParenLoc(SourceLocation Loc) {
877     this->getLocalData()->RParenLoc = Loc;
878   }
879
880   SourceRange getLocalSourceRange() const {
881     return SourceRange(getLParenLoc(), getRParenLoc());
882   }
883
884   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
885     setLParenLoc(Loc);
886     setRParenLoc(Loc);
887   }
888
889   TypeLoc getInnerLoc() const {
890     return getInnerTypeLoc();
891   }
892
893   QualType getInnerType() const {
894     return this->getTypePtr()->getInnerType();
895   }
896 };
897
898
899 struct PointerLikeLocInfo {
900   SourceLocation StarLoc;
901 };
902
903 /// A base class for 
904 template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo>
905 class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived,
906                                                   TypeClass, LocalData> {
907 public:  
908   SourceLocation getSigilLoc() const {
909     return this->getLocalData()->StarLoc;
910   }
911   void setSigilLoc(SourceLocation Loc) {
912     this->getLocalData()->StarLoc = Loc;
913   }
914
915   TypeLoc getPointeeLoc() const {
916     return this->getInnerTypeLoc();
917   }
918
919   SourceRange getLocalSourceRange() const {
920     return SourceRange(getSigilLoc(), getSigilLoc());
921   }
922
923   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
924     setSigilLoc(Loc);
925   }
926
927   QualType getInnerType() const {
928     return this->getTypePtr()->getPointeeType();
929   }
930 };
931
932
933 /// \brief Wrapper for source info for pointers.
934 class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc,
935                                                  PointerType> {
936 public:
937   SourceLocation getStarLoc() const {
938     return getSigilLoc();
939   }
940   void setStarLoc(SourceLocation Loc) {
941     setSigilLoc(Loc);
942   }
943 };
944
945
946 /// \brief Wrapper for source info for block pointers.
947 class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
948                                                       BlockPointerType> {
949 public:
950   SourceLocation getCaretLoc() const {
951     return getSigilLoc();
952   }
953   void setCaretLoc(SourceLocation Loc) {
954     setSigilLoc(Loc);
955   }
956 };
957
958 struct MemberPointerLocInfo : public PointerLikeLocInfo {
959   TypeSourceInfo *ClassTInfo;
960 };
961
962 /// \brief Wrapper for source info for member pointers.
963 class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
964                                                        MemberPointerType,
965                                                        MemberPointerLocInfo> {
966 public:
967   SourceLocation getStarLoc() const {
968     return getSigilLoc();
969   }
970   void setStarLoc(SourceLocation Loc) {
971     setSigilLoc(Loc);
972   }
973
974   const Type *getClass() const {
975     return getTypePtr()->getClass();
976   }
977   TypeSourceInfo *getClassTInfo() const {
978     return getLocalData()->ClassTInfo;
979   }
980   void setClassTInfo(TypeSourceInfo* TI) {
981     getLocalData()->ClassTInfo = TI;
982   }
983
984   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
985     setSigilLoc(Loc);
986     setClassTInfo(0);
987   }
988
989   SourceRange getLocalSourceRange() const {
990     if (TypeSourceInfo *TI = getClassTInfo())
991       return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc());
992     else
993       return SourceRange(getStarLoc());
994   }
995 };
996
997 /// Wraps an ObjCPointerType with source location information.
998 class ObjCObjectPointerTypeLoc :
999     public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc,
1000                               ObjCObjectPointerType> {
1001 public:
1002   SourceLocation getStarLoc() const {
1003     return getSigilLoc();
1004   }
1005
1006   void setStarLoc(SourceLocation Loc) {
1007     setSigilLoc(Loc);
1008   }
1009 };
1010
1011
1012 class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc,
1013                                                    ReferenceType> {
1014 public:
1015   QualType getInnerType() const {
1016     return getTypePtr()->getPointeeTypeAsWritten();
1017   }
1018 };
1019
1020 class LValueReferenceTypeLoc :
1021     public InheritingConcreteTypeLoc<ReferenceTypeLoc,
1022                                      LValueReferenceTypeLoc,
1023                                      LValueReferenceType> {
1024 public:
1025   SourceLocation getAmpLoc() const {
1026     return getSigilLoc();
1027   }
1028   void setAmpLoc(SourceLocation Loc) {
1029     setSigilLoc(Loc);
1030   }
1031 };
1032
1033 class RValueReferenceTypeLoc :
1034     public InheritingConcreteTypeLoc<ReferenceTypeLoc,
1035                                      RValueReferenceTypeLoc,
1036                                      RValueReferenceType> {
1037 public:
1038   SourceLocation getAmpAmpLoc() const {
1039     return getSigilLoc();
1040   }
1041   void setAmpAmpLoc(SourceLocation Loc) {
1042     setSigilLoc(Loc);
1043   }
1044 };
1045
1046
1047 struct FunctionLocInfo {
1048   SourceLocation LocalRangeBegin;
1049   SourceLocation LocalRangeEnd;
1050   bool TrailingReturn;
1051 };
1052
1053 /// \brief Wrapper for source info for functions.
1054 class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1055                                                FunctionTypeLoc,
1056                                                FunctionType,
1057                                                FunctionLocInfo> {
1058 public:
1059   SourceLocation getLocalRangeBegin() const {
1060     return getLocalData()->LocalRangeBegin;
1061   }
1062   void setLocalRangeBegin(SourceLocation L) {
1063     getLocalData()->LocalRangeBegin = L;
1064   }
1065
1066   SourceLocation getLocalRangeEnd() const {
1067     return getLocalData()->LocalRangeEnd;
1068   }
1069   void setLocalRangeEnd(SourceLocation L) {
1070     getLocalData()->LocalRangeEnd = L;
1071   }
1072
1073   bool getTrailingReturn() const {
1074     return getLocalData()->TrailingReturn;
1075   }
1076   void setTrailingReturn(bool Trailing) {
1077     getLocalData()->TrailingReturn = Trailing;
1078   }
1079
1080   // ParmVarDecls* are stored after Info, one for each argument.
1081   ParmVarDecl **getParmArray() const {
1082     return (ParmVarDecl**) getExtraLocalData();
1083   }
1084
1085   unsigned getNumArgs() const {
1086     if (isa<FunctionNoProtoType>(getTypePtr()))
1087       return 0;
1088     return cast<FunctionProtoType>(getTypePtr())->getNumArgs();
1089   }
1090   ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; }
1091   void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; }
1092
1093   TypeLoc getResultLoc() const {
1094     return getInnerTypeLoc();
1095   }
1096
1097   SourceRange getLocalSourceRange() const {
1098     return SourceRange(getLocalRangeBegin(), getLocalRangeEnd());
1099   }
1100
1101   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1102     setLocalRangeBegin(Loc);
1103     setLocalRangeEnd(Loc);
1104     setTrailingReturn(false);
1105     for (unsigned i = 0, e = getNumArgs(); i != e; ++i)
1106       setArg(i, NULL);
1107   }
1108
1109   /// \brief Returns the size of the type source info data block that is
1110   /// specific to this type.
1111   unsigned getExtraLocalDataSize() const {
1112     return getNumArgs() * sizeof(ParmVarDecl*);
1113   }
1114
1115   QualType getInnerType() const { return getTypePtr()->getResultType(); }
1116 };
1117
1118 class FunctionProtoTypeLoc :
1119     public InheritingConcreteTypeLoc<FunctionTypeLoc,
1120                                      FunctionProtoTypeLoc,
1121                                      FunctionProtoType> {
1122 };
1123
1124 class FunctionNoProtoTypeLoc :
1125     public InheritingConcreteTypeLoc<FunctionTypeLoc,
1126                                      FunctionNoProtoTypeLoc,
1127                                      FunctionNoProtoType> {
1128 };
1129
1130
1131 struct ArrayLocInfo {
1132   SourceLocation LBracketLoc, RBracketLoc;
1133   Expr *Size;
1134 };
1135
1136 /// \brief Wrapper for source info for arrays.
1137 class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1138                                             ArrayTypeLoc,
1139                                             ArrayType,
1140                                             ArrayLocInfo> {
1141 public:
1142   SourceLocation getLBracketLoc() const {
1143     return getLocalData()->LBracketLoc;
1144   }
1145   void setLBracketLoc(SourceLocation Loc) {
1146     getLocalData()->LBracketLoc = Loc;
1147   }
1148
1149   SourceLocation getRBracketLoc() const {
1150     return getLocalData()->RBracketLoc;
1151   }
1152   void setRBracketLoc(SourceLocation Loc) {
1153     getLocalData()->RBracketLoc = Loc;
1154   }
1155
1156   SourceRange getBracketsRange() const {
1157     return SourceRange(getLBracketLoc(), getRBracketLoc());
1158   }
1159
1160   Expr *getSizeExpr() const {
1161     return getLocalData()->Size;
1162   }
1163   void setSizeExpr(Expr *Size) {
1164     getLocalData()->Size = Size;
1165   }
1166
1167   TypeLoc getElementLoc() const {
1168     return getInnerTypeLoc();
1169   }
1170
1171   SourceRange getLocalSourceRange() const {
1172     return SourceRange(getLBracketLoc(), getRBracketLoc());
1173   }
1174
1175   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1176     setLBracketLoc(Loc);
1177     setRBracketLoc(Loc);
1178     setSizeExpr(NULL);
1179   }
1180
1181   QualType getInnerType() const { return getTypePtr()->getElementType(); }
1182 };
1183
1184 class ConstantArrayTypeLoc :
1185     public InheritingConcreteTypeLoc<ArrayTypeLoc,
1186                                      ConstantArrayTypeLoc,
1187                                      ConstantArrayType> {
1188 };
1189
1190 class IncompleteArrayTypeLoc :
1191     public InheritingConcreteTypeLoc<ArrayTypeLoc,
1192                                      IncompleteArrayTypeLoc,
1193                                      IncompleteArrayType> {
1194 };
1195
1196 class DependentSizedArrayTypeLoc :
1197     public InheritingConcreteTypeLoc<ArrayTypeLoc,
1198                                      DependentSizedArrayTypeLoc,
1199                                      DependentSizedArrayType> {
1200
1201 };
1202
1203 class VariableArrayTypeLoc :
1204     public InheritingConcreteTypeLoc<ArrayTypeLoc,
1205                                      VariableArrayTypeLoc,
1206                                      VariableArrayType> {
1207 };
1208
1209
1210 // Location information for a TemplateName.  Rudimentary for now.
1211 struct TemplateNameLocInfo {
1212   SourceLocation NameLoc;
1213 };
1214
1215 struct TemplateSpecializationLocInfo : TemplateNameLocInfo {
1216   SourceLocation LAngleLoc;
1217   SourceLocation RAngleLoc;
1218 };
1219
1220 class TemplateSpecializationTypeLoc :
1221     public ConcreteTypeLoc<UnqualTypeLoc,
1222                            TemplateSpecializationTypeLoc,
1223                            TemplateSpecializationType,
1224                            TemplateSpecializationLocInfo> {
1225 public:
1226   SourceLocation getLAngleLoc() const {
1227     return getLocalData()->LAngleLoc;
1228   }
1229   void setLAngleLoc(SourceLocation Loc) {
1230     getLocalData()->LAngleLoc = Loc;
1231   }
1232
1233   SourceLocation getRAngleLoc() const {
1234     return getLocalData()->RAngleLoc;
1235   }
1236   void setRAngleLoc(SourceLocation Loc) {
1237     getLocalData()->RAngleLoc = Loc;
1238   }
1239
1240   unsigned getNumArgs() const {
1241     return getTypePtr()->getNumArgs();
1242   }
1243   void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
1244     getArgInfos()[i] = AI;
1245   }
1246   TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
1247     return getArgInfos()[i];
1248   }
1249
1250   TemplateArgumentLoc getArgLoc(unsigned i) const {
1251     return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
1252   }
1253
1254   SourceLocation getTemplateNameLoc() const {
1255     return getLocalData()->NameLoc;
1256   }
1257   void setTemplateNameLoc(SourceLocation Loc) {
1258     getLocalData()->NameLoc = Loc;
1259   }
1260
1261   /// \brief - Copy the location information from the given info.
1262   void copy(TemplateSpecializationTypeLoc Loc) {
1263     unsigned size = getFullDataSize();
1264     assert(size == Loc.getFullDataSize());
1265
1266     // We're potentially copying Expr references here.  We don't
1267     // bother retaining them because TypeSourceInfos live forever, so
1268     // as long as the Expr was retained when originally written into
1269     // the TypeLoc, we're okay.
1270     memcpy(Data, Loc.Data, size);
1271   }
1272
1273   SourceRange getLocalSourceRange() const {
1274     return SourceRange(getTemplateNameLoc(), getRAngleLoc());
1275   }
1276
1277   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1278     setLAngleLoc(Loc);
1279     setRAngleLoc(Loc);
1280     setTemplateNameLoc(Loc);
1281     initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(),
1282                       getArgInfos(), Loc);
1283   }
1284
1285   static void initializeArgLocs(ASTContext &Context, unsigned NumArgs,
1286                                 const TemplateArgument *Args,
1287                                 TemplateArgumentLocInfo *ArgInfos,
1288                                 SourceLocation Loc);
1289
1290   unsigned getExtraLocalDataSize() const {
1291     return getNumArgs() * sizeof(TemplateArgumentLocInfo);
1292   }
1293
1294 private:
1295   TemplateArgumentLocInfo *getArgInfos() const {
1296     return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
1297   }
1298 };
1299
1300 //===----------------------------------------------------------------------===//
1301 //
1302 //  All of these need proper implementations.
1303 //
1304 //===----------------------------------------------------------------------===//
1305
1306 // FIXME: size expression and attribute locations (or keyword if we
1307 // ever fully support altivec syntax).
1308 class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1309                                                        VectorTypeLoc,
1310                                                        VectorType> {
1311 };
1312
1313 // FIXME: size expression and attribute locations.
1314 class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc,
1315                                                           ExtVectorTypeLoc,
1316                                                           ExtVectorType> {
1317 };
1318
1319 // FIXME: attribute locations.
1320 // For some reason, this isn't a subtype of VectorType.
1321 class DependentSizedExtVectorTypeLoc :
1322     public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1323                                      DependentSizedExtVectorTypeLoc,
1324                                      DependentSizedExtVectorType> {
1325 };
1326
1327 // FIXME: location of the '_Complex' keyword.
1328 class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1329                                                         ComplexTypeLoc,
1330                                                         ComplexType> {
1331 };
1332
1333 struct TypeofLocInfo {
1334   SourceLocation TypeofLoc;
1335   SourceLocation LParenLoc;
1336   SourceLocation RParenLoc;
1337 };
1338
1339 struct TypeOfExprTypeLocInfo : public TypeofLocInfo {
1340 };
1341
1342 struct TypeOfTypeLocInfo : public TypeofLocInfo {
1343   TypeSourceInfo* UnderlyingTInfo;
1344 };
1345
1346 template <class Derived, class TypeClass, class LocalData = TypeofLocInfo>
1347 class TypeofLikeTypeLoc
1348   : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> {
1349 public:
1350   SourceLocation getTypeofLoc() const {
1351     return this->getLocalData()->TypeofLoc;
1352   }
1353   void setTypeofLoc(SourceLocation Loc) {
1354     this->getLocalData()->TypeofLoc = Loc;
1355   }
1356
1357   SourceLocation getLParenLoc() const {
1358     return this->getLocalData()->LParenLoc;
1359   }
1360   void setLParenLoc(SourceLocation Loc) {
1361     this->getLocalData()->LParenLoc = Loc;
1362   }
1363
1364   SourceLocation getRParenLoc() const {
1365     return this->getLocalData()->RParenLoc;
1366   }
1367   void setRParenLoc(SourceLocation Loc) {
1368     this->getLocalData()->RParenLoc = Loc;
1369   }
1370
1371   SourceRange getParensRange() const {
1372     return SourceRange(getLParenLoc(), getRParenLoc());
1373   }
1374   void setParensRange(SourceRange range) {
1375       setLParenLoc(range.getBegin());
1376       setRParenLoc(range.getEnd());
1377   }
1378
1379   SourceRange getLocalSourceRange() const {
1380     return SourceRange(getTypeofLoc(), getRParenLoc());
1381   }
1382
1383   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1384     setTypeofLoc(Loc);
1385     setLParenLoc(Loc);
1386     setRParenLoc(Loc);
1387   }
1388 };
1389
1390 class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc,
1391                                                    TypeOfExprType,
1392                                                    TypeOfExprTypeLocInfo> {
1393 public:
1394   Expr* getUnderlyingExpr() const {
1395     return getTypePtr()->getUnderlyingExpr();
1396   }
1397   // Reimplemented to account for GNU/C++ extension
1398   //     typeof unary-expression
1399   // where there are no parentheses.
1400   SourceRange getLocalSourceRange() const;
1401 };
1402
1403 class TypeOfTypeLoc
1404   : public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> {
1405 public:
1406   QualType getUnderlyingType() const {
1407     return this->getTypePtr()->getUnderlyingType();
1408   }
1409   TypeSourceInfo* getUnderlyingTInfo() const {
1410     return this->getLocalData()->UnderlyingTInfo;
1411   }
1412   void setUnderlyingTInfo(TypeSourceInfo* TI) const {
1413     this->getLocalData()->UnderlyingTInfo = TI;
1414   }
1415 };
1416
1417 // FIXME: location of the 'decltype' and parens.
1418 class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1419                                                          DecltypeTypeLoc,
1420                                                          DecltypeType> {
1421 public:
1422   Expr *getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); }
1423 };
1424
1425 struct UnaryTransformTypeLocInfo {
1426   // FIXME: While there's only one unary transform right now, future ones may
1427   // need different representations
1428   SourceLocation KWLoc, LParenLoc, RParenLoc;
1429   TypeSourceInfo *UnderlyingTInfo;
1430 };
1431
1432 class UnaryTransformTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1433                                                     UnaryTransformTypeLoc,
1434                                                     UnaryTransformType,
1435                                                     UnaryTransformTypeLocInfo> {
1436 public:
1437   SourceLocation getKWLoc() const { return getLocalData()->KWLoc; }
1438   void setKWLoc(SourceLocation Loc) { getLocalData()->KWLoc = Loc; }
1439
1440   SourceLocation getLParenLoc() const { return getLocalData()->LParenLoc; }
1441   void setLParenLoc(SourceLocation Loc) { getLocalData()->LParenLoc = Loc; }
1442
1443   SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; }
1444   void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; }
1445
1446   TypeSourceInfo* getUnderlyingTInfo() const {
1447     return getLocalData()->UnderlyingTInfo;
1448   }
1449   void setUnderlyingTInfo(TypeSourceInfo *TInfo) {
1450     getLocalData()->UnderlyingTInfo = TInfo;
1451   }
1452
1453   SourceRange getLocalSourceRange() const {
1454     return SourceRange(getKWLoc(), getRParenLoc());
1455   }
1456
1457   SourceRange getParensRange() const {
1458     return SourceRange(getLParenLoc(), getRParenLoc());
1459   }
1460   void setParensRange(SourceRange Range) {
1461     setLParenLoc(Range.getBegin());
1462     setRParenLoc(Range.getEnd());
1463   }
1464
1465   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1466     setKWLoc(Loc);
1467     setRParenLoc(Loc);
1468     setLParenLoc(Loc);
1469   }
1470 };
1471
1472 class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1473                                                         AutoTypeLoc,
1474                                                         AutoType> {
1475 };
1476
1477 struct ElaboratedLocInfo {
1478   SourceLocation KeywordLoc;
1479   
1480   /// \brief Opaque data pointer used to reconstruct a nested-name-specifier
1481   /// from 
1482   void *QualifierData;
1483 };
1484
1485 class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1486                                                  ElaboratedTypeLoc,
1487                                                  ElaboratedType,
1488                                                  ElaboratedLocInfo> {
1489 public:
1490   SourceLocation getKeywordLoc() const {
1491     return this->getLocalData()->KeywordLoc;
1492   }
1493   void setKeywordLoc(SourceLocation Loc) {
1494     this->getLocalData()->KeywordLoc = Loc;
1495   }
1496
1497   NestedNameSpecifierLoc getQualifierLoc() const {
1498     return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), 
1499                                   getLocalData()->QualifierData);
1500   }
1501  
1502   void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
1503     assert(QualifierLoc.getNestedNameSpecifier() 
1504                                             == getTypePtr()->getQualifier() &&
1505            "Inconsistent nested-name-specifier pointer");
1506     getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
1507   }
1508
1509   SourceRange getLocalSourceRange() const {
1510     if (getKeywordLoc().isValid())
1511       if (getQualifierLoc())
1512         return SourceRange(getKeywordLoc(), getQualifierLoc().getEndLoc());
1513       else
1514         return SourceRange(getKeywordLoc());
1515     else
1516       return getQualifierLoc().getSourceRange();
1517   }
1518
1519   void initializeLocal(ASTContext &Context, SourceLocation Loc);
1520
1521   TypeLoc getNamedTypeLoc() const {
1522     return getInnerTypeLoc();
1523   }
1524
1525   QualType getInnerType() const {
1526     return getTypePtr()->getNamedType();
1527   }
1528
1529   void copy(ElaboratedTypeLoc Loc) {
1530     unsigned size = getFullDataSize();
1531     assert(size == Loc.getFullDataSize());
1532     memcpy(Data, Loc.Data, size);
1533   }
1534 };
1535
1536 // This is exactly the structure of an ElaboratedTypeLoc whose inner
1537 // type is some sort of TypeDeclTypeLoc.
1538 struct DependentNameLocInfo : ElaboratedLocInfo {
1539   SourceLocation NameLoc;
1540   
1541   /// \brief Data associated with the nested-name-specifier location.
1542   void *QualifierData;
1543 };
1544
1545 class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1546                                                     DependentNameTypeLoc,
1547                                                     DependentNameType,
1548                                                     DependentNameLocInfo> {
1549 public:
1550   SourceLocation getKeywordLoc() const {
1551     return this->getLocalData()->KeywordLoc;
1552   }
1553   void setKeywordLoc(SourceLocation Loc) {
1554     this->getLocalData()->KeywordLoc = Loc;
1555   }
1556
1557   NestedNameSpecifierLoc getQualifierLoc() const {
1558     return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), 
1559                                   getLocalData()->QualifierData);
1560   }
1561       
1562   void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
1563     assert(QualifierLoc.getNestedNameSpecifier() 
1564                                             == getTypePtr()->getQualifier() &&
1565            "Inconsistent nested-name-specifier pointer");
1566     getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
1567   }
1568                                                       
1569   SourceLocation getNameLoc() const {
1570     return this->getLocalData()->NameLoc;
1571   }
1572   void setNameLoc(SourceLocation Loc) {
1573     this->getLocalData()->NameLoc = Loc;
1574   }
1575
1576   SourceRange getLocalSourceRange() const {
1577     if (getKeywordLoc().isValid())
1578       return SourceRange(getKeywordLoc(), getNameLoc());
1579     else
1580       return SourceRange(getQualifierLoc().getBeginLoc(), getNameLoc());
1581   }
1582
1583   void copy(DependentNameTypeLoc Loc) {
1584     unsigned size = getFullDataSize();
1585     assert(size == Loc.getFullDataSize());
1586     memcpy(Data, Loc.Data, size);
1587   }
1588
1589   void initializeLocal(ASTContext &Context, SourceLocation Loc);
1590 };
1591
1592 struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo {
1593   SourceLocation KeywordLoc;
1594   SourceLocation LAngleLoc;
1595   SourceLocation RAngleLoc;
1596   // followed by a TemplateArgumentLocInfo[]
1597 };
1598
1599 class DependentTemplateSpecializationTypeLoc :
1600     public ConcreteTypeLoc<UnqualTypeLoc,
1601                            DependentTemplateSpecializationTypeLoc,
1602                            DependentTemplateSpecializationType,
1603                            DependentTemplateSpecializationLocInfo> {
1604 public:
1605   SourceLocation getKeywordLoc() const {
1606     return this->getLocalData()->KeywordLoc;
1607   }
1608   void setKeywordLoc(SourceLocation Loc) {
1609     this->getLocalData()->KeywordLoc = Loc;
1610   }
1611
1612   NestedNameSpecifierLoc getQualifierLoc() const {
1613     if (!getLocalData()->QualifierData)
1614       return NestedNameSpecifierLoc();
1615     
1616     return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), 
1617                                   getLocalData()->QualifierData);
1618   }
1619    
1620   void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
1621     if (!QualifierLoc) {
1622       // Even if we have a nested-name-specifier in the dependent 
1623       // template specialization type, we won't record the nested-name-specifier
1624       // location information when this type-source location information is
1625       // part of a nested-name-specifier.
1626       getLocalData()->QualifierData = 0;
1627       return;
1628     }
1629     
1630     assert(QualifierLoc.getNestedNameSpecifier() 
1631                                         == getTypePtr()->getQualifier() &&
1632            "Inconsistent nested-name-specifier pointer");
1633     getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
1634   }
1635
1636   SourceLocation getNameLoc() const {
1637     return this->getLocalData()->NameLoc;
1638   }
1639   void setNameLoc(SourceLocation Loc) {
1640     this->getLocalData()->NameLoc = Loc;
1641   }
1642
1643   SourceLocation getLAngleLoc() const {
1644     return this->getLocalData()->LAngleLoc;
1645   }
1646   void setLAngleLoc(SourceLocation Loc) {
1647     this->getLocalData()->LAngleLoc = Loc;
1648   }
1649
1650   SourceLocation getRAngleLoc() const {
1651     return this->getLocalData()->RAngleLoc;
1652   }
1653   void setRAngleLoc(SourceLocation Loc) {
1654     this->getLocalData()->RAngleLoc = Loc;
1655   }
1656
1657   unsigned getNumArgs() const {
1658     return getTypePtr()->getNumArgs();
1659   }
1660
1661   void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
1662     getArgInfos()[i] = AI;
1663   }
1664   TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
1665     return getArgInfos()[i];
1666   }
1667
1668   TemplateArgumentLoc getArgLoc(unsigned i) const {
1669     return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
1670   }
1671
1672   SourceRange getLocalSourceRange() const {
1673     if (getKeywordLoc().isValid())
1674       return SourceRange(getKeywordLoc(), getRAngleLoc());
1675     else if (getQualifierLoc())
1676       return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc());
1677     else
1678       return SourceRange(getNameLoc(), getRAngleLoc());
1679   }
1680
1681   void copy(DependentTemplateSpecializationTypeLoc Loc) {
1682     unsigned size = getFullDataSize();
1683     assert(size == Loc.getFullDataSize());
1684     memcpy(Data, Loc.Data, size);
1685   }
1686
1687   void initializeLocal(ASTContext &Context, SourceLocation Loc);
1688
1689   unsigned getExtraLocalDataSize() const {
1690     return getNumArgs() * sizeof(TemplateArgumentLocInfo);
1691   }
1692
1693 private:
1694   TemplateArgumentLocInfo *getArgInfos() const {
1695     return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
1696   }
1697 };
1698
1699
1700 struct PackExpansionTypeLocInfo {
1701   SourceLocation EllipsisLoc;
1702 };
1703
1704 class PackExpansionTypeLoc
1705   : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc, 
1706                            PackExpansionType, PackExpansionTypeLocInfo> {
1707 public:
1708   SourceLocation getEllipsisLoc() const {
1709     return this->getLocalData()->EllipsisLoc;
1710   }
1711
1712   void setEllipsisLoc(SourceLocation Loc) {
1713     this->getLocalData()->EllipsisLoc = Loc;
1714   }
1715
1716   SourceRange getLocalSourceRange() const {
1717     return SourceRange(getEllipsisLoc(), getEllipsisLoc());
1718   }
1719
1720   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1721     setEllipsisLoc(Loc);
1722   }
1723
1724   TypeLoc getPatternLoc() const {
1725     return getInnerTypeLoc();
1726   }
1727
1728   QualType getInnerType() const {
1729     return this->getTypePtr()->getPattern();
1730   }
1731 };
1732
1733 struct AtomicTypeLocInfo {
1734   SourceLocation KWLoc, LParenLoc, RParenLoc;
1735 };
1736
1737 class AtomicTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AtomicTypeLoc,
1738                                              AtomicType, AtomicTypeLocInfo> {
1739 public:  
1740   TypeLoc getValueLoc() const {
1741     return this->getInnerTypeLoc();
1742   }
1743
1744   SourceRange getLocalSourceRange() const {
1745     return SourceRange(getKWLoc(), getRParenLoc());
1746   }
1747
1748   SourceLocation getKWLoc() const {
1749     return this->getLocalData()->KWLoc;
1750   }
1751   void setKWLoc(SourceLocation Loc) {
1752     this->getLocalData()->KWLoc = Loc;
1753   }
1754
1755   SourceLocation getLParenLoc() const {
1756     return this->getLocalData()->LParenLoc;
1757   }
1758   void setLParenLoc(SourceLocation Loc) {
1759     this->getLocalData()->LParenLoc = Loc;
1760   }
1761
1762   SourceLocation getRParenLoc() const {
1763     return this->getLocalData()->RParenLoc;
1764   }
1765   void setRParenLoc(SourceLocation Loc) {
1766     this->getLocalData()->RParenLoc = Loc;
1767   }
1768
1769   SourceRange getParensRange() const {
1770     return SourceRange(getLParenLoc(), getRParenLoc());
1771   }
1772   void setParensRange(SourceRange Range) {
1773     setLParenLoc(Range.getBegin());
1774     setRParenLoc(Range.getEnd());
1775   }
1776
1777   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1778     setKWLoc(Loc);
1779     setLParenLoc(Loc);
1780     setRParenLoc(Loc);
1781   }
1782
1783   QualType getInnerType() const {
1784     return this->getTypePtr()->getValueType();
1785   }
1786 };
1787
1788
1789 }
1790
1791 #endif