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