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