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