TypeLoc.h revision ef012445d431eb51de6ce033e117106624a1dc73
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 ParmVarDecl;
24  class TypeSourceInfo;
25  class UnqualTypeLoc;
26
27// Predeclare all the type nodes.
28#define ABSTRACT_TYPELOC(Class, Base)
29#define TYPELOC(Class, Base) \
30  class Class##TypeLoc;
31#include "clang/AST/TypeLocNodes.def"
32
33/// \brief Base wrapper for a particular "section" of type source info.
34///
35/// A client should use the TypeLoc subclasses through cast/dyn_cast in order to
36/// get at the actual information.
37class TypeLoc {
38protected:
39  // The correctness of this relies on the property that, for Type *Ty,
40  //   QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty
41  void *Ty;
42  void *Data;
43
44public:
45  /// The kinds of TypeLocs.  Equivalent to the Type::TypeClass enum,
46  /// except it also defines a Qualified enum that corresponds to the
47  /// QualifiedLoc class.
48  enum TypeLocClass {
49#define ABSTRACT_TYPE(Class, Base)
50#define TYPE(Class, Base) \
51    Class = Type::Class,
52#include "clang/AST/TypeNodes.def"
53    Qualified
54  };
55
56  TypeLoc() : Ty(0), Data(0) { }
57  TypeLoc(QualType ty, void *opaqueData)
58    : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { }
59  TypeLoc(Type *ty, void *opaqueData)
60    : Ty(ty), Data(opaqueData) { }
61
62  TypeLocClass getTypeLocClass() const {
63    if (getType().hasLocalQualifiers()) return Qualified;
64    return (TypeLocClass) getType()->getTypeClass();
65  }
66
67  bool isNull() const { return !Ty; }
68  operator bool() const { return Ty; }
69
70  /// \brief Returns the size of type source info data block for the given type.
71  static unsigned getFullDataSizeForType(QualType Ty);
72
73  /// \brief Get the type for which this source info wrapper provides
74  /// information.
75  QualType getType() const {
76    return QualType::getFromOpaquePtr(Ty);
77  }
78
79  Type *getTypePtr() const {
80    return QualType::getFromOpaquePtr(Ty).getTypePtr();
81  }
82
83  /// \brief Get the pointer where source information is stored.
84  void *getOpaqueData() const {
85    return Data;
86  }
87
88  /// \brief Get the full source range.
89  SourceRange getFullSourceRange() const {
90    SourceLocation End = getSourceRange().getEnd();
91    TypeLoc Cur = *this;
92    while (true) {
93      TypeLoc Next = Cur.getNextTypeLoc();
94      if (Next.isNull()) break;
95      Cur = Next;
96    }
97    return SourceRange(Cur.getSourceRange().getBegin(), End);
98  }
99
100  /// \brief Get the local source range.
101  SourceRange getSourceRange() const {
102    return getSourceRangeImpl(*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  /// \brief Initializes this to state that every location in this
120  /// type is the given location.
121  ///
122  /// This method exists to provide a simple transition for code that
123  /// relies on location-less types.
124  void initialize(SourceLocation Loc) const {
125    initializeImpl(*this, Loc);
126  }
127
128  friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) {
129    return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data;
130  }
131
132  friend bool operator!=(const TypeLoc &LHS, const TypeLoc &RHS) {
133    return !(LHS == RHS);
134  }
135
136  static bool classof(const TypeLoc *TL) { return true; }
137
138private:
139  static void initializeImpl(TypeLoc TL, SourceLocation Loc);
140  static TypeLoc getNextTypeLocImpl(TypeLoc TL);
141  static SourceRange getSourceRangeImpl(TypeLoc TL);
142};
143
144/// \brief Return the TypeLoc for a type source info.
145inline TypeLoc TypeSourceInfo::getTypeLoc() const {
146  return TypeLoc(Ty, (void*)(this + 1));
147}
148
149/// \brief Wrapper of type source information for a type with
150/// no direct quqlaifiers.
151class UnqualTypeLoc : public TypeLoc {
152public:
153  UnqualTypeLoc() {}
154  UnqualTypeLoc(Type *Ty, void *Data) : TypeLoc(Ty, Data) {}
155
156  Type *getTypePtr() const {
157    return reinterpret_cast<Type*>(Ty);
158  }
159
160  TypeLocClass getTypeLocClass() const {
161    return (TypeLocClass) getTypePtr()->getTypeClass();
162  }
163
164  static bool classof(const TypeLoc *TL) {
165    return !TL->getType().hasLocalQualifiers();
166  }
167  static bool classof(const UnqualTypeLoc *TL) { return true; }
168};
169
170/// \brief Wrapper of type source information for a type with
171/// non-trivial direct qualifiers.
172///
173/// Currently, we intentionally do not provide source location for
174/// type qualifiers.
175class QualifiedTypeLoc : public TypeLoc {
176public:
177  SourceRange getSourceRange() const {
178    return SourceRange();
179  }
180
181  UnqualTypeLoc getUnqualifiedLoc() const {
182    return UnqualTypeLoc(getTypePtr(), Data);
183  }
184
185  /// Initializes the local data of this type source info block to
186  /// provide no information.
187  void initializeLocal(SourceLocation Loc) {
188    // do nothing
189  }
190
191  TypeLoc getNextTypeLoc() const {
192    return getUnqualifiedLoc();
193  }
194
195  /// \brief Returns the size of the type source info data block that is
196  /// specific to this type.
197  unsigned getLocalDataSize() const {
198    // In fact, we don't currently preserve any location information
199    // for qualifiers.
200    return 0;
201  }
202
203  /// \brief Returns the size of the type source info data block.
204  unsigned getFullDataSize() const {
205    return getLocalDataSize() +
206      getFullDataSizeForType(getType().getLocalUnqualifiedType());
207  }
208
209  static bool classof(const TypeLoc *TL) {
210    return TL->getType().hasLocalQualifiers();
211  }
212  static bool classof(const QualifiedTypeLoc *TL) { return true; }
213};
214
215inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const {
216  if (isa<QualifiedTypeLoc>(this))
217    return cast<QualifiedTypeLoc>(this)->getUnqualifiedLoc();
218  return cast<UnqualTypeLoc>(*this);
219}
220
221/// A metaprogramming base class for TypeLoc classes which correspond
222/// to a particular Type subclass.  It is accepted for a single
223/// TypeLoc class to correspond to multiple Type classes.
224///
225/// \param Base a class from which to derive
226/// \param Derived the class deriving from this one
227/// \param TypeClass the concrete Type subclass associated with this
228///   location type
229/// \param LocalData the structure type of local location data for
230///   this type
231///
232/// sizeof(LocalData) needs to be a multiple of sizeof(void*) or
233/// else the world will end.
234///
235/// TypeLocs with non-constant amounts of local data should override
236/// getExtraLocalDataSize(); getExtraLocalData() will then point to
237/// this extra memory.
238///
239/// TypeLocs with an inner type should define
240///   QualType getInnerType() const
241/// and getInnerTypeLoc() will then point to this inner type's
242/// location data.
243///
244/// A word about hierarchies: this template is not designed to be
245/// derived from multiple times in a hierarchy.  It is also not
246/// designed to be used for classes where subtypes might provide
247/// different amounts of source information.  It should be subclassed
248/// only at the deepest portion of the hierarchy where all children
249/// have identical source information; if that's an abstract type,
250/// then further descendents should inherit from
251/// InheritingConcreteTypeLoc instead.
252template <class Base, class Derived, class TypeClass, class LocalData>
253class ConcreteTypeLoc : public Base {
254
255  const Derived *asDerived() const {
256    return static_cast<const Derived*>(this);
257  }
258
259public:
260  unsigned getLocalDataSize() const {
261    return sizeof(LocalData) + asDerived()->getExtraLocalDataSize();
262  }
263  // Give a default implementation that's useful for leaf types.
264  unsigned getFullDataSize() const {
265    return asDerived()->getLocalDataSize() + getInnerTypeSize();
266  }
267
268  static bool classofType(const Type *Ty) {
269    return TypeClass::classof(Ty);
270  }
271
272  static bool classof(const TypeLoc *TL) {
273    return Derived::classofType(TL->getTypePtr());
274  }
275  static bool classof(const UnqualTypeLoc *TL) {
276    return Derived::classofType(TL->getTypePtr());
277  }
278  static bool classof(const Derived *TL) {
279    return true;
280  }
281
282  TypeLoc getNextTypeLoc() const {
283    return getNextTypeLoc(asDerived()->getInnerType());
284  }
285
286  TypeClass *getTypePtr() const {
287    return cast<TypeClass>(Base::getTypePtr());
288  }
289
290protected:
291  unsigned getExtraLocalDataSize() const {
292    return 0;
293  }
294
295  LocalData *getLocalData() const {
296    return static_cast<LocalData*>(Base::Data);
297  }
298
299  /// Gets a pointer past the Info structure; useful for classes with
300  /// local data that can't be captured in the Info (e.g. because it's
301  /// of variable size).
302  void *getExtraLocalData() const {
303    return getLocalData() + 1;
304  }
305
306  void *getNonLocalData() const {
307    return static_cast<char*>(Base::Data) + asDerived()->getLocalDataSize();
308  }
309
310  struct HasNoInnerType {};
311  HasNoInnerType getInnerType() const { return HasNoInnerType(); }
312
313  TypeLoc getInnerTypeLoc() const {
314    return TypeLoc(asDerived()->getInnerType(), getNonLocalData());
315  }
316
317private:
318  unsigned getInnerTypeSize() const {
319    return getInnerTypeSize(asDerived()->getInnerType());
320  }
321
322  unsigned getInnerTypeSize(HasNoInnerType _) const {
323    return 0;
324  }
325
326  unsigned getInnerTypeSize(QualType _) const {
327    return getInnerTypeLoc().getFullDataSize();
328  }
329
330  TypeLoc getNextTypeLoc(HasNoInnerType _) const {
331    return TypeLoc();
332  }
333
334  TypeLoc getNextTypeLoc(QualType T) const {
335    return TypeLoc(T, getNonLocalData());
336  }
337};
338
339/// A metaprogramming class designed for concrete subtypes of abstract
340/// types where all subtypes share equivalently-structured source
341/// information.  See the note on ConcreteTypeLoc.
342template <class Base, class Derived, class TypeClass>
343class InheritingConcreteTypeLoc : public Base {
344public:
345  static bool classof(const TypeLoc *TL) {
346    return Derived::classofType(TL->getTypePtr());
347  }
348  static bool classof(const UnqualTypeLoc *TL) {
349    return Derived::classofType(TL->getTypePtr());
350  }
351  static bool classof(const Derived *TL) {
352    return true;
353  }
354
355  TypeClass *getTypePtr() const {
356    return cast<TypeClass>(Base::getTypePtr());
357  }
358};
359
360
361struct TypeSpecLocInfo {
362  SourceLocation NameLoc;
363};
364
365/// \brief A reasonable base class for TypeLocs that correspond to
366/// types that are written as a type-specifier.
367class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
368                                               TypeSpecTypeLoc,
369                                               Type,
370                                               TypeSpecLocInfo> {
371public:
372  enum { LocalDataSize = sizeof(TypeSpecLocInfo) };
373
374  SourceLocation getNameLoc() const {
375    return this->getLocalData()->NameLoc;
376  }
377  void setNameLoc(SourceLocation Loc) {
378    this->getLocalData()->NameLoc = Loc;
379  }
380  SourceRange getSourceRange() const {
381    return SourceRange(getNameLoc(), getNameLoc());
382  }
383  void initializeLocal(SourceLocation Loc) {
384    setNameLoc(Loc);
385  }
386
387  static bool classof(const TypeLoc *TL);
388  static bool classof(const TypeSpecTypeLoc *TL) { return true; }
389};
390
391
392struct BuiltinLocInfo {
393  SourceLocation BuiltinLoc;
394};
395
396/// \brief Wrapper for source info for builtin types.
397class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
398                                              BuiltinTypeLoc,
399                                              BuiltinType,
400                                              BuiltinLocInfo> {
401public:
402  enum { LocalDataSize = sizeof(BuiltinLocInfo) };
403
404  SourceLocation getBuiltinLoc() const {
405    return getLocalData()->BuiltinLoc;
406  }
407  void setBuiltinLoc(SourceLocation Loc) {
408    getLocalData()->BuiltinLoc = Loc;
409  }
410
411  SourceLocation getNameLoc() const { return getBuiltinLoc(); }
412
413  WrittenBuiltinSpecs& getWrittenBuiltinSpecs() {
414    return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData()));
415  }
416  const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
417    return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData()));
418  }
419
420  bool needsExtraLocalData() const {
421    BuiltinType::Kind bk = getTypePtr()->getKind();
422    return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128)
423      || (bk >= BuiltinType::Short && bk <= BuiltinType::LongDouble)
424      || bk == BuiltinType::UChar
425      || bk == BuiltinType::SChar;
426  }
427
428  unsigned getExtraLocalDataSize() const {
429    return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0;
430  }
431
432  SourceRange getSourceRange() const {
433    return SourceRange(getBuiltinLoc(), getBuiltinLoc());
434  }
435
436  TypeSpecifierSign getWrittenSignSpec() const {
437    if (needsExtraLocalData())
438      return static_cast<TypeSpecifierSign>(getWrittenBuiltinSpecs().Sign);
439    else
440      return TSS_unspecified;
441  }
442  bool hasWrittenSignSpec() const {
443    return getWrittenSignSpec() != TSS_unspecified;
444  }
445  void setWrittenSignSpec(TypeSpecifierSign written) {
446    if (needsExtraLocalData())
447      getWrittenBuiltinSpecs().Sign = written;
448  }
449
450  TypeSpecifierWidth getWrittenWidthSpec() const {
451    if (needsExtraLocalData())
452      return static_cast<TypeSpecifierWidth>(getWrittenBuiltinSpecs().Width);
453    else
454      return TSW_unspecified;
455  }
456  bool hasWrittenWidthSpec() const {
457    return getWrittenWidthSpec() != TSW_unspecified;
458  }
459  void setWrittenWidthSpec(TypeSpecifierWidth written) {
460    if (needsExtraLocalData())
461      getWrittenBuiltinSpecs().Width = written;
462  }
463
464  TypeSpecifierType getWrittenTypeSpec() const;
465  bool hasWrittenTypeSpec() const {
466    return getWrittenTypeSpec() != TST_unspecified;
467  }
468  void setWrittenTypeSpec(TypeSpecifierType written) {
469    if (needsExtraLocalData())
470      getWrittenBuiltinSpecs().Type = written;
471  }
472
473  bool hasModeAttr() const {
474    if (needsExtraLocalData())
475      return getWrittenBuiltinSpecs().ModeAttr;
476    else
477      return false;
478  }
479  void setModeAttr(bool written) {
480    if (needsExtraLocalData())
481      getWrittenBuiltinSpecs().ModeAttr = written;
482  }
483
484  void initializeLocal(SourceLocation Loc) {
485    setBuiltinLoc(Loc);
486    if (needsExtraLocalData()) {
487      WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs();
488      wbs.Sign = TSS_unspecified;
489      wbs.Width = TSW_unspecified;
490      wbs.Type = TST_unspecified;
491      wbs.ModeAttr = false;
492    }
493  }
494};
495
496
497/// \brief Wrapper for source info for typedefs.
498class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
499                                                        TypedefTypeLoc,
500                                                        TypedefType> {
501public:
502  TypedefDecl *getTypedefDecl() const {
503    return getTypePtr()->getDecl();
504  }
505};
506
507/// \brief Wrapper for source info for injected class names of class
508/// templates.
509class InjectedClassNameTypeLoc :
510    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
511                                     InjectedClassNameTypeLoc,
512                                     InjectedClassNameType> {
513};
514
515/// \brief Wrapper for source info for unresolved typename using decls.
516class UnresolvedUsingTypeLoc :
517    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
518                                     UnresolvedUsingTypeLoc,
519                                     UnresolvedUsingType> {
520public:
521  UnresolvedUsingTypenameDecl *getDecl() const {
522    return getTypePtr()->getDecl();
523  }
524};
525
526/// \brief Wrapper for source info for tag types.  Note that this only
527/// records source info for the name itself; a type written 'struct foo'
528/// should be represented as an ElaboratedTypeLoc.  We currently
529/// only do that when C++ is enabled because of the expense of
530/// creating an ElaboratedType node for so many type references in C.
531class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
532                                                    TagTypeLoc,
533                                                    TagType> {
534public:
535  TagDecl *getDecl() const { return getTypePtr()->getDecl(); }
536};
537
538/// \brief Wrapper for source info for record types.
539class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
540                                                       RecordTypeLoc,
541                                                       RecordType> {
542public:
543  RecordDecl *getDecl() const { return getTypePtr()->getDecl(); }
544};
545
546/// \brief Wrapper for source info for enum types.
547class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
548                                                     EnumTypeLoc,
549                                                     EnumType> {
550public:
551  EnumDecl *getDecl() const { return getTypePtr()->getDecl(); }
552};
553
554/// \brief Wrapper for template type parameters.
555class TemplateTypeParmTypeLoc :
556    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
557                                     TemplateTypeParmTypeLoc,
558                                     TemplateTypeParmType> {
559};
560
561/// \brief Wrapper for substituted template type parameters.
562class SubstTemplateTypeParmTypeLoc :
563    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
564                                     SubstTemplateTypeParmTypeLoc,
565                                     SubstTemplateTypeParmType> {
566};
567
568
569struct ObjCProtocolListLocInfo {
570  SourceLocation LAngleLoc;
571  SourceLocation RAngleLoc;
572};
573
574// A helper class for defining ObjC TypeLocs that can qualified with
575// protocols.
576//
577// TypeClass basically has to be either ObjCInterfaceType or
578// ObjCObjectPointerType.
579template <class Derived, class TypeClass, class LocalData>
580class ObjCProtocolListTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
581                                                       Derived,
582                                                       TypeClass,
583                                                       LocalData> {
584  // SourceLocations are stored after Info, one for each Protocol.
585  SourceLocation *getProtocolLocArray() const {
586    return (SourceLocation*) this->getExtraLocalData();
587  }
588
589protected:
590  void initializeLocalBase(SourceLocation Loc) {
591    setLAngleLoc(Loc);
592    setRAngleLoc(Loc);
593    for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
594      setProtocolLoc(i, Loc);
595  }
596
597public:
598  SourceLocation getLAngleLoc() const {
599    return this->getLocalData()->LAngleLoc;
600  }
601  void setLAngleLoc(SourceLocation Loc) {
602    this->getLocalData()->LAngleLoc = Loc;
603  }
604
605  SourceLocation getRAngleLoc() const {
606    return this->getLocalData()->RAngleLoc;
607  }
608  void setRAngleLoc(SourceLocation Loc) {
609    this->getLocalData()->RAngleLoc = Loc;
610  }
611
612  unsigned getNumProtocols() const {
613    return this->getTypePtr()->getNumProtocols();
614  }
615
616  SourceLocation getProtocolLoc(unsigned i) const {
617    assert(i < getNumProtocols() && "Index is out of bounds!");
618    return getProtocolLocArray()[i];
619  }
620  void setProtocolLoc(unsigned i, SourceLocation Loc) {
621    assert(i < getNumProtocols() && "Index is out of bounds!");
622    getProtocolLocArray()[i] = Loc;
623  }
624
625  ObjCProtocolDecl *getProtocol(unsigned i) const {
626    assert(i < getNumProtocols() && "Index is out of bounds!");
627    return *(this->getTypePtr()->qual_begin() + i);
628  }
629
630  SourceRange getSourceRange() const {
631    return SourceRange(getLAngleLoc(), getRAngleLoc());
632  }
633
634  void initializeLocal(SourceLocation Loc) {
635    initializeLocalBase(Loc);
636  }
637
638  unsigned getExtraLocalDataSize() const {
639    return this->getNumProtocols() * sizeof(SourceLocation);
640  }
641};
642
643
644struct ObjCInterfaceLocInfo : ObjCProtocolListLocInfo {
645  SourceLocation NameLoc;
646};
647
648/// \brief Wrapper for source info for ObjC interfaces.
649class ObjCInterfaceTypeLoc :
650    public ObjCProtocolListTypeLoc<ObjCInterfaceTypeLoc,
651                                   ObjCInterfaceType,
652                                   ObjCInterfaceLocInfo> {
653public:
654  ObjCInterfaceDecl *getIFaceDecl() const {
655    return getTypePtr()->getDecl();
656  }
657
658  SourceLocation getNameLoc() const {
659    return getLocalData()->NameLoc;
660  }
661
662  void setNameLoc(SourceLocation Loc) {
663    getLocalData()->NameLoc = Loc;
664  }
665
666  SourceRange getSourceRange() const {
667    if (getNumProtocols())
668      return SourceRange(getNameLoc(), getRAngleLoc());
669    else
670      return SourceRange(getNameLoc(), getNameLoc());
671  }
672
673  void initializeLocal(SourceLocation Loc) {
674    initializeLocalBase(Loc);
675    setNameLoc(Loc);
676  }
677};
678
679
680struct ObjCObjectPointerLocInfo : ObjCProtocolListLocInfo {
681  SourceLocation StarLoc;
682  bool HasProtocols;
683  bool HasBaseType;
684};
685
686/// Wraps an ObjCPointerType with source location information.  Note
687/// that not all ObjCPointerTypes actually have a star location; nor
688/// are protocol locations necessarily written in the source just
689/// because they're present on the type.
690class ObjCObjectPointerTypeLoc :
691    public ObjCProtocolListTypeLoc<ObjCObjectPointerTypeLoc,
692                                   ObjCObjectPointerType,
693                                   ObjCObjectPointerLocInfo> {
694public:
695  bool hasProtocolsAsWritten() const {
696    return getLocalData()->HasProtocols;
697  }
698
699  void setHasProtocolsAsWritten(bool HasProtocols) {
700    getLocalData()->HasProtocols = HasProtocols;
701  }
702
703  bool hasBaseTypeAsWritten() const {
704    return getLocalData()->HasBaseType;
705  }
706
707  void setHasBaseTypeAsWritten(bool HasBaseType) {
708    getLocalData()->HasBaseType = HasBaseType;
709  }
710
711  SourceLocation getStarLoc() const {
712    return getLocalData()->StarLoc;
713  }
714
715  void setStarLoc(SourceLocation Loc) {
716    getLocalData()->StarLoc = Loc;
717  }
718
719  SourceRange getSourceRange() const {
720    // Being written with protocols is incompatible with being written
721    // with a star.
722    if (hasProtocolsAsWritten())
723      return SourceRange(getLAngleLoc(), getRAngleLoc());
724    else
725      return SourceRange(getStarLoc(), getStarLoc());
726  }
727
728  void initializeLocal(SourceLocation Loc) {
729    initializeLocalBase(Loc);
730    setHasProtocolsAsWritten(false);
731    setHasBaseTypeAsWritten(false);
732    setStarLoc(Loc);
733  }
734
735  TypeLoc getBaseTypeLoc() const {
736    return getInnerTypeLoc();
737  }
738
739  QualType getInnerType() const {
740    return getTypePtr()->getPointeeType();
741  }
742};
743
744
745struct PointerLikeLocInfo {
746  SourceLocation StarLoc;
747};
748
749/// A base class for
750template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo>
751class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived,
752                                                  TypeClass, LocalData> {
753public:
754  SourceLocation getSigilLoc() const {
755    return this->getLocalData()->StarLoc;
756  }
757  void setSigilLoc(SourceLocation Loc) {
758    this->getLocalData()->StarLoc = Loc;
759  }
760
761  TypeLoc getPointeeLoc() const {
762    return this->getInnerTypeLoc();
763  }
764
765  SourceRange getSourceRange() const {
766    return SourceRange(getSigilLoc(), getSigilLoc());
767  }
768
769  void initializeLocal(SourceLocation Loc) {
770    setSigilLoc(Loc);
771  }
772
773  QualType getInnerType() const {
774    return this->getTypePtr()->getPointeeType();
775  }
776};
777
778
779/// \brief Wrapper for source info for pointers.
780class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc,
781                                                 PointerType> {
782public:
783  SourceLocation getStarLoc() const {
784    return getSigilLoc();
785  }
786  void setStarLoc(SourceLocation Loc) {
787    setSigilLoc(Loc);
788  }
789};
790
791
792/// \brief Wrapper for source info for block pointers.
793class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
794                                                      BlockPointerType> {
795public:
796  SourceLocation getCaretLoc() const {
797    return getSigilLoc();
798  }
799  void setCaretLoc(SourceLocation Loc) {
800    setSigilLoc(Loc);
801  }
802};
803
804
805/// \brief Wrapper for source info for member pointers.
806class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
807                                                       MemberPointerType> {
808public:
809  SourceLocation getStarLoc() const {
810    return getSigilLoc();
811  }
812  void setStarLoc(SourceLocation Loc) {
813    setSigilLoc(Loc);
814  }
815};
816
817
818class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc,
819                                                   ReferenceType> {
820public:
821  QualType getInnerType() const {
822    return getTypePtr()->getPointeeTypeAsWritten();
823  }
824};
825
826class LValueReferenceTypeLoc :
827    public InheritingConcreteTypeLoc<ReferenceTypeLoc,
828                                     LValueReferenceTypeLoc,
829                                     LValueReferenceType> {
830public:
831  SourceLocation getAmpLoc() const {
832    return getSigilLoc();
833  }
834  void setAmpLoc(SourceLocation Loc) {
835    setSigilLoc(Loc);
836  }
837};
838
839class RValueReferenceTypeLoc :
840    public InheritingConcreteTypeLoc<ReferenceTypeLoc,
841                                     RValueReferenceTypeLoc,
842                                     RValueReferenceType> {
843public:
844  SourceLocation getAmpAmpLoc() const {
845    return getSigilLoc();
846  }
847  void setAmpAmpLoc(SourceLocation Loc) {
848    setSigilLoc(Loc);
849  }
850};
851
852
853struct FunctionLocInfo {
854  SourceLocation LParenLoc, RParenLoc;
855};
856
857/// \brief Wrapper for source info for functions.
858class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
859                                               FunctionTypeLoc,
860                                               FunctionType,
861                                               FunctionLocInfo> {
862  // ParmVarDecls* are stored after Info, one for each argument.
863  ParmVarDecl **getParmArray() const {
864    return (ParmVarDecl**) getExtraLocalData();
865  }
866
867public:
868  SourceLocation getLParenLoc() const {
869    return getLocalData()->LParenLoc;
870  }
871  void setLParenLoc(SourceLocation Loc) {
872    getLocalData()->LParenLoc = Loc;
873  }
874
875  SourceLocation getRParenLoc() const {
876    return getLocalData()->RParenLoc;
877  }
878  void setRParenLoc(SourceLocation Loc) {
879    getLocalData()->RParenLoc = Loc;
880  }
881
882  unsigned getNumArgs() const {
883    if (isa<FunctionNoProtoType>(getTypePtr()))
884      return 0;
885    return cast<FunctionProtoType>(getTypePtr())->getNumArgs();
886  }
887  ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; }
888  void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; }
889
890  TypeLoc getResultLoc() const {
891    return getInnerTypeLoc();
892  }
893
894  SourceRange getSourceRange() const {
895    return SourceRange(getLParenLoc(), getRParenLoc());
896  }
897
898  void initializeLocal(SourceLocation Loc) {
899    setLParenLoc(Loc);
900    setRParenLoc(Loc);
901    for (unsigned i = 0, e = getNumArgs(); i != e; ++i)
902      setArg(i, NULL);
903  }
904
905  /// \brief Returns the size of the type source info data block that is
906  /// specific to this type.
907  unsigned getExtraLocalDataSize() const {
908    return getNumArgs() * sizeof(ParmVarDecl*);
909  }
910
911  QualType getInnerType() const { return getTypePtr()->getResultType(); }
912};
913
914class FunctionProtoTypeLoc :
915    public InheritingConcreteTypeLoc<FunctionTypeLoc,
916                                     FunctionProtoTypeLoc,
917                                     FunctionProtoType> {
918};
919
920class FunctionNoProtoTypeLoc :
921    public InheritingConcreteTypeLoc<FunctionTypeLoc,
922                                     FunctionNoProtoTypeLoc,
923                                     FunctionNoProtoType> {
924};
925
926
927struct ArrayLocInfo {
928  SourceLocation LBracketLoc, RBracketLoc;
929  Expr *Size;
930};
931
932/// \brief Wrapper for source info for arrays.
933class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
934                                            ArrayTypeLoc,
935                                            ArrayType,
936                                            ArrayLocInfo> {
937public:
938  SourceLocation getLBracketLoc() const {
939    return getLocalData()->LBracketLoc;
940  }
941  void setLBracketLoc(SourceLocation Loc) {
942    getLocalData()->LBracketLoc = Loc;
943  }
944
945  SourceLocation getRBracketLoc() const {
946    return getLocalData()->RBracketLoc;
947  }
948  void setRBracketLoc(SourceLocation Loc) {
949    getLocalData()->RBracketLoc = Loc;
950  }
951
952  SourceRange getBracketsRange() const {
953    return SourceRange(getLBracketLoc(), getRBracketLoc());
954  }
955
956  Expr *getSizeExpr() const {
957    return getLocalData()->Size;
958  }
959  void setSizeExpr(Expr *Size) {
960    getLocalData()->Size = Size;
961  }
962
963  TypeLoc getElementLoc() const {
964    return getInnerTypeLoc();
965  }
966
967  SourceRange getSourceRange() const {
968    return SourceRange(getLBracketLoc(), getRBracketLoc());
969  }
970
971  void initializeLocal(SourceLocation Loc) {
972    setLBracketLoc(Loc);
973    setRBracketLoc(Loc);
974    setSizeExpr(NULL);
975  }
976
977  QualType getInnerType() const { return getTypePtr()->getElementType(); }
978};
979
980class ConstantArrayTypeLoc :
981    public InheritingConcreteTypeLoc<ArrayTypeLoc,
982                                     ConstantArrayTypeLoc,
983                                     ConstantArrayType> {
984};
985
986class IncompleteArrayTypeLoc :
987    public InheritingConcreteTypeLoc<ArrayTypeLoc,
988                                     IncompleteArrayTypeLoc,
989                                     IncompleteArrayType> {
990};
991
992class DependentSizedArrayTypeLoc :
993    public InheritingConcreteTypeLoc<ArrayTypeLoc,
994                                     DependentSizedArrayTypeLoc,
995                                     DependentSizedArrayType> {
996
997};
998
999class VariableArrayTypeLoc :
1000    public InheritingConcreteTypeLoc<ArrayTypeLoc,
1001                                     VariableArrayTypeLoc,
1002                                     VariableArrayType> {
1003};
1004
1005
1006// Location information for a TemplateName.  Rudimentary for now.
1007struct TemplateNameLocInfo {
1008  SourceLocation NameLoc;
1009};
1010
1011struct TemplateSpecializationLocInfo : TemplateNameLocInfo {
1012  SourceLocation LAngleLoc;
1013  SourceLocation RAngleLoc;
1014};
1015
1016class TemplateSpecializationTypeLoc :
1017    public ConcreteTypeLoc<UnqualTypeLoc,
1018                           TemplateSpecializationTypeLoc,
1019                           TemplateSpecializationType,
1020                           TemplateSpecializationLocInfo> {
1021public:
1022  SourceLocation getLAngleLoc() const {
1023    return getLocalData()->LAngleLoc;
1024  }
1025  void setLAngleLoc(SourceLocation Loc) {
1026    getLocalData()->LAngleLoc = Loc;
1027  }
1028
1029  SourceLocation getRAngleLoc() const {
1030    return getLocalData()->RAngleLoc;
1031  }
1032  void setRAngleLoc(SourceLocation Loc) {
1033    getLocalData()->RAngleLoc = Loc;
1034  }
1035
1036  unsigned getNumArgs() const {
1037    return getTypePtr()->getNumArgs();
1038  }
1039  void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
1040#ifndef NDEBUG
1041    AI.validateForArgument(getTypePtr()->getArg(i));
1042#endif
1043    getArgInfos()[i] = AI;
1044  }
1045  TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
1046    return getArgInfos()[i];
1047  }
1048
1049  TemplateArgumentLoc getArgLoc(unsigned i) const {
1050    return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
1051  }
1052
1053  SourceLocation getTemplateNameLoc() const {
1054    return getLocalData()->NameLoc;
1055  }
1056  void setTemplateNameLoc(SourceLocation Loc) {
1057    getLocalData()->NameLoc = Loc;
1058  }
1059
1060  /// \brief - Copy the location information from the given info.
1061  void copy(TemplateSpecializationTypeLoc Loc) {
1062    unsigned size = getFullDataSize();
1063    assert(size == Loc.getFullDataSize());
1064
1065    // We're potentially copying Expr references here.  We don't
1066    // bother retaining them because TypeSourceInfos live forever, so
1067    // as long as the Expr was retained when originally written into
1068    // the TypeLoc, we're okay.
1069    memcpy(Data, Loc.Data, size);
1070  }
1071
1072  SourceRange getSourceRange() const {
1073    return SourceRange(getTemplateNameLoc(), getRAngleLoc());
1074  }
1075
1076  void initializeLocal(SourceLocation Loc) {
1077    setLAngleLoc(Loc);
1078    setRAngleLoc(Loc);
1079    setTemplateNameLoc(Loc);
1080
1081    for (unsigned i = 0, e = getNumArgs(); i != e; ++i) {
1082      TemplateArgumentLocInfo Info;
1083#ifndef NDEBUG
1084      // If asserts are enabled, be sure to initialize the argument
1085      // loc with the right kind of pointer.
1086      switch (getTypePtr()->getArg(i).getKind()) {
1087      case TemplateArgument::Expression:
1088      case TemplateArgument::Declaration:
1089        Info = TemplateArgumentLocInfo((Expr*) 0);
1090        break;
1091
1092      case TemplateArgument::Type:
1093        Info = TemplateArgumentLocInfo((TypeSourceInfo*) 0);
1094        break;
1095
1096      case TemplateArgument::Template:
1097        Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation());
1098        break;
1099
1100      case TemplateArgument::Integral:
1101      case TemplateArgument::Pack:
1102      case TemplateArgument::Null:
1103        // K_None is fine.
1104        break;
1105      }
1106#endif
1107      getArgInfos()[i] = Info;
1108    }
1109  }
1110
1111  unsigned getExtraLocalDataSize() const {
1112    return getNumArgs() * sizeof(TemplateArgumentLocInfo);
1113  }
1114
1115private:
1116  TemplateArgumentLocInfo *getArgInfos() const {
1117    return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
1118  }
1119};
1120
1121//===----------------------------------------------------------------------===//
1122//
1123//  All of these need proper implementations.
1124//
1125//===----------------------------------------------------------------------===//
1126
1127// FIXME: size expression and attribute locations (or keyword if we
1128// ever fully support altivec syntax).
1129class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1130                                                       VectorTypeLoc,
1131                                                       VectorType> {
1132};
1133
1134// FIXME: size expression and attribute locations.
1135class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc,
1136                                                          ExtVectorTypeLoc,
1137                                                          ExtVectorType> {
1138};
1139
1140// FIXME: attribute locations.
1141// For some reason, this isn't a subtype of VectorType.
1142class DependentSizedExtVectorTypeLoc :
1143    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1144                                     DependentSizedExtVectorTypeLoc,
1145                                     DependentSizedExtVectorType> {
1146};
1147
1148// FIXME: location of the '_Complex' keyword.
1149class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1150                                                        ComplexTypeLoc,
1151                                                        ComplexType> {
1152};
1153
1154struct TypeofLocInfo {
1155  SourceLocation TypeofLoc;
1156  SourceLocation LParenLoc;
1157  SourceLocation RParenLoc;
1158};
1159
1160struct TypeOfExprTypeLocInfo : public TypeofLocInfo {
1161};
1162
1163struct TypeOfTypeLocInfo : public TypeofLocInfo {
1164  TypeSourceInfo* UnderlyingTInfo;
1165};
1166
1167template <class Derived, class TypeClass, class LocalData = TypeofLocInfo>
1168class TypeofLikeTypeLoc
1169  : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> {
1170public:
1171  SourceLocation getTypeofLoc() const {
1172    return this->getLocalData()->TypeofLoc;
1173  }
1174  void setTypeofLoc(SourceLocation Loc) {
1175    this->getLocalData()->TypeofLoc = Loc;
1176  }
1177
1178  SourceLocation getLParenLoc() const {
1179    return this->getLocalData()->LParenLoc;
1180  }
1181  void setLParenLoc(SourceLocation Loc) {
1182    this->getLocalData()->LParenLoc = Loc;
1183  }
1184
1185  SourceLocation getRParenLoc() const {
1186    return this->getLocalData()->RParenLoc;
1187  }
1188  void setRParenLoc(SourceLocation Loc) {
1189    this->getLocalData()->RParenLoc = Loc;
1190  }
1191
1192  SourceRange getParensRange() const {
1193    return SourceRange(getLParenLoc(), getRParenLoc());
1194  }
1195  void setParensRange(SourceRange range) {
1196      setLParenLoc(range.getBegin());
1197      setRParenLoc(range.getEnd());
1198  }
1199
1200  SourceRange getSourceRange() const {
1201    return SourceRange(getTypeofLoc(), getRParenLoc());
1202  }
1203
1204  void initializeLocal(SourceLocation Loc) {
1205    setTypeofLoc(Loc);
1206    setLParenLoc(Loc);
1207    setRParenLoc(Loc);
1208  }
1209};
1210
1211class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc,
1212                                                   TypeOfExprType,
1213                                                   TypeOfExprTypeLocInfo> {
1214public:
1215  Expr* getUnderlyingExpr() const {
1216    return getTypePtr()->getUnderlyingExpr();
1217  }
1218  // Reimplemented to account for GNU/C++ extension
1219  //     typeof unary-expression
1220  // where there are no parentheses.
1221  SourceRange getSourceRange() const;
1222};
1223
1224class TypeOfTypeLoc
1225  : public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> {
1226public:
1227  QualType getUnderlyingType() const {
1228    return this->getTypePtr()->getUnderlyingType();
1229  }
1230  TypeSourceInfo* getUnderlyingTInfo() const {
1231    return this->getLocalData()->UnderlyingTInfo;
1232  }
1233  void setUnderlyingTInfo(TypeSourceInfo* TI) const {
1234    this->getLocalData()->UnderlyingTInfo = TI;
1235  }
1236};
1237
1238// FIXME: location of the 'decltype' and parens.
1239class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1240                                                         DecltypeTypeLoc,
1241                                                         DecltypeType> {
1242};
1243
1244// FIXME: locations for the nested name specifier should be put in
1245// NestedNameSpecifier
1246struct ElaboratedLocInfo {
1247  SourceLocation KeywordLoc;
1248};
1249
1250class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1251                                                 ElaboratedTypeLoc,
1252                                                 ElaboratedType,
1253                                                 ElaboratedLocInfo> {
1254public:
1255  SourceLocation getKeywordLoc() const {
1256    return this->getLocalData()->KeywordLoc;
1257  }
1258  void setKeywordLoc(SourceLocation Loc) {
1259    this->getLocalData()->KeywordLoc = Loc;
1260  }
1261
1262  SourceRange getSourceRange() const {
1263    return SourceRange(getKeywordLoc(), getKeywordLoc());
1264  }
1265
1266  void initializeLocal(SourceLocation Loc) {
1267    setKeywordLoc(Loc);
1268  }
1269
1270  TypeLoc getNamedTypeLoc() const {
1271    return getInnerTypeLoc();
1272  }
1273
1274  QualType getInnerType() const {
1275    return getTypePtr()->getNamedType();
1276  }
1277};
1278
1279// FIXME: locations for the nested name specifier should be put in
1280// NestedNameSpecifier
1281struct DependentNameLocInfo {
1282  SourceLocation KeywordLoc;
1283  SourceLocation NameLoc;
1284};
1285
1286class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
1287                                                    DependentNameTypeLoc,
1288                                                    DependentNameType,
1289                                                    DependentNameLocInfo> {
1290public:
1291  SourceLocation getKeywordLoc() const {
1292    return this->getLocalData()->KeywordLoc;
1293  }
1294  void setKeywordLoc(SourceLocation Loc) {
1295    this->getLocalData()->KeywordLoc = Loc;
1296  }
1297
1298  SourceLocation getNameLoc() const {
1299    return this->getLocalData()->NameLoc;
1300  }
1301  void setNameLoc(SourceLocation Loc) {
1302    this->getLocalData()->NameLoc = Loc;
1303  }
1304
1305  SourceRange getSourceRange() const {
1306    return SourceRange(getKeywordLoc(), getNameLoc());
1307  }
1308
1309  void initializeLocal(SourceLocation Loc) {
1310    setKeywordLoc(Loc);
1311    setNameLoc(Loc);
1312  }
1313};
1314
1315}
1316
1317#endif
1318