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