TypeLoc.h revision 9fbf327cfdd27ddb5d845042c95f2299ac95b143
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/// \param Base a class from which to derive
254/// \param Derived the class deriving from this one
255/// \param TypeClass the concrete Type subclass associated with this
256///   location type
257/// \param 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  }
870};
871
872struct ParenLocInfo {
873  SourceLocation LParenLoc;
874  SourceLocation RParenLoc;
875};
876
877class ParenTypeLoc
878  : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType,
879                           ParenLocInfo> {
880public:
881  SourceLocation getLParenLoc() const {
882    return this->getLocalData()->LParenLoc;
883  }
884  SourceLocation getRParenLoc() const {
885    return this->getLocalData()->RParenLoc;
886  }
887  void setLParenLoc(SourceLocation Loc) {
888    this->getLocalData()->LParenLoc = Loc;
889  }
890  void setRParenLoc(SourceLocation Loc) {
891    this->getLocalData()->RParenLoc = Loc;
892  }
893
894  SourceRange getLocalSourceRange() const {
895    return SourceRange(getLParenLoc(), getRParenLoc());
896  }
897
898  void initializeLocal(ASTContext &Context, SourceLocation Loc) {
899    setLParenLoc(Loc);
900    setRParenLoc(Loc);
901  }
902
903  TypeLoc getInnerLoc() const {
904    return getInnerTypeLoc();
905  }
906
907  QualType getInnerType() const {
908    return this->getTypePtr()->getInnerType();
909  }
910};
911
912
913struct PointerLikeLocInfo {
914  SourceLocation StarLoc;
915};
916
917/// A base class for
918template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo>
919class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived,
920                                                  TypeClass, LocalData> {
921public:
922  SourceLocation getSigilLoc() const {
923    return this->getLocalData()->StarLoc;
924  }
925  void setSigilLoc(SourceLocation Loc) {
926    this->getLocalData()->StarLoc = Loc;
927  }
928
929  TypeLoc getPointeeLoc() const {
930    return this->getInnerTypeLoc();
931  }
932
933  SourceRange getLocalSourceRange() const {
934    return SourceRange(getSigilLoc(), getSigilLoc());
935  }
936
937  void initializeLocal(ASTContext &Context, SourceLocation Loc) {
938    setSigilLoc(Loc);
939  }
940
941  QualType getInnerType() const {
942    return this->getTypePtr()->getPointeeType();
943  }
944};
945
946
947/// \brief Wrapper for source info for pointers.
948class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc,
949                                                 PointerType> {
950public:
951  SourceLocation getStarLoc() const {
952    return getSigilLoc();
953  }
954  void setStarLoc(SourceLocation Loc) {
955    setSigilLoc(Loc);
956  }
957};
958
959
960/// \brief Wrapper for source info for block pointers.
961class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
962                                                      BlockPointerType> {
963public:
964  SourceLocation getCaretLoc() const {
965    return getSigilLoc();
966  }
967  void setCaretLoc(SourceLocation Loc) {
968    setSigilLoc(Loc);
969  }
970};
971
972struct MemberPointerLocInfo : public PointerLikeLocInfo {
973  TypeSourceInfo *ClassTInfo;
974};
975
976/// \brief Wrapper for source info for member pointers.
977class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
978                                                       MemberPointerType,
979                                                       MemberPointerLocInfo> {
980public:
981  SourceLocation getStarLoc() const {
982    return getSigilLoc();
983  }
984  void setStarLoc(SourceLocation Loc) {
985    setSigilLoc(Loc);
986  }
987
988  const Type *getClass() const {
989    return getTypePtr()->getClass();
990  }
991  TypeSourceInfo *getClassTInfo() const {
992    return getLocalData()->ClassTInfo;
993  }
994  void setClassTInfo(TypeSourceInfo* TI) {
995    getLocalData()->ClassTInfo = TI;
996  }
997
998  void initializeLocal(ASTContext &Context, SourceLocation Loc) {
999    setSigilLoc(Loc);
1000    setClassTInfo(0);
1001  }
1002
1003  SourceRange getLocalSourceRange() const {
1004    if (TypeSourceInfo *TI = getClassTInfo())
1005      return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc());
1006    else
1007      return SourceRange(getStarLoc());
1008  }
1009};
1010
1011/// Wraps an ObjCPointerType with source location information.
1012class ObjCObjectPointerTypeLoc :
1013    public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc,
1014                              ObjCObjectPointerType> {
1015public:
1016  SourceLocation getStarLoc() const {
1017    return getSigilLoc();
1018  }
1019
1020  void setStarLoc(SourceLocation Loc) {
1021    setSigilLoc(Loc);
1022  }
1023};
1024
1025
1026class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc,
1027                                                   ReferenceType> {
1028public:
1029  QualType getInnerType() const {
1030    return getTypePtr()->getPointeeTypeAsWritten();
1031  }
1032};
1033
1034class LValueReferenceTypeLoc :
1035    public InheritingConcreteTypeLoc<ReferenceTypeLoc,
1036                                     LValueReferenceTypeLoc,
1037                                     LValueReferenceType> {
1038public:
1039  SourceLocation getAmpLoc() const {
1040    return getSigilLoc();
1041  }
1042  void setAmpLoc(SourceLocation Loc) {
1043    setSigilLoc(Loc);
1044  }
1045};
1046
1047class RValueReferenceTypeLoc :
1048    public InheritingConcreteTypeLoc<ReferenceTypeLoc,
1049                                     RValueReferenceTypeLoc,
1050                                     RValueReferenceType> {
1051public:
1052  SourceLocation getAmpAmpLoc() const {
1053    return getSigilLoc();
1054  }
1055  void setAmpAmpLoc(SourceLocation Loc) {
1056    setSigilLoc(Loc);
1057  }
1058};
1059
1060
1061struct FunctionLocInfo {
1062  SourceLocation LocalRangeBegin;
1063  SourceLocation LocalRangeEnd;
1064};
1065
1066/// \brief Wrapper for source info for functions.
1067class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1068                                               FunctionTypeLoc,
1069                                               FunctionType,
1070                                               FunctionLocInfo> {
1071public:
1072  SourceLocation getLocalRangeBegin() const {
1073    return getLocalData()->LocalRangeBegin;
1074  }
1075  void setLocalRangeBegin(SourceLocation L) {
1076    getLocalData()->LocalRangeBegin = L;
1077  }
1078
1079  SourceLocation getLocalRangeEnd() const {
1080    return getLocalData()->LocalRangeEnd;
1081  }
1082  void setLocalRangeEnd(SourceLocation L) {
1083    getLocalData()->LocalRangeEnd = L;
1084  }
1085
1086  ArrayRef<ParmVarDecl *> getParams() const {
1087    return ArrayRef<ParmVarDecl *>(getParmArray(), getNumArgs());
1088  }
1089
1090  // ParmVarDecls* are stored after Info, one for each argument.
1091  ParmVarDecl **getParmArray() const {
1092    return (ParmVarDecl**) getExtraLocalData();
1093  }
1094
1095  unsigned getNumArgs() const {
1096    if (isa<FunctionNoProtoType>(getTypePtr()))
1097      return 0;
1098    return cast<FunctionProtoType>(getTypePtr())->getNumArgs();
1099  }
1100  ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; }
1101  void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; }
1102
1103  TypeLoc getResultLoc() const {
1104    return getInnerTypeLoc();
1105  }
1106
1107  SourceRange getLocalSourceRange() const {
1108    return SourceRange(getLocalRangeBegin(), getLocalRangeEnd());
1109  }
1110
1111  void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1112    setLocalRangeBegin(Loc);
1113    setLocalRangeEnd(Loc);
1114    for (unsigned i = 0, e = getNumArgs(); i != e; ++i)
1115      setArg(i, NULL);
1116  }
1117
1118  /// \brief Returns the size of the type source info data block that is
1119  /// specific to this type.
1120  unsigned getExtraLocalDataSize() const {
1121    return getNumArgs() * sizeof(ParmVarDecl*);
1122  }
1123
1124  QualType getInnerType() const { return getTypePtr()->getResultType(); }
1125};
1126
1127class FunctionProtoTypeLoc :
1128    public InheritingConcreteTypeLoc<FunctionTypeLoc,
1129                                     FunctionProtoTypeLoc,
1130                                     FunctionProtoType> {
1131};
1132
1133class FunctionNoProtoTypeLoc :
1134    public InheritingConcreteTypeLoc<FunctionTypeLoc,
1135                                     FunctionNoProtoTypeLoc,
1136                                     FunctionNoProtoType> {
1137};
1138
1139
1140struct ArrayLocInfo {
1141  SourceLocation LBracketLoc, RBracketLoc;
1142  Expr *Size;
1143};
1144
1145/// \brief Wrapper for source info for arrays.
1146class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1147                                            ArrayTypeLoc,
1148                                            ArrayType,
1149                                            ArrayLocInfo> {
1150public:
1151  SourceLocation getLBracketLoc() const {
1152    return getLocalData()->LBracketLoc;
1153  }
1154  void setLBracketLoc(SourceLocation Loc) {
1155    getLocalData()->LBracketLoc = Loc;
1156  }
1157
1158  SourceLocation getRBracketLoc() const {
1159    return getLocalData()->RBracketLoc;
1160  }
1161  void setRBracketLoc(SourceLocation Loc) {
1162    getLocalData()->RBracketLoc = Loc;
1163  }
1164
1165  SourceRange getBracketsRange() const {
1166    return SourceRange(getLBracketLoc(), getRBracketLoc());
1167  }
1168
1169  Expr *getSizeExpr() const {
1170    return getLocalData()->Size;
1171  }
1172  void setSizeExpr(Expr *Size) {
1173    getLocalData()->Size = Size;
1174  }
1175
1176  TypeLoc getElementLoc() const {
1177    return getInnerTypeLoc();
1178  }
1179
1180  SourceRange getLocalSourceRange() const {
1181    return SourceRange(getLBracketLoc(), getRBracketLoc());
1182  }
1183
1184  void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1185    setLBracketLoc(Loc);
1186    setRBracketLoc(Loc);
1187    setSizeExpr(NULL);
1188  }
1189
1190  QualType getInnerType() const { return getTypePtr()->getElementType(); }
1191};
1192
1193class ConstantArrayTypeLoc :
1194    public InheritingConcreteTypeLoc<ArrayTypeLoc,
1195                                     ConstantArrayTypeLoc,
1196                                     ConstantArrayType> {
1197};
1198
1199class IncompleteArrayTypeLoc :
1200    public InheritingConcreteTypeLoc<ArrayTypeLoc,
1201                                     IncompleteArrayTypeLoc,
1202                                     IncompleteArrayType> {
1203};
1204
1205class DependentSizedArrayTypeLoc :
1206    public InheritingConcreteTypeLoc<ArrayTypeLoc,
1207                                     DependentSizedArrayTypeLoc,
1208                                     DependentSizedArrayType> {
1209
1210};
1211
1212class VariableArrayTypeLoc :
1213    public InheritingConcreteTypeLoc<ArrayTypeLoc,
1214                                     VariableArrayTypeLoc,
1215                                     VariableArrayType> {
1216};
1217
1218
1219// Location information for a TemplateName.  Rudimentary for now.
1220struct TemplateNameLocInfo {
1221  SourceLocation NameLoc;
1222};
1223
1224struct TemplateSpecializationLocInfo : TemplateNameLocInfo {
1225  SourceLocation TemplateKWLoc;
1226  SourceLocation LAngleLoc;
1227  SourceLocation RAngleLoc;
1228};
1229
1230class TemplateSpecializationTypeLoc :
1231    public ConcreteTypeLoc<UnqualTypeLoc,
1232                           TemplateSpecializationTypeLoc,
1233                           TemplateSpecializationType,
1234                           TemplateSpecializationLocInfo> {
1235public:
1236  SourceLocation getTemplateKeywordLoc() const {
1237    return getLocalData()->TemplateKWLoc;
1238  }
1239  void setTemplateKeywordLoc(SourceLocation Loc) {
1240    getLocalData()->TemplateKWLoc = Loc;
1241  }
1242
1243  SourceLocation getLAngleLoc() const {
1244    return getLocalData()->LAngleLoc;
1245  }
1246  void setLAngleLoc(SourceLocation Loc) {
1247    getLocalData()->LAngleLoc = Loc;
1248  }
1249
1250  SourceLocation getRAngleLoc() const {
1251    return getLocalData()->RAngleLoc;
1252  }
1253  void setRAngleLoc(SourceLocation Loc) {
1254    getLocalData()->RAngleLoc = Loc;
1255  }
1256
1257  unsigned getNumArgs() const {
1258    return getTypePtr()->getNumArgs();
1259  }
1260  void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
1261    getArgInfos()[i] = AI;
1262  }
1263  TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
1264    return getArgInfos()[i];
1265  }
1266
1267  TemplateArgumentLoc getArgLoc(unsigned i) const {
1268    return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
1269  }
1270
1271  SourceLocation getTemplateNameLoc() const {
1272    return getLocalData()->NameLoc;
1273  }
1274  void setTemplateNameLoc(SourceLocation Loc) {
1275    getLocalData()->NameLoc = Loc;
1276  }
1277
1278  /// \brief - Copy the location information from the given info.
1279  void copy(TemplateSpecializationTypeLoc Loc) {
1280    unsigned size = getFullDataSize();
1281    assert(size == Loc.getFullDataSize());
1282
1283    // We're potentially copying Expr references here.  We don't
1284    // bother retaining them because TypeSourceInfos live forever, so
1285    // as long as the Expr was retained when originally written into
1286    // the TypeLoc, we're okay.
1287    memcpy(Data, Loc.Data, size);
1288  }
1289
1290  SourceRange getLocalSourceRange() const {
1291    if (getTemplateKeywordLoc().isValid())
1292      return SourceRange(getTemplateKeywordLoc(), getRAngleLoc());
1293    else
1294      return SourceRange(getTemplateNameLoc(), getRAngleLoc());
1295  }
1296
1297  void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1298    setTemplateKeywordLoc(Loc);
1299    setTemplateNameLoc(Loc);
1300    setLAngleLoc(Loc);
1301    setRAngleLoc(Loc);
1302    initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(),
1303                      getArgInfos(), Loc);
1304  }
1305
1306  static void initializeArgLocs(ASTContext &Context, unsigned NumArgs,
1307                                const TemplateArgument *Args,
1308                                TemplateArgumentLocInfo *ArgInfos,
1309                                SourceLocation Loc);
1310
1311  unsigned getExtraLocalDataSize() const {
1312    return getNumArgs() * sizeof(TemplateArgumentLocInfo);
1313  }
1314
1315private:
1316  TemplateArgumentLocInfo *getArgInfos() const {
1317    return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
1318  }
1319};
1320
1321//===----------------------------------------------------------------------===//
1322//
1323//  All of these need proper implementations.
1324//
1325//===----------------------------------------------------------------------===//
1326
1327// FIXME: size expression and attribute locations (or keyword if we
1328// ever fully support altivec syntax).
1329class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1330                                                       VectorTypeLoc,
1331                                                       VectorType> {
1332};
1333
1334// FIXME: size expression and attribute locations.
1335class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc,
1336                                                          ExtVectorTypeLoc,
1337                                                          ExtVectorType> {
1338};
1339
1340// FIXME: attribute locations.
1341// For some reason, this isn't a subtype of VectorType.
1342class DependentSizedExtVectorTypeLoc :
1343    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1344                                     DependentSizedExtVectorTypeLoc,
1345                                     DependentSizedExtVectorType> {
1346};
1347
1348// FIXME: location of the '_Complex' keyword.
1349class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1350                                                        ComplexTypeLoc,
1351                                                        ComplexType> {
1352};
1353
1354struct TypeofLocInfo {
1355  SourceLocation TypeofLoc;
1356  SourceLocation LParenLoc;
1357  SourceLocation RParenLoc;
1358};
1359
1360struct TypeOfExprTypeLocInfo : public TypeofLocInfo {
1361};
1362
1363struct TypeOfTypeLocInfo : public TypeofLocInfo {
1364  TypeSourceInfo* UnderlyingTInfo;
1365};
1366
1367template <class Derived, class TypeClass, class LocalData = TypeofLocInfo>
1368class TypeofLikeTypeLoc
1369  : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> {
1370public:
1371  SourceLocation getTypeofLoc() const {
1372    return this->getLocalData()->TypeofLoc;
1373  }
1374  void setTypeofLoc(SourceLocation Loc) {
1375    this->getLocalData()->TypeofLoc = Loc;
1376  }
1377
1378  SourceLocation getLParenLoc() const {
1379    return this->getLocalData()->LParenLoc;
1380  }
1381  void setLParenLoc(SourceLocation Loc) {
1382    this->getLocalData()->LParenLoc = Loc;
1383  }
1384
1385  SourceLocation getRParenLoc() const {
1386    return this->getLocalData()->RParenLoc;
1387  }
1388  void setRParenLoc(SourceLocation Loc) {
1389    this->getLocalData()->RParenLoc = Loc;
1390  }
1391
1392  SourceRange getParensRange() const {
1393    return SourceRange(getLParenLoc(), getRParenLoc());
1394  }
1395  void setParensRange(SourceRange range) {
1396      setLParenLoc(range.getBegin());
1397      setRParenLoc(range.getEnd());
1398  }
1399
1400  SourceRange getLocalSourceRange() const {
1401    return SourceRange(getTypeofLoc(), getRParenLoc());
1402  }
1403
1404  void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1405    setTypeofLoc(Loc);
1406    setLParenLoc(Loc);
1407    setRParenLoc(Loc);
1408  }
1409};
1410
1411class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc,
1412                                                   TypeOfExprType,
1413                                                   TypeOfExprTypeLocInfo> {
1414public:
1415  Expr* getUnderlyingExpr() const {
1416    return getTypePtr()->getUnderlyingExpr();
1417  }
1418  // Reimplemented to account for GNU/C++ extension
1419  //     typeof unary-expression
1420  // where there are no parentheses.
1421  SourceRange getLocalSourceRange() const;
1422};
1423
1424class TypeOfTypeLoc
1425  : public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> {
1426public:
1427  QualType getUnderlyingType() const {
1428    return this->getTypePtr()->getUnderlyingType();
1429  }
1430  TypeSourceInfo* getUnderlyingTInfo() const {
1431    return this->getLocalData()->UnderlyingTInfo;
1432  }
1433  void setUnderlyingTInfo(TypeSourceInfo* TI) const {
1434    this->getLocalData()->UnderlyingTInfo = TI;
1435  }
1436};
1437
1438// FIXME: location of the 'decltype' and parens.
1439class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1440                                                         DecltypeTypeLoc,
1441                                                         DecltypeType> {
1442public:
1443  Expr *getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); }
1444};
1445
1446struct UnaryTransformTypeLocInfo {
1447  // FIXME: While there's only one unary transform right now, future ones may
1448  // need different representations
1449  SourceLocation KWLoc, LParenLoc, RParenLoc;
1450  TypeSourceInfo *UnderlyingTInfo;
1451};
1452
1453class UnaryTransformTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1454                                                    UnaryTransformTypeLoc,
1455                                                    UnaryTransformType,
1456                                                    UnaryTransformTypeLocInfo> {
1457public:
1458  SourceLocation getKWLoc() const { return getLocalData()->KWLoc; }
1459  void setKWLoc(SourceLocation Loc) { getLocalData()->KWLoc = Loc; }
1460
1461  SourceLocation getLParenLoc() const { return getLocalData()->LParenLoc; }
1462  void setLParenLoc(SourceLocation Loc) { getLocalData()->LParenLoc = Loc; }
1463
1464  SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; }
1465  void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; }
1466
1467  TypeSourceInfo* getUnderlyingTInfo() const {
1468    return getLocalData()->UnderlyingTInfo;
1469  }
1470  void setUnderlyingTInfo(TypeSourceInfo *TInfo) {
1471    getLocalData()->UnderlyingTInfo = TInfo;
1472  }
1473
1474  SourceRange getLocalSourceRange() const {
1475    return SourceRange(getKWLoc(), getRParenLoc());
1476  }
1477
1478  SourceRange getParensRange() const {
1479    return SourceRange(getLParenLoc(), getRParenLoc());
1480  }
1481  void setParensRange(SourceRange Range) {
1482    setLParenLoc(Range.getBegin());
1483    setRParenLoc(Range.getEnd());
1484  }
1485
1486  void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1487    setKWLoc(Loc);
1488    setRParenLoc(Loc);
1489    setLParenLoc(Loc);
1490  }
1491};
1492
1493class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1494                                                        AutoTypeLoc,
1495                                                        AutoType> {
1496};
1497
1498struct ElaboratedLocInfo {
1499  SourceLocation ElaboratedKWLoc;
1500  /// \brief Data associated with the nested-name-specifier location.
1501  void *QualifierData;
1502};
1503
1504class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1505                                                 ElaboratedTypeLoc,
1506                                                 ElaboratedType,
1507                                                 ElaboratedLocInfo> {
1508public:
1509  SourceLocation getElaboratedKeywordLoc() const {
1510    return this->getLocalData()->ElaboratedKWLoc;
1511  }
1512  void setElaboratedKeywordLoc(SourceLocation Loc) {
1513    this->getLocalData()->ElaboratedKWLoc = Loc;
1514  }
1515
1516  NestedNameSpecifierLoc getQualifierLoc() const {
1517    return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
1518                                  getLocalData()->QualifierData);
1519  }
1520
1521  void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
1522    assert(QualifierLoc.getNestedNameSpecifier()
1523                                            == getTypePtr()->getQualifier() &&
1524           "Inconsistent nested-name-specifier pointer");
1525    getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
1526  }
1527
1528  SourceRange getLocalSourceRange() const {
1529    if (getElaboratedKeywordLoc().isValid())
1530      if (getQualifierLoc())
1531        return SourceRange(getElaboratedKeywordLoc(),
1532                           getQualifierLoc().getEndLoc());
1533      else
1534        return SourceRange(getElaboratedKeywordLoc());
1535    else
1536      return getQualifierLoc().getSourceRange();
1537  }
1538
1539  void initializeLocal(ASTContext &Context, SourceLocation Loc);
1540
1541  TypeLoc getNamedTypeLoc() const {
1542    return getInnerTypeLoc();
1543  }
1544
1545  QualType getInnerType() const {
1546    return getTypePtr()->getNamedType();
1547  }
1548
1549  void copy(ElaboratedTypeLoc Loc) {
1550    unsigned size = getFullDataSize();
1551    assert(size == Loc.getFullDataSize());
1552    memcpy(Data, Loc.Data, size);
1553  }
1554};
1555
1556// This is exactly the structure of an ElaboratedTypeLoc whose inner
1557// type is some sort of TypeDeclTypeLoc.
1558struct DependentNameLocInfo : ElaboratedLocInfo {
1559  SourceLocation NameLoc;
1560};
1561
1562class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1563                                                    DependentNameTypeLoc,
1564                                                    DependentNameType,
1565                                                    DependentNameLocInfo> {
1566public:
1567  SourceLocation getElaboratedKeywordLoc() const {
1568    return this->getLocalData()->ElaboratedKWLoc;
1569  }
1570  void setElaboratedKeywordLoc(SourceLocation Loc) {
1571    this->getLocalData()->ElaboratedKWLoc = Loc;
1572  }
1573
1574  NestedNameSpecifierLoc getQualifierLoc() const {
1575    return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
1576                                  getLocalData()->QualifierData);
1577  }
1578
1579  void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
1580    assert(QualifierLoc.getNestedNameSpecifier()
1581                                            == getTypePtr()->getQualifier() &&
1582           "Inconsistent nested-name-specifier pointer");
1583    getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
1584  }
1585
1586  SourceLocation getNameLoc() const {
1587    return this->getLocalData()->NameLoc;
1588  }
1589  void setNameLoc(SourceLocation Loc) {
1590    this->getLocalData()->NameLoc = Loc;
1591  }
1592
1593  SourceRange getLocalSourceRange() const {
1594    if (getElaboratedKeywordLoc().isValid())
1595      return SourceRange(getElaboratedKeywordLoc(), getNameLoc());
1596    else
1597      return SourceRange(getQualifierLoc().getBeginLoc(), getNameLoc());
1598  }
1599
1600  void copy(DependentNameTypeLoc Loc) {
1601    unsigned size = getFullDataSize();
1602    assert(size == Loc.getFullDataSize());
1603    memcpy(Data, Loc.Data, size);
1604  }
1605
1606  void initializeLocal(ASTContext &Context, SourceLocation Loc);
1607};
1608
1609struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo {
1610  SourceLocation TemplateKWLoc;
1611  SourceLocation LAngleLoc;
1612  SourceLocation RAngleLoc;
1613  // followed by a TemplateArgumentLocInfo[]
1614};
1615
1616class DependentTemplateSpecializationTypeLoc :
1617    public ConcreteTypeLoc<UnqualTypeLoc,
1618                           DependentTemplateSpecializationTypeLoc,
1619                           DependentTemplateSpecializationType,
1620                           DependentTemplateSpecializationLocInfo> {
1621public:
1622  SourceLocation getElaboratedKeywordLoc() const {
1623    return this->getLocalData()->ElaboratedKWLoc;
1624  }
1625  void setElaboratedKeywordLoc(SourceLocation Loc) {
1626    this->getLocalData()->ElaboratedKWLoc = Loc;
1627  }
1628
1629  NestedNameSpecifierLoc getQualifierLoc() const {
1630    if (!getLocalData()->QualifierData)
1631      return NestedNameSpecifierLoc();
1632
1633    return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
1634                                  getLocalData()->QualifierData);
1635  }
1636
1637  void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
1638    if (!QualifierLoc) {
1639      // Even if we have a nested-name-specifier in the dependent
1640      // template specialization type, we won't record the nested-name-specifier
1641      // location information when this type-source location information is
1642      // part of a nested-name-specifier.
1643      getLocalData()->QualifierData = 0;
1644      return;
1645    }
1646
1647    assert(QualifierLoc.getNestedNameSpecifier()
1648                                        == getTypePtr()->getQualifier() &&
1649           "Inconsistent nested-name-specifier pointer");
1650    getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
1651  }
1652
1653  SourceLocation getTemplateKeywordLoc() const {
1654    return getLocalData()->TemplateKWLoc;
1655  }
1656  void setTemplateKeywordLoc(SourceLocation Loc) {
1657    getLocalData()->TemplateKWLoc = Loc;
1658  }
1659
1660  SourceLocation getTemplateNameLoc() const {
1661    return this->getLocalData()->NameLoc;
1662  }
1663  void setTemplateNameLoc(SourceLocation Loc) {
1664    this->getLocalData()->NameLoc = Loc;
1665  }
1666
1667  SourceLocation getLAngleLoc() const {
1668    return this->getLocalData()->LAngleLoc;
1669  }
1670  void setLAngleLoc(SourceLocation Loc) {
1671    this->getLocalData()->LAngleLoc = Loc;
1672  }
1673
1674  SourceLocation getRAngleLoc() const {
1675    return this->getLocalData()->RAngleLoc;
1676  }
1677  void setRAngleLoc(SourceLocation Loc) {
1678    this->getLocalData()->RAngleLoc = Loc;
1679  }
1680
1681  unsigned getNumArgs() const {
1682    return getTypePtr()->getNumArgs();
1683  }
1684
1685  void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
1686    getArgInfos()[i] = AI;
1687  }
1688  TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
1689    return getArgInfos()[i];
1690  }
1691
1692  TemplateArgumentLoc getArgLoc(unsigned i) const {
1693    return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
1694  }
1695
1696  SourceRange getLocalSourceRange() const {
1697    if (getElaboratedKeywordLoc().isValid())
1698      return SourceRange(getElaboratedKeywordLoc(), getRAngleLoc());
1699    else if (getQualifierLoc())
1700      return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc());
1701    else if (getTemplateKeywordLoc().isValid())
1702      return SourceRange(getTemplateKeywordLoc(), getRAngleLoc());
1703    else
1704      return SourceRange(getTemplateNameLoc(), getRAngleLoc());
1705  }
1706
1707  void copy(DependentTemplateSpecializationTypeLoc Loc) {
1708    unsigned size = getFullDataSize();
1709    assert(size == Loc.getFullDataSize());
1710    memcpy(Data, Loc.Data, size);
1711  }
1712
1713  void initializeLocal(ASTContext &Context, SourceLocation Loc);
1714
1715  unsigned getExtraLocalDataSize() const {
1716    return getNumArgs() * sizeof(TemplateArgumentLocInfo);
1717  }
1718
1719private:
1720  TemplateArgumentLocInfo *getArgInfos() const {
1721    return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
1722  }
1723};
1724
1725
1726struct PackExpansionTypeLocInfo {
1727  SourceLocation EllipsisLoc;
1728};
1729
1730class PackExpansionTypeLoc
1731  : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc,
1732                           PackExpansionType, PackExpansionTypeLocInfo> {
1733public:
1734  SourceLocation getEllipsisLoc() const {
1735    return this->getLocalData()->EllipsisLoc;
1736  }
1737
1738  void setEllipsisLoc(SourceLocation Loc) {
1739    this->getLocalData()->EllipsisLoc = Loc;
1740  }
1741
1742  SourceRange getLocalSourceRange() const {
1743    return SourceRange(getEllipsisLoc(), getEllipsisLoc());
1744  }
1745
1746  void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1747    setEllipsisLoc(Loc);
1748  }
1749
1750  TypeLoc getPatternLoc() const {
1751    return getInnerTypeLoc();
1752  }
1753
1754  QualType getInnerType() const {
1755    return this->getTypePtr()->getPattern();
1756  }
1757};
1758
1759struct AtomicTypeLocInfo {
1760  SourceLocation KWLoc, LParenLoc, RParenLoc;
1761};
1762
1763class AtomicTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AtomicTypeLoc,
1764                                             AtomicType, AtomicTypeLocInfo> {
1765public:
1766  TypeLoc getValueLoc() const {
1767    return this->getInnerTypeLoc();
1768  }
1769
1770  SourceRange getLocalSourceRange() const {
1771    return SourceRange(getKWLoc(), getRParenLoc());
1772  }
1773
1774  SourceLocation getKWLoc() const {
1775    return this->getLocalData()->KWLoc;
1776  }
1777  void setKWLoc(SourceLocation Loc) {
1778    this->getLocalData()->KWLoc = Loc;
1779  }
1780
1781  SourceLocation getLParenLoc() const {
1782    return this->getLocalData()->LParenLoc;
1783  }
1784  void setLParenLoc(SourceLocation Loc) {
1785    this->getLocalData()->LParenLoc = Loc;
1786  }
1787
1788  SourceLocation getRParenLoc() const {
1789    return this->getLocalData()->RParenLoc;
1790  }
1791  void setRParenLoc(SourceLocation Loc) {
1792    this->getLocalData()->RParenLoc = Loc;
1793  }
1794
1795  SourceRange getParensRange() const {
1796    return SourceRange(getLParenLoc(), getRParenLoc());
1797  }
1798  void setParensRange(SourceRange Range) {
1799    setLParenLoc(Range.getBegin());
1800    setRParenLoc(Range.getEnd());
1801  }
1802
1803  void initializeLocal(ASTContext &Context, SourceLocation Loc) {
1804    setKWLoc(Loc);
1805    setLParenLoc(Loc);
1806    setRParenLoc(Loc);
1807  }
1808
1809  QualType getInnerType() const {
1810    return this->getTypePtr()->getValueType();
1811  }
1812};
1813
1814
1815}
1816
1817#endif
1818