//===--- TypeLoc.h - Type Source Info Wrapper -------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the TypeLoc interface and subclasses. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_TYPELOC_H #define LLVM_CLANG_AST_TYPELOC_H #include "clang/AST/Decl.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/Specifiers.h" #include "llvm/Support/Compiler.h" namespace clang { class ASTContext; class ParmVarDecl; class TypeSourceInfo; class UnqualTypeLoc; // Predeclare all the type nodes. #define ABSTRACT_TYPELOC(Class, Base) #define TYPELOC(Class, Base) \ class Class##TypeLoc; #include "clang/AST/TypeLocNodes.def" /// \brief Base wrapper for a particular "section" of type source info. /// /// A client should use the TypeLoc subclasses through cast/dyn_cast in order to /// get at the actual information. class TypeLoc { protected: // The correctness of this relies on the property that, for Type *Ty, // QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty const void *Ty; void *Data; public: /// \brief Convert to the specified TypeLoc type, asserting that this TypeLoc /// is of the desired type. template T castAs() const { assert(T::isKind(*this)); T t; TypeLoc& tl = t; tl = *this; return t; } /// \brief Convert to the specified TypeLoc type, returning a null TypeLoc if /// this TypeLoc is not of the desired type. template T getAs() const { if (!T::isKind(*this)) return T(); T t; TypeLoc& tl = t; tl = *this; return t; } /// The kinds of TypeLocs. Equivalent to the Type::TypeClass enum, /// except it also defines a Qualified enum that corresponds to the /// QualifiedLoc class. enum TypeLocClass { #define ABSTRACT_TYPE(Class, Base) #define TYPE(Class, Base) \ Class = Type::Class, #include "clang/AST/TypeNodes.def" Qualified }; TypeLoc() : Ty(0), Data(0) { } TypeLoc(QualType ty, void *opaqueData) : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { } TypeLoc(const Type *ty, void *opaqueData) : Ty(ty), Data(opaqueData) { } TypeLocClass getTypeLocClass() const { if (getType().hasLocalQualifiers()) return Qualified; return (TypeLocClass) getType()->getTypeClass(); } bool isNull() const { return !Ty; } operator bool() const { return Ty; } /// \brief Returns the size of type source info data block for the given type. static unsigned getFullDataSizeForType(QualType Ty); /// \brief Get the type for which this source info wrapper provides /// information. QualType getType() const { return QualType::getFromOpaquePtr(Ty); } const Type *getTypePtr() const { return QualType::getFromOpaquePtr(Ty).getTypePtr(); } /// \brief Get the pointer where source information is stored. void *getOpaqueData() const { return Data; } /// \brief Get the begin source location. SourceLocation getBeginLoc() const; /// \brief Get the end source location. SourceLocation getEndLoc() const; /// \brief Get the full source range. SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getBeginLoc(), getEndLoc()); } SourceLocation getLocStart() const LLVM_READONLY { return getBeginLoc(); } SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } /// \brief Get the local source range. SourceRange getLocalSourceRange() const { return getLocalSourceRangeImpl(*this); } /// \brief Returns the size of the type source info data block. unsigned getFullDataSize() const { return getFullDataSizeForType(getType()); } /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the /// TypeLoc is a PointerLoc and next TypeLoc is for "int". TypeLoc getNextTypeLoc() const { return getNextTypeLocImpl(*this); } /// \brief Skips past any qualifiers, if this is qualified. UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header TypeLoc IgnoreParens() const; /// \brief Initializes this to state that every location in this /// type is the given location. /// /// This method exists to provide a simple transition for code that /// relies on location-less types. void initialize(ASTContext &Context, SourceLocation Loc) const { initializeImpl(Context, *this, Loc); } /// \brief Initializes this by copying its information from another /// TypeLoc of the same type. void initializeFullCopy(TypeLoc Other) const { assert(getType() == Other.getType()); size_t Size = getFullDataSize(); memcpy(getOpaqueData(), Other.getOpaqueData(), Size); } /// \brief Initializes this by copying its information from another /// TypeLoc of the same type. The given size must be the full data /// size. void initializeFullCopy(TypeLoc Other, unsigned Size) const { assert(getType() == Other.getType()); assert(getFullDataSize() == Size); memcpy(getOpaqueData(), Other.getOpaqueData(), Size); } friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) { return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data; } friend bool operator!=(const TypeLoc &LHS, const TypeLoc &RHS) { return !(LHS == RHS); } private: static bool isKind(const TypeLoc&) { return true; } static void initializeImpl(ASTContext &Context, TypeLoc TL, SourceLocation Loc); static TypeLoc getNextTypeLocImpl(TypeLoc TL); static TypeLoc IgnoreParensImpl(TypeLoc TL); static SourceRange getLocalSourceRangeImpl(TypeLoc TL); }; /// \brief Return the TypeLoc for a type source info. inline TypeLoc TypeSourceInfo::getTypeLoc() const { return TypeLoc(Ty, const_cast(static_cast(this + 1))); } /// \brief Wrapper of type source information for a type with /// no direct qualifiers. class UnqualTypeLoc : public TypeLoc { public: UnqualTypeLoc() {} UnqualTypeLoc(const Type *Ty, void *Data) : TypeLoc(Ty, Data) {} const Type *getTypePtr() const { return reinterpret_cast(Ty); } TypeLocClass getTypeLocClass() const { return (TypeLocClass) getTypePtr()->getTypeClass(); } private: friend class TypeLoc; static bool isKind(const TypeLoc &TL) { return !TL.getType().hasLocalQualifiers(); } }; /// \brief Wrapper of type source information for a type with /// non-trivial direct qualifiers. /// /// Currently, we intentionally do not provide source location for /// type qualifiers. class QualifiedTypeLoc : public TypeLoc { public: SourceRange getLocalSourceRange() const { return SourceRange(); } UnqualTypeLoc getUnqualifiedLoc() const { return UnqualTypeLoc(getTypePtr(), Data); } /// Initializes the local data of this type source info block to /// provide no information. void initializeLocal(ASTContext &Context, SourceLocation Loc) { // do nothing } TypeLoc getNextTypeLoc() const { return getUnqualifiedLoc(); } /// \brief Returns the size of the type source info data block that is /// specific to this type. unsigned getLocalDataSize() const { // In fact, we don't currently preserve any location information // for qualifiers. return 0; } /// \brief Returns the size of the type source info data block. unsigned getFullDataSize() const { return getLocalDataSize() + getFullDataSizeForType(getType().getLocalUnqualifiedType()); } private: friend class TypeLoc; static bool isKind(const TypeLoc &TL) { return TL.getType().hasLocalQualifiers(); } }; inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { if (QualifiedTypeLoc Loc = getAs()) return Loc.getUnqualifiedLoc(); return castAs(); } /// A metaprogramming base class for TypeLoc classes which correspond /// to a particular Type subclass. It is accepted for a single /// TypeLoc class to correspond to multiple Type classes. /// /// \tparam Base a class from which to derive /// \tparam Derived the class deriving from this one /// \tparam TypeClass the concrete Type subclass associated with this /// location type /// \tparam LocalData the structure type of local location data for /// this type /// /// sizeof(LocalData) needs to be a multiple of sizeof(void*) or /// else the world will end. /// /// TypeLocs with non-constant amounts of local data should override /// getExtraLocalDataSize(); getExtraLocalData() will then point to /// this extra memory. /// /// TypeLocs with an inner type should define /// QualType getInnerType() const /// and getInnerTypeLoc() will then point to this inner type's /// location data. /// /// A word about hierarchies: this template is not designed to be /// derived from multiple times in a hierarchy. It is also not /// designed to be used for classes where subtypes might provide /// different amounts of source information. It should be subclassed /// only at the deepest portion of the hierarchy where all children /// have identical source information; if that's an abstract type, /// then further descendents should inherit from /// InheritingConcreteTypeLoc instead. template class ConcreteTypeLoc : public Base { const Derived *asDerived() const { return static_cast(this); } friend class TypeLoc; static bool isKind(const TypeLoc &TL) { return Derived::classofType(TL.getTypePtr()); } static bool classofType(const Type *Ty) { return TypeClass::classof(Ty); } public: unsigned getLocalDataSize() const { return sizeof(LocalData) + asDerived()->getExtraLocalDataSize(); } // Give a default implementation that's useful for leaf types. unsigned getFullDataSize() const { return asDerived()->getLocalDataSize() + getInnerTypeSize(); } TypeLoc getNextTypeLoc() const { return getNextTypeLoc(asDerived()->getInnerType()); } const TypeClass *getTypePtr() const { return cast(Base::getTypePtr()); } protected: unsigned getExtraLocalDataSize() const { return 0; } LocalData *getLocalData() const { return static_cast(Base::Data); } /// Gets a pointer past the Info structure; useful for classes with /// local data that can't be captured in the Info (e.g. because it's /// of variable size). void *getExtraLocalData() const { return getLocalData() + 1; } void *getNonLocalData() const { return static_cast(Base::Data) + asDerived()->getLocalDataSize(); } struct HasNoInnerType {}; HasNoInnerType getInnerType() const { return HasNoInnerType(); } TypeLoc getInnerTypeLoc() const { return TypeLoc(asDerived()->getInnerType(), getNonLocalData()); } private: unsigned getInnerTypeSize() const { return getInnerTypeSize(asDerived()->getInnerType()); } unsigned getInnerTypeSize(HasNoInnerType _) const { return 0; } unsigned getInnerTypeSize(QualType _) const { return getInnerTypeLoc().getFullDataSize(); } TypeLoc getNextTypeLoc(HasNoInnerType _) const { return TypeLoc(); } TypeLoc getNextTypeLoc(QualType T) const { return TypeLoc(T, getNonLocalData()); } }; /// A metaprogramming class designed for concrete subtypes of abstract /// types where all subtypes share equivalently-structured source /// information. See the note on ConcreteTypeLoc. template class InheritingConcreteTypeLoc : public Base { friend class TypeLoc; static bool classofType(const Type *Ty) { return TypeClass::classof(Ty); } static bool isKind(const TypeLoc &TL) { return Derived::classofType(TL.getTypePtr()); } static bool isKind(const UnqualTypeLoc &TL) { return Derived::classofType(TL.getTypePtr()); } public: const TypeClass *getTypePtr() const { return cast(Base::getTypePtr()); } }; struct TypeSpecLocInfo { SourceLocation NameLoc; }; /// \brief A reasonable base class for TypeLocs that correspond to /// types that are written as a type-specifier. class TypeSpecTypeLoc : public ConcreteTypeLoc { public: enum { LocalDataSize = sizeof(TypeSpecLocInfo) }; SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } SourceRange getLocalSourceRange() const { return SourceRange(getNameLoc(), getNameLoc()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setNameLoc(Loc); } private: friend class TypeLoc; static bool isKind(const TypeLoc &TL); }; struct BuiltinLocInfo { SourceLocation BuiltinLoc; }; /// \brief Wrapper for source info for builtin types. class BuiltinTypeLoc : public ConcreteTypeLoc { public: enum { LocalDataSize = sizeof(BuiltinLocInfo) }; SourceLocation getBuiltinLoc() const { return getLocalData()->BuiltinLoc; } void setBuiltinLoc(SourceLocation Loc) { getLocalData()->BuiltinLoc = Loc; } SourceLocation getNameLoc() const { return getBuiltinLoc(); } WrittenBuiltinSpecs& getWrittenBuiltinSpecs() { return *(static_cast(getExtraLocalData())); } const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const { return *(static_cast(getExtraLocalData())); } bool needsExtraLocalData() const { BuiltinType::Kind bk = getTypePtr()->getKind(); return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) || (bk >= BuiltinType::Short && bk <= BuiltinType::LongDouble) || bk == BuiltinType::UChar || bk == BuiltinType::SChar; } unsigned getExtraLocalDataSize() const { return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0; } SourceRange getLocalSourceRange() const { return SourceRange(getBuiltinLoc(), getBuiltinLoc()); } TypeSpecifierSign getWrittenSignSpec() const { if (needsExtraLocalData()) return static_cast(getWrittenBuiltinSpecs().Sign); else return TSS_unspecified; } bool hasWrittenSignSpec() const { return getWrittenSignSpec() != TSS_unspecified; } void setWrittenSignSpec(TypeSpecifierSign written) { if (needsExtraLocalData()) getWrittenBuiltinSpecs().Sign = written; } TypeSpecifierWidth getWrittenWidthSpec() const { if (needsExtraLocalData()) return static_cast(getWrittenBuiltinSpecs().Width); else return TSW_unspecified; } bool hasWrittenWidthSpec() const { return getWrittenWidthSpec() != TSW_unspecified; } void setWrittenWidthSpec(TypeSpecifierWidth written) { if (needsExtraLocalData()) getWrittenBuiltinSpecs().Width = written; } TypeSpecifierType getWrittenTypeSpec() const; bool hasWrittenTypeSpec() const { return getWrittenTypeSpec() != TST_unspecified; } void setWrittenTypeSpec(TypeSpecifierType written) { if (needsExtraLocalData()) getWrittenBuiltinSpecs().Type = written; } bool hasModeAttr() const { if (needsExtraLocalData()) return getWrittenBuiltinSpecs().ModeAttr; else return false; } void setModeAttr(bool written) { if (needsExtraLocalData()) getWrittenBuiltinSpecs().ModeAttr = written; } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setBuiltinLoc(Loc); if (needsExtraLocalData()) { WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs(); wbs.Sign = TSS_unspecified; wbs.Width = TSW_unspecified; wbs.Type = TST_unspecified; wbs.ModeAttr = false; } } }; /// \brief Wrapper for source info for typedefs. class TypedefTypeLoc : public InheritingConcreteTypeLoc { public: TypedefNameDecl *getTypedefNameDecl() const { return getTypePtr()->getDecl(); } }; /// \brief Wrapper for source info for injected class names of class /// templates. class InjectedClassNameTypeLoc : public InheritingConcreteTypeLoc { public: CXXRecordDecl *getDecl() const { return getTypePtr()->getDecl(); } }; /// \brief Wrapper for source info for unresolved typename using decls. class UnresolvedUsingTypeLoc : public InheritingConcreteTypeLoc { public: UnresolvedUsingTypenameDecl *getDecl() const { return getTypePtr()->getDecl(); } }; /// \brief Wrapper for source info for tag types. Note that this only /// records source info for the name itself; a type written 'struct foo' /// should be represented as an ElaboratedTypeLoc. We currently /// only do that when C++ is enabled because of the expense of /// creating an ElaboratedType node for so many type references in C. class TagTypeLoc : public InheritingConcreteTypeLoc { public: TagDecl *getDecl() const { return getTypePtr()->getDecl(); } /// \brief True if the tag was defined in this type specifier. bool isDefinition() const { TagDecl *D = getDecl(); return D->isCompleteDefinition() && (D->getIdentifier() == 0 || D->getLocation() == getNameLoc()); } }; /// \brief Wrapper for source info for record types. class RecordTypeLoc : public InheritingConcreteTypeLoc { public: RecordDecl *getDecl() const { return getTypePtr()->getDecl(); } }; /// \brief Wrapper for source info for enum types. class EnumTypeLoc : public InheritingConcreteTypeLoc { public: EnumDecl *getDecl() const { return getTypePtr()->getDecl(); } }; /// \brief Wrapper for template type parameters. class TemplateTypeParmTypeLoc : public InheritingConcreteTypeLoc { public: TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); } }; /// \brief Wrapper for substituted template type parameters. class SubstTemplateTypeParmTypeLoc : public InheritingConcreteTypeLoc { }; /// \brief Wrapper for substituted template type parameters. class SubstTemplateTypeParmPackTypeLoc : public InheritingConcreteTypeLoc { }; struct AttributedLocInfo { union { Expr *ExprOperand; /// A raw SourceLocation. unsigned EnumOperandLoc; }; SourceRange OperandParens; SourceLocation AttrLoc; }; /// \brief Type source information for an attributed type. class AttributedTypeLoc : public ConcreteTypeLoc { public: AttributedType::Kind getAttrKind() const { return getTypePtr()->getAttrKind(); } bool hasAttrExprOperand() const { return (getAttrKind() >= AttributedType::FirstExprOperandKind && getAttrKind() <= AttributedType::LastExprOperandKind); } bool hasAttrEnumOperand() const { return (getAttrKind() >= AttributedType::FirstEnumOperandKind && getAttrKind() <= AttributedType::LastEnumOperandKind); } bool hasAttrOperand() const { return hasAttrExprOperand() || hasAttrEnumOperand(); } /// The modified type, which is generally canonically different from /// the attribute type. /// int main(int, char**) __attribute__((noreturn)) /// ~~~ ~~~~~~~~~~~~~ TypeLoc getModifiedLoc() const { return getInnerTypeLoc(); } /// The location of the attribute name, i.e. /// __attribute__((regparm(1000))) /// ^~~~~~~ SourceLocation getAttrNameLoc() const { return getLocalData()->AttrLoc; } void setAttrNameLoc(SourceLocation loc) { getLocalData()->AttrLoc = loc; } /// The attribute's expression operand, if it has one. /// void *cur_thread __attribute__((address_space(21))) /// ^~ Expr *getAttrExprOperand() const { assert(hasAttrExprOperand()); return getLocalData()->ExprOperand; } void setAttrExprOperand(Expr *e) { assert(hasAttrExprOperand()); getLocalData()->ExprOperand = e; } /// The location of the attribute's enumerated operand, if it has one. /// void * __attribute__((objc_gc(weak))) /// ^~~~ SourceLocation getAttrEnumOperandLoc() const { assert(hasAttrEnumOperand()); return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc); } void setAttrEnumOperandLoc(SourceLocation loc) { assert(hasAttrEnumOperand()); getLocalData()->EnumOperandLoc = loc.getRawEncoding(); } /// The location of the parentheses around the operand, if there is /// an operand. /// void * __attribute__((objc_gc(weak))) /// ^ ^ SourceRange getAttrOperandParensRange() const { assert(hasAttrOperand()); return getLocalData()->OperandParens; } void setAttrOperandParensRange(SourceRange range) { assert(hasAttrOperand()); getLocalData()->OperandParens = range; } SourceRange getLocalSourceRange() const { // Note that this does *not* include the range of the attribute // enclosure, e.g.: // __attribute__((foo(bar))) // ^~~~~~~~~~~~~~~ ~~ // or // [[foo(bar)]] // ^~ ~~ // That enclosure doesn't necessarily belong to a single attribute // anyway. SourceRange range(getAttrNameLoc()); if (hasAttrOperand()) range.setEnd(getAttrOperandParensRange().getEnd()); return range; } void initializeLocal(ASTContext &Context, SourceLocation loc) { setAttrNameLoc(loc); if (hasAttrExprOperand()) { setAttrOperandParensRange(SourceRange(loc)); setAttrExprOperand(0); } else if (hasAttrEnumOperand()) { setAttrOperandParensRange(SourceRange(loc)); setAttrEnumOperandLoc(loc); } } QualType getInnerType() const { return getTypePtr()->getModifiedType(); } }; struct ObjCProtocolListLocInfo { SourceLocation LAngleLoc; SourceLocation RAngleLoc; bool HasBaseTypeAsWritten; }; // A helper class for defining ObjC TypeLocs that can qualified with // protocols. // // TypeClass basically has to be either ObjCInterfaceType or // ObjCObjectPointerType. class ObjCObjectTypeLoc : public ConcreteTypeLoc { // SourceLocations are stored after Info, one for each Protocol. SourceLocation *getProtocolLocArray() const { return (SourceLocation*) this->getExtraLocalData(); } public: SourceLocation getLAngleLoc() const { return this->getLocalData()->LAngleLoc; } void setLAngleLoc(SourceLocation Loc) { this->getLocalData()->LAngleLoc = Loc; } SourceLocation getRAngleLoc() const { return this->getLocalData()->RAngleLoc; } void setRAngleLoc(SourceLocation Loc) { this->getLocalData()->RAngleLoc = Loc; } unsigned getNumProtocols() const { return this->getTypePtr()->getNumProtocols(); } SourceLocation getProtocolLoc(unsigned i) const { assert(i < getNumProtocols() && "Index is out of bounds!"); return getProtocolLocArray()[i]; } void setProtocolLoc(unsigned i, SourceLocation Loc) { assert(i < getNumProtocols() && "Index is out of bounds!"); getProtocolLocArray()[i] = Loc; } ObjCProtocolDecl *getProtocol(unsigned i) const { assert(i < getNumProtocols() && "Index is out of bounds!"); return *(this->getTypePtr()->qual_begin() + i); } bool hasBaseTypeAsWritten() const { return getLocalData()->HasBaseTypeAsWritten; } void setHasBaseTypeAsWritten(bool HasBaseType) { getLocalData()->HasBaseTypeAsWritten = HasBaseType; } TypeLoc getBaseLoc() const { return getInnerTypeLoc(); } SourceRange getLocalSourceRange() const { return SourceRange(getLAngleLoc(), getRAngleLoc()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setHasBaseTypeAsWritten(true); setLAngleLoc(Loc); setRAngleLoc(Loc); for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) setProtocolLoc(i, Loc); } unsigned getExtraLocalDataSize() const { return this->getNumProtocols() * sizeof(SourceLocation); } QualType getInnerType() const { return getTypePtr()->getBaseType(); } }; struct ObjCInterfaceLocInfo { SourceLocation NameLoc; SourceLocation NameEndLoc; }; /// \brief Wrapper for source info for ObjC interfaces. class ObjCInterfaceTypeLoc : public ConcreteTypeLoc { public: ObjCInterfaceDecl *getIFaceDecl() const { return getTypePtr()->getDecl(); } SourceLocation getNameLoc() const { return getLocalData()->NameLoc; } void setNameLoc(SourceLocation Loc) { getLocalData()->NameLoc = Loc; } SourceRange getLocalSourceRange() const { return SourceRange(getNameLoc(), getNameEndLoc()); } SourceLocation getNameEndLoc() const { return getLocalData()->NameEndLoc; } void setNameEndLoc(SourceLocation Loc) { getLocalData()->NameEndLoc = Loc; } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setNameLoc(Loc); setNameEndLoc(Loc); } }; struct ParenLocInfo { SourceLocation LParenLoc; SourceLocation RParenLoc; }; class ParenTypeLoc : public ConcreteTypeLoc { public: SourceLocation getLParenLoc() const { return this->getLocalData()->LParenLoc; } SourceLocation getRParenLoc() const { return this->getLocalData()->RParenLoc; } void setLParenLoc(SourceLocation Loc) { this->getLocalData()->LParenLoc = Loc; } void setRParenLoc(SourceLocation Loc) { this->getLocalData()->RParenLoc = Loc; } SourceRange getLocalSourceRange() const { return SourceRange(getLParenLoc(), getRParenLoc()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setLParenLoc(Loc); setRParenLoc(Loc); } TypeLoc getInnerLoc() const { return getInnerTypeLoc(); } QualType getInnerType() const { return this->getTypePtr()->getInnerType(); } }; inline TypeLoc TypeLoc::IgnoreParens() const { if (ParenTypeLoc::isKind(*this)) return IgnoreParensImpl(*this); return *this; } struct PointerLikeLocInfo { SourceLocation StarLoc; }; /// A base class for template class PointerLikeTypeLoc : public ConcreteTypeLoc { public: SourceLocation getSigilLoc() const { return this->getLocalData()->StarLoc; } void setSigilLoc(SourceLocation Loc) { this->getLocalData()->StarLoc = Loc; } TypeLoc getPointeeLoc() const { return this->getInnerTypeLoc(); } SourceRange getLocalSourceRange() const { return SourceRange(getSigilLoc(), getSigilLoc()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setSigilLoc(Loc); } QualType getInnerType() const { return this->getTypePtr()->getPointeeType(); } }; /// \brief Wrapper for source info for pointers. class PointerTypeLoc : public PointerLikeTypeLoc { public: SourceLocation getStarLoc() const { return getSigilLoc(); } void setStarLoc(SourceLocation Loc) { setSigilLoc(Loc); } }; /// \brief Wrapper for source info for block pointers. class BlockPointerTypeLoc : public PointerLikeTypeLoc { public: SourceLocation getCaretLoc() const { return getSigilLoc(); } void setCaretLoc(SourceLocation Loc) { setSigilLoc(Loc); } }; struct MemberPointerLocInfo : public PointerLikeLocInfo { TypeSourceInfo *ClassTInfo; }; /// \brief Wrapper for source info for member pointers. class MemberPointerTypeLoc : public PointerLikeTypeLoc { public: SourceLocation getStarLoc() const { return getSigilLoc(); } void setStarLoc(SourceLocation Loc) { setSigilLoc(Loc); } const Type *getClass() const { return getTypePtr()->getClass(); } TypeSourceInfo *getClassTInfo() const { return getLocalData()->ClassTInfo; } void setClassTInfo(TypeSourceInfo* TI) { getLocalData()->ClassTInfo = TI; } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setSigilLoc(Loc); setClassTInfo(0); } SourceRange getLocalSourceRange() const { if (TypeSourceInfo *TI = getClassTInfo()) return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc()); else return SourceRange(getStarLoc()); } }; /// Wraps an ObjCPointerType with source location information. class ObjCObjectPointerTypeLoc : public PointerLikeTypeLoc { public: SourceLocation getStarLoc() const { return getSigilLoc(); } void setStarLoc(SourceLocation Loc) { setSigilLoc(Loc); } }; class ReferenceTypeLoc : public PointerLikeTypeLoc { public: QualType getInnerType() const { return getTypePtr()->getPointeeTypeAsWritten(); } }; class LValueReferenceTypeLoc : public InheritingConcreteTypeLoc { public: SourceLocation getAmpLoc() const { return getSigilLoc(); } void setAmpLoc(SourceLocation Loc) { setSigilLoc(Loc); } }; class RValueReferenceTypeLoc : public InheritingConcreteTypeLoc { public: SourceLocation getAmpAmpLoc() const { return getSigilLoc(); } void setAmpAmpLoc(SourceLocation Loc) { setSigilLoc(Loc); } }; struct FunctionLocInfo { SourceLocation LocalRangeBegin; SourceLocation LParenLoc; SourceLocation RParenLoc; SourceLocation LocalRangeEnd; }; /// \brief Wrapper for source info for functions. class FunctionTypeLoc : public ConcreteTypeLoc { public: SourceLocation getLocalRangeBegin() const { return getLocalData()->LocalRangeBegin; } void setLocalRangeBegin(SourceLocation L) { getLocalData()->LocalRangeBegin = L; } SourceLocation getLocalRangeEnd() const { return getLocalData()->LocalRangeEnd; } void setLocalRangeEnd(SourceLocation L) { getLocalData()->LocalRangeEnd = L; } SourceLocation getLParenLoc() const { return this->getLocalData()->LParenLoc; } void setLParenLoc(SourceLocation Loc) { this->getLocalData()->LParenLoc = Loc; } SourceLocation getRParenLoc() const { return this->getLocalData()->RParenLoc; } void setRParenLoc(SourceLocation Loc) { this->getLocalData()->RParenLoc = Loc; } SourceRange getParensRange() const { return SourceRange(getLParenLoc(), getRParenLoc()); } ArrayRef getParams() const { return ArrayRef(getParmArray(), getNumArgs()); } // ParmVarDecls* are stored after Info, one for each argument. ParmVarDecl **getParmArray() const { return (ParmVarDecl**) getExtraLocalData(); } unsigned getNumArgs() const { if (isa(getTypePtr())) return 0; return cast(getTypePtr())->getNumArgs(); } ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; } void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; } TypeLoc getResultLoc() const { return getInnerTypeLoc(); } SourceRange getLocalSourceRange() const { return SourceRange(getLocalRangeBegin(), getLocalRangeEnd()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setLocalRangeBegin(Loc); setLParenLoc(Loc); setRParenLoc(Loc); setLocalRangeEnd(Loc); for (unsigned i = 0, e = getNumArgs(); i != e; ++i) setArg(i, NULL); } /// \brief Returns the size of the type source info data block that is /// specific to this type. unsigned getExtraLocalDataSize() const { return getNumArgs() * sizeof(ParmVarDecl*); } QualType getInnerType() const { return getTypePtr()->getResultType(); } }; class FunctionProtoTypeLoc : public InheritingConcreteTypeLoc { }; class FunctionNoProtoTypeLoc : public InheritingConcreteTypeLoc { }; struct ArrayLocInfo { SourceLocation LBracketLoc, RBracketLoc; Expr *Size; }; /// \brief Wrapper for source info for arrays. class ArrayTypeLoc : public ConcreteTypeLoc { public: SourceLocation getLBracketLoc() const { return getLocalData()->LBracketLoc; } void setLBracketLoc(SourceLocation Loc) { getLocalData()->LBracketLoc = Loc; } SourceLocation getRBracketLoc() const { return getLocalData()->RBracketLoc; } void setRBracketLoc(SourceLocation Loc) { getLocalData()->RBracketLoc = Loc; } SourceRange getBracketsRange() const { return SourceRange(getLBracketLoc(), getRBracketLoc()); } Expr *getSizeExpr() const { return getLocalData()->Size; } void setSizeExpr(Expr *Size) { getLocalData()->Size = Size; } TypeLoc getElementLoc() const { return getInnerTypeLoc(); } SourceRange getLocalSourceRange() const { return SourceRange(getLBracketLoc(), getRBracketLoc()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setLBracketLoc(Loc); setRBracketLoc(Loc); setSizeExpr(NULL); } QualType getInnerType() const { return getTypePtr()->getElementType(); } }; class ConstantArrayTypeLoc : public InheritingConcreteTypeLoc { }; class IncompleteArrayTypeLoc : public InheritingConcreteTypeLoc { }; class DependentSizedArrayTypeLoc : public InheritingConcreteTypeLoc { }; class VariableArrayTypeLoc : public InheritingConcreteTypeLoc { }; // Location information for a TemplateName. Rudimentary for now. struct TemplateNameLocInfo { SourceLocation NameLoc; }; struct TemplateSpecializationLocInfo : TemplateNameLocInfo { SourceLocation TemplateKWLoc; SourceLocation LAngleLoc; SourceLocation RAngleLoc; }; class TemplateSpecializationTypeLoc : public ConcreteTypeLoc { public: SourceLocation getTemplateKeywordLoc() const { return getLocalData()->TemplateKWLoc; } void setTemplateKeywordLoc(SourceLocation Loc) { getLocalData()->TemplateKWLoc = Loc; } SourceLocation getLAngleLoc() const { return getLocalData()->LAngleLoc; } void setLAngleLoc(SourceLocation Loc) { getLocalData()->LAngleLoc = Loc; } SourceLocation getRAngleLoc() const { return getLocalData()->RAngleLoc; } void setRAngleLoc(SourceLocation Loc) { getLocalData()->RAngleLoc = Loc; } unsigned getNumArgs() const { return getTypePtr()->getNumArgs(); } void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { getArgInfos()[i] = AI; } TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { return getArgInfos()[i]; } TemplateArgumentLoc getArgLoc(unsigned i) const { return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i)); } SourceLocation getTemplateNameLoc() const { return getLocalData()->NameLoc; } void setTemplateNameLoc(SourceLocation Loc) { getLocalData()->NameLoc = Loc; } /// \brief - Copy the location information from the given info. void copy(TemplateSpecializationTypeLoc Loc) { unsigned size = getFullDataSize(); assert(size == Loc.getFullDataSize()); // We're potentially copying Expr references here. We don't // bother retaining them because TypeSourceInfos live forever, so // as long as the Expr was retained when originally written into // the TypeLoc, we're okay. memcpy(Data, Loc.Data, size); } SourceRange getLocalSourceRange() const { if (getTemplateKeywordLoc().isValid()) return SourceRange(getTemplateKeywordLoc(), getRAngleLoc()); else return SourceRange(getTemplateNameLoc(), getRAngleLoc()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setTemplateKeywordLoc(Loc); setTemplateNameLoc(Loc); setLAngleLoc(Loc); setRAngleLoc(Loc); initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(), getArgInfos(), Loc); } static void initializeArgLocs(ASTContext &Context, unsigned NumArgs, const TemplateArgument *Args, TemplateArgumentLocInfo *ArgInfos, SourceLocation Loc); unsigned getExtraLocalDataSize() const { return getNumArgs() * sizeof(TemplateArgumentLocInfo); } private: TemplateArgumentLocInfo *getArgInfos() const { return static_cast(getExtraLocalData()); } }; //===----------------------------------------------------------------------===// // // All of these need proper implementations. // //===----------------------------------------------------------------------===// // FIXME: size expression and attribute locations (or keyword if we // ever fully support altivec syntax). class VectorTypeLoc : public InheritingConcreteTypeLoc { }; // FIXME: size expression and attribute locations. class ExtVectorTypeLoc : public InheritingConcreteTypeLoc { }; // FIXME: attribute locations. // For some reason, this isn't a subtype of VectorType. class DependentSizedExtVectorTypeLoc : public InheritingConcreteTypeLoc { }; // FIXME: location of the '_Complex' keyword. class ComplexTypeLoc : public InheritingConcreteTypeLoc { }; struct TypeofLocInfo { SourceLocation TypeofLoc; SourceLocation LParenLoc; SourceLocation RParenLoc; }; struct TypeOfExprTypeLocInfo : public TypeofLocInfo { }; struct TypeOfTypeLocInfo : public TypeofLocInfo { TypeSourceInfo* UnderlyingTInfo; }; template class TypeofLikeTypeLoc : public ConcreteTypeLoc { public: SourceLocation getTypeofLoc() const { return this->getLocalData()->TypeofLoc; } void setTypeofLoc(SourceLocation Loc) { this->getLocalData()->TypeofLoc = Loc; } SourceLocation getLParenLoc() const { return this->getLocalData()->LParenLoc; } void setLParenLoc(SourceLocation Loc) { this->getLocalData()->LParenLoc = Loc; } SourceLocation getRParenLoc() const { return this->getLocalData()->RParenLoc; } void setRParenLoc(SourceLocation Loc) { this->getLocalData()->RParenLoc = Loc; } SourceRange getParensRange() const { return SourceRange(getLParenLoc(), getRParenLoc()); } void setParensRange(SourceRange range) { setLParenLoc(range.getBegin()); setRParenLoc(range.getEnd()); } SourceRange getLocalSourceRange() const { return SourceRange(getTypeofLoc(), getRParenLoc()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setTypeofLoc(Loc); setLParenLoc(Loc); setRParenLoc(Loc); } }; class TypeOfExprTypeLoc : public TypeofLikeTypeLoc { public: Expr* getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); } // Reimplemented to account for GNU/C++ extension // typeof unary-expression // where there are no parentheses. SourceRange getLocalSourceRange() const; }; class TypeOfTypeLoc : public TypeofLikeTypeLoc { public: QualType getUnderlyingType() const { return this->getTypePtr()->getUnderlyingType(); } TypeSourceInfo* getUnderlyingTInfo() const { return this->getLocalData()->UnderlyingTInfo; } void setUnderlyingTInfo(TypeSourceInfo* TI) const { this->getLocalData()->UnderlyingTInfo = TI; } }; // FIXME: location of the 'decltype' and parens. class DecltypeTypeLoc : public InheritingConcreteTypeLoc { public: Expr *getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); } }; struct UnaryTransformTypeLocInfo { // FIXME: While there's only one unary transform right now, future ones may // need different representations SourceLocation KWLoc, LParenLoc, RParenLoc; TypeSourceInfo *UnderlyingTInfo; }; class UnaryTransformTypeLoc : public ConcreteTypeLoc { public: SourceLocation getKWLoc() const { return getLocalData()->KWLoc; } void setKWLoc(SourceLocation Loc) { getLocalData()->KWLoc = Loc; } SourceLocation getLParenLoc() const { return getLocalData()->LParenLoc; } void setLParenLoc(SourceLocation Loc) { getLocalData()->LParenLoc = Loc; } SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; } void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; } TypeSourceInfo* getUnderlyingTInfo() const { return getLocalData()->UnderlyingTInfo; } void setUnderlyingTInfo(TypeSourceInfo *TInfo) { getLocalData()->UnderlyingTInfo = TInfo; } SourceRange getLocalSourceRange() const { return SourceRange(getKWLoc(), getRParenLoc()); } SourceRange getParensRange() const { return SourceRange(getLParenLoc(), getRParenLoc()); } void setParensRange(SourceRange Range) { setLParenLoc(Range.getBegin()); setRParenLoc(Range.getEnd()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setKWLoc(Loc); setRParenLoc(Loc); setLParenLoc(Loc); } }; class AutoTypeLoc : public InheritingConcreteTypeLoc { }; struct ElaboratedLocInfo { SourceLocation ElaboratedKWLoc; /// \brief Data associated with the nested-name-specifier location. void *QualifierData; }; class ElaboratedTypeLoc : public ConcreteTypeLoc { public: SourceLocation getElaboratedKeywordLoc() const { return this->getLocalData()->ElaboratedKWLoc; } void setElaboratedKeywordLoc(SourceLocation Loc) { this->getLocalData()->ElaboratedKWLoc = Loc; } NestedNameSpecifierLoc getQualifierLoc() const { return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), getLocalData()->QualifierData); } void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { assert(QualifierLoc.getNestedNameSpecifier() == getTypePtr()->getQualifier() && "Inconsistent nested-name-specifier pointer"); getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } SourceRange getLocalSourceRange() const { if (getElaboratedKeywordLoc().isValid()) if (getQualifierLoc()) return SourceRange(getElaboratedKeywordLoc(), getQualifierLoc().getEndLoc()); else return SourceRange(getElaboratedKeywordLoc()); else return getQualifierLoc().getSourceRange(); } void initializeLocal(ASTContext &Context, SourceLocation Loc); TypeLoc getNamedTypeLoc() const { return getInnerTypeLoc(); } QualType getInnerType() const { return getTypePtr()->getNamedType(); } void copy(ElaboratedTypeLoc Loc) { unsigned size = getFullDataSize(); assert(size == Loc.getFullDataSize()); memcpy(Data, Loc.Data, size); } }; // This is exactly the structure of an ElaboratedTypeLoc whose inner // type is some sort of TypeDeclTypeLoc. struct DependentNameLocInfo : ElaboratedLocInfo { SourceLocation NameLoc; }; class DependentNameTypeLoc : public ConcreteTypeLoc { public: SourceLocation getElaboratedKeywordLoc() const { return this->getLocalData()->ElaboratedKWLoc; } void setElaboratedKeywordLoc(SourceLocation Loc) { this->getLocalData()->ElaboratedKWLoc = Loc; } NestedNameSpecifierLoc getQualifierLoc() const { return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), getLocalData()->QualifierData); } void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { assert(QualifierLoc.getNestedNameSpecifier() == getTypePtr()->getQualifier() && "Inconsistent nested-name-specifier pointer"); getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } SourceRange getLocalSourceRange() const { if (getElaboratedKeywordLoc().isValid()) return SourceRange(getElaboratedKeywordLoc(), getNameLoc()); else return SourceRange(getQualifierLoc().getBeginLoc(), getNameLoc()); } void copy(DependentNameTypeLoc Loc) { unsigned size = getFullDataSize(); assert(size == Loc.getFullDataSize()); memcpy(Data, Loc.Data, size); } void initializeLocal(ASTContext &Context, SourceLocation Loc); }; struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo { SourceLocation TemplateKWLoc; SourceLocation LAngleLoc; SourceLocation RAngleLoc; // followed by a TemplateArgumentLocInfo[] }; class DependentTemplateSpecializationTypeLoc : public ConcreteTypeLoc { public: SourceLocation getElaboratedKeywordLoc() const { return this->getLocalData()->ElaboratedKWLoc; } void setElaboratedKeywordLoc(SourceLocation Loc) { this->getLocalData()->ElaboratedKWLoc = Loc; } NestedNameSpecifierLoc getQualifierLoc() const { if (!getLocalData()->QualifierData) return NestedNameSpecifierLoc(); return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), getLocalData()->QualifierData); } void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { if (!QualifierLoc) { // Even if we have a nested-name-specifier in the dependent // template specialization type, we won't record the nested-name-specifier // location information when this type-source location information is // part of a nested-name-specifier. getLocalData()->QualifierData = 0; return; } assert(QualifierLoc.getNestedNameSpecifier() == getTypePtr()->getQualifier() && "Inconsistent nested-name-specifier pointer"); getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } SourceLocation getTemplateKeywordLoc() const { return getLocalData()->TemplateKWLoc; } void setTemplateKeywordLoc(SourceLocation Loc) { getLocalData()->TemplateKWLoc = Loc; } SourceLocation getTemplateNameLoc() const { return this->getLocalData()->NameLoc; } void setTemplateNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } SourceLocation getLAngleLoc() const { return this->getLocalData()->LAngleLoc; } void setLAngleLoc(SourceLocation Loc) { this->getLocalData()->LAngleLoc = Loc; } SourceLocation getRAngleLoc() const { return this->getLocalData()->RAngleLoc; } void setRAngleLoc(SourceLocation Loc) { this->getLocalData()->RAngleLoc = Loc; } unsigned getNumArgs() const { return getTypePtr()->getNumArgs(); } void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { getArgInfos()[i] = AI; } TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { return getArgInfos()[i]; } TemplateArgumentLoc getArgLoc(unsigned i) const { return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i)); } SourceRange getLocalSourceRange() const { if (getElaboratedKeywordLoc().isValid()) return SourceRange(getElaboratedKeywordLoc(), getRAngleLoc()); else if (getQualifierLoc()) return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc()); else if (getTemplateKeywordLoc().isValid()) return SourceRange(getTemplateKeywordLoc(), getRAngleLoc()); else return SourceRange(getTemplateNameLoc(), getRAngleLoc()); } void copy(DependentTemplateSpecializationTypeLoc Loc) { unsigned size = getFullDataSize(); assert(size == Loc.getFullDataSize()); memcpy(Data, Loc.Data, size); } void initializeLocal(ASTContext &Context, SourceLocation Loc); unsigned getExtraLocalDataSize() const { return getNumArgs() * sizeof(TemplateArgumentLocInfo); } private: TemplateArgumentLocInfo *getArgInfos() const { return static_cast(getExtraLocalData()); } }; struct PackExpansionTypeLocInfo { SourceLocation EllipsisLoc; }; class PackExpansionTypeLoc : public ConcreteTypeLoc { public: SourceLocation getEllipsisLoc() const { return this->getLocalData()->EllipsisLoc; } void setEllipsisLoc(SourceLocation Loc) { this->getLocalData()->EllipsisLoc = Loc; } SourceRange getLocalSourceRange() const { return SourceRange(getEllipsisLoc(), getEllipsisLoc()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setEllipsisLoc(Loc); } TypeLoc getPatternLoc() const { return getInnerTypeLoc(); } QualType getInnerType() const { return this->getTypePtr()->getPattern(); } }; struct AtomicTypeLocInfo { SourceLocation KWLoc, LParenLoc, RParenLoc; }; class AtomicTypeLoc : public ConcreteTypeLoc { public: TypeLoc getValueLoc() const { return this->getInnerTypeLoc(); } SourceRange getLocalSourceRange() const { return SourceRange(getKWLoc(), getRParenLoc()); } SourceLocation getKWLoc() const { return this->getLocalData()->KWLoc; } void setKWLoc(SourceLocation Loc) { this->getLocalData()->KWLoc = Loc; } SourceLocation getLParenLoc() const { return this->getLocalData()->LParenLoc; } void setLParenLoc(SourceLocation Loc) { this->getLocalData()->LParenLoc = Loc; } SourceLocation getRParenLoc() const { return this->getLocalData()->RParenLoc; } void setRParenLoc(SourceLocation Loc) { this->getLocalData()->RParenLoc = Loc; } SourceRange getParensRange() const { return SourceRange(getLParenLoc(), getRParenLoc()); } void setParensRange(SourceRange Range) { setLParenLoc(Range.getBegin()); setRParenLoc(Range.getEnd()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { setKWLoc(Loc); setLParenLoc(Loc); setRParenLoc(Loc); } QualType getInnerType() const { return this->getTypePtr()->getValueType(); } }; } #endif