| //===- TypeLoc.h - Type Source Info Wrapper ---------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| /// \file |
| /// Defines the clang::TypeLoc interface and its subclasses. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_AST_TYPELOC_H |
| #define LLVM_CLANG_AST_TYPELOC_H |
| |
| #include "clang/AST/Attr.h" |
| #include "clang/AST/Decl.h" |
| #include "clang/AST/NestedNameSpecifier.h" |
| #include "clang/AST/TemplateBase.h" |
| #include "clang/AST/Type.h" |
| #include "clang/Basic/LLVM.h" |
| #include "clang/Basic/SourceLocation.h" |
| #include "clang/Basic/Specifiers.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/Support/MathExtras.h" |
| #include <algorithm> |
| #include <cassert> |
| #include <cstdint> |
| #include <cstring> |
| |
| namespace clang { |
| |
| class ASTContext; |
| class CXXRecordDecl; |
| class Expr; |
| class ObjCInterfaceDecl; |
| class ObjCProtocolDecl; |
| class ObjCTypeParamDecl; |
| class TemplateTypeParmDecl; |
| class UnqualTypeLoc; |
| class UnresolvedUsingTypenameDecl; |
| |
| // Predeclare all the type nodes. |
| #define ABSTRACT_TYPELOC(Class, Base) |
| #define TYPELOC(Class, Base) \ |
| class Class##TypeLoc; |
| #include "clang/AST/TypeLocNodes.def" |
| |
| /// Base wrapper for a particular "section" of type source info. |
| /// |
| /// A client should use the TypeLoc subclasses through castAs()/getAs() |
| /// 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 = nullptr; |
| void *Data = nullptr; |
| |
| public: |
| TypeLoc() = default; |
| TypeLoc(QualType ty, void *opaqueData) |
| : Ty(ty.getAsOpaquePtr()), Data(opaqueData) {} |
| TypeLoc(const Type *ty, void *opaqueData) |
| : Ty(ty), Data(opaqueData) {} |
| |
| /// Convert to the specified TypeLoc type, asserting that this TypeLoc |
| /// is of the desired type. |
| /// |
| /// \pre T::isKind(*this) |
| template<typename T> |
| T castAs() const { |
| assert(T::isKind(*this)); |
| T t; |
| TypeLoc& tl = t; |
| tl = *this; |
| return t; |
| } |
| |
| /// Convert to the specified TypeLoc type, returning a null TypeLoc if |
| /// this TypeLoc is not of the desired type. |
| template<typename T> |
| T getAs() const { |
| if (!T::isKind(*this)) |
| return {}; |
| T t; |
| TypeLoc& tl = t; |
| tl = *this; |
| return t; |
| } |
| |
| /// Convert to the specified TypeLoc type, returning a null TypeLoc if |
| /// this TypeLoc is not of the desired type. It will consider type |
| /// adjustments from a type that was written as a T to another type that is |
| /// still canonically a T (ignores parens, attributes, elaborated types, etc). |
| template <typename T> |
| T getAsAdjusted() const; |
| |
| /// 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.inc" |
| Qualified |
| }; |
| |
| TypeLocClass getTypeLocClass() const { |
| if (getType().hasLocalQualifiers()) return Qualified; |
| return (TypeLocClass) getType()->getTypeClass(); |
| } |
| |
| bool isNull() const { return !Ty; } |
| explicit operator bool() const { return Ty; } |
| |
| /// Returns the size of type source info data block for the given type. |
| static unsigned getFullDataSizeForType(QualType Ty); |
| |
| /// Returns the alignment of type source info data block for |
| /// the given type. |
| static unsigned getLocalAlignmentForType(QualType Ty); |
| |
| /// 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(); |
| } |
| |
| /// Get the pointer where source information is stored. |
| void *getOpaqueData() const { |
| return Data; |
| } |
| |
| /// Get the begin source location. |
| SourceLocation getBeginLoc() const; |
| |
| /// Get the end source location. |
| SourceLocation getEndLoc() const; |
| |
| /// Get the full source range. |
| SourceRange getSourceRange() const LLVM_READONLY { |
| return SourceRange(getBeginLoc(), getEndLoc()); |
| } |
| |
| |
| /// Get the local source range. |
| SourceRange getLocalSourceRange() const { |
| return getLocalSourceRangeImpl(*this); |
| } |
| |
| /// Returns the size of the type source info data block. |
| unsigned getFullDataSize() const { |
| return getFullDataSizeForType(getType()); |
| } |
| |
| /// 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); |
| } |
| |
| /// Skips past any qualifiers, if this is qualified. |
| UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header |
| |
| TypeLoc IgnoreParens() const; |
| |
| /// Strips MacroDefinitionTypeLocs from a type location. |
| TypeLoc IgnoreMacroDefinitions() const; |
| |
| /// Find a type with the location of an explicit type qualifier. |
| /// |
| /// The result, if non-null, will be one of: |
| /// QualifiedTypeLoc |
| /// AtomicTypeLoc |
| /// AttributedTypeLoc, for those type attributes that behave as qualifiers |
| TypeLoc findExplicitQualifierLoc() const; |
| |
| /// 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); |
| } |
| |
| /// Initializes this by copying its information from another |
| /// TypeLoc of the same type. |
| void initializeFullCopy(TypeLoc Other) { |
| assert(getType() == Other.getType()); |
| copy(Other); |
| } |
| |
| /// 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) { |
| assert(getType() == Other.getType()); |
| assert(getFullDataSize() == Size); |
| copy(Other); |
| } |
| |
| /// Copies the other type loc into this one. |
| void copy(TypeLoc other); |
| |
| 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); |
| } |
| |
| /// Find the location of the nullability specifier (__nonnull, |
| /// __nullable, or __null_unspecifier), if there is one. |
| SourceLocation findNullabilityLoc() const; |
| |
| 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); |
| }; |
| |
| /// Return the TypeLoc for a type source info. |
| inline TypeLoc TypeSourceInfo::getTypeLoc() const { |
| // TODO: is this alignment already sufficient? |
| return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1))); |
| } |
| |
| /// Wrapper of type source information for a type with |
| /// no direct qualifiers. |
| class UnqualTypeLoc : public TypeLoc { |
| public: |
| UnqualTypeLoc() = default; |
| UnqualTypeLoc(const Type *Ty, void *Data) : TypeLoc(Ty, Data) {} |
| |
| const Type *getTypePtr() const { |
| return reinterpret_cast<const Type*>(Ty); |
| } |
| |
| TypeLocClass getTypeLocClass() const { |
| return (TypeLocClass) getTypePtr()->getTypeClass(); |
| } |
| |
| private: |
| friend class TypeLoc; |
| |
| static bool isKind(const TypeLoc &TL) { |
| return !TL.getType().hasLocalQualifiers(); |
| } |
| }; |
| |
| /// 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 {}; } |
| |
| UnqualTypeLoc getUnqualifiedLoc() const { |
| unsigned align = |
| TypeLoc::getLocalAlignmentForType(QualType(getTypePtr(), 0)); |
| auto dataInt = reinterpret_cast<uintptr_t>(Data); |
| dataInt = llvm::alignTo(dataInt, align); |
| return UnqualTypeLoc(getTypePtr(), reinterpret_cast<void*>(dataInt)); |
| } |
| |
| /// Initializes the local data of this type source info block to |
| /// provide no information. |
| void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
| // do nothing |
| } |
| |
| void copyLocal(TypeLoc other) { |
| // do nothing |
| } |
| |
| TypeLoc getNextTypeLoc() const { |
| return getUnqualifiedLoc(); |
| } |
| |
| /// 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; |
| } |
| |
| /// Returns the alignment of the type source info data block that is |
| /// specific to this type. |
| unsigned getLocalDataAlignment() const { |
| // We don't preserve any location information. |
| return 1; |
| } |
| |
| private: |
| friend class TypeLoc; |
| |
| static bool isKind(const TypeLoc &TL) { |
| return TL.getType().hasLocalQualifiers(); |
| } |
| }; |
| |
| inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { |
| if (QualifiedTypeLoc Loc = getAs<QualifiedTypeLoc>()) |
| return Loc.getUnqualifiedLoc(); |
| return castAs<UnqualTypeLoc>(); |
| } |
| |
| /// 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 |
| /// |
| /// 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 Base, class Derived, class TypeClass, class LocalData> |
| class ConcreteTypeLoc : public Base { |
| friend class TypeLoc; |
| |
| const Derived *asDerived() const { |
| return static_cast<const Derived*>(this); |
| } |
| |
| static bool isKind(const TypeLoc &TL) { |
| return !TL.getType().hasLocalQualifiers() && |
| Derived::classofType(TL.getTypePtr()); |
| } |
| |
| static bool classofType(const Type *Ty) { |
| return TypeClass::classof(Ty); |
| } |
| |
| public: |
| unsigned getLocalDataAlignment() const { |
| return std::max(unsigned(alignof(LocalData)), |
| asDerived()->getExtraLocalDataAlignment()); |
| } |
| |
| unsigned getLocalDataSize() const { |
| unsigned size = sizeof(LocalData); |
| unsigned extraAlign = asDerived()->getExtraLocalDataAlignment(); |
| size = llvm::alignTo(size, extraAlign); |
| size += asDerived()->getExtraLocalDataSize(); |
| return size; |
| } |
| |
| void copyLocal(Derived other) { |
| // Some subclasses have no data to copy. |
| if (asDerived()->getLocalDataSize() == 0) return; |
| |
| // Copy the fixed-sized local data. |
| memcpy(getLocalData(), other.getLocalData(), sizeof(LocalData)); |
| |
| // Copy the variable-sized local data. We need to do this |
| // separately because the padding in the source and the padding in |
| // the destination might be different. |
| memcpy(getExtraLocalData(), other.getExtraLocalData(), |
| asDerived()->getExtraLocalDataSize()); |
| } |
| |
| TypeLoc getNextTypeLoc() const { |
| return getNextTypeLoc(asDerived()->getInnerType()); |
| } |
| |
| const TypeClass *getTypePtr() const { |
| return cast<TypeClass>(Base::getTypePtr()); |
| } |
| |
| protected: |
| unsigned getExtraLocalDataSize() const { |
| return 0; |
| } |
| |
| unsigned getExtraLocalDataAlignment() const { |
| return 1; |
| } |
| |
| LocalData *getLocalData() const { |
| return static_cast<LocalData*>(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 { |
| unsigned size = sizeof(LocalData); |
| unsigned extraAlign = asDerived()->getExtraLocalDataAlignment(); |
| size = llvm::alignTo(size, extraAlign); |
| return reinterpret_cast<char*>(Base::Data) + size; |
| } |
| |
| void *getNonLocalData() const { |
| auto data = reinterpret_cast<uintptr_t>(Base::Data); |
| data += asDerived()->getLocalDataSize(); |
| data = llvm::alignTo(data, getNextTypeAlign()); |
| return reinterpret_cast<void*>(data); |
| } |
| |
| 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(); |
| } |
| |
| unsigned getNextTypeAlign() const { |
| return getNextTypeAlign(asDerived()->getInnerType()); |
| } |
| |
| unsigned getNextTypeAlign(HasNoInnerType _) const { |
| return 1; |
| } |
| |
| unsigned getNextTypeAlign(QualType T) const { |
| return TypeLoc::getLocalAlignmentForType(T); |
| } |
| |
| TypeLoc getNextTypeLoc(HasNoInnerType _) const { return {}; } |
| |
| 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 Base, class Derived, class TypeClass> |
| class InheritingConcreteTypeLoc : public Base { |
| friend class TypeLoc; |
| |
| static bool classofType(const Type *Ty) { |
| return TypeClass::classof(Ty); |
| } |
| |
| static bool isKind(const TypeLoc &TL) { |
| return !TL.getType().hasLocalQualifiers() && |
| Derived::classofType(TL.getTypePtr()); |
| } |
| static bool isKind(const UnqualTypeLoc &TL) { |
| return Derived::classofType(TL.getTypePtr()); |
| } |
| |
| public: |
| const TypeClass *getTypePtr() const { |
| return cast<TypeClass>(Base::getTypePtr()); |
| } |
| }; |
| |
| struct TypeSpecLocInfo { |
| SourceLocation NameLoc; |
| }; |
| |
| /// A reasonable base class for TypeLocs that correspond to |
| /// types that are written as a type-specifier. |
| class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
| TypeSpecTypeLoc, |
| Type, |
| TypeSpecLocInfo> { |
| public: |
| enum { |
| LocalDataSize = sizeof(TypeSpecLocInfo), |
| LocalDataAlignment = alignof(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 { |
| SourceRange BuiltinRange; |
| }; |
| |
| /// Wrapper for source info for builtin types. |
| class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
| BuiltinTypeLoc, |
| BuiltinType, |
| BuiltinLocInfo> { |
| public: |
| SourceLocation getBuiltinLoc() const { |
| return getLocalData()->BuiltinRange.getBegin(); |
| } |
| |
| void setBuiltinLoc(SourceLocation Loc) { |
| getLocalData()->BuiltinRange = Loc; |
| } |
| |
| void expandBuiltinRange(SourceRange Range) { |
| SourceRange &BuiltinRange = getLocalData()->BuiltinRange; |
| if (!BuiltinRange.getBegin().isValid()) { |
| BuiltinRange = Range; |
| } else { |
| BuiltinRange.setBegin(std::min(Range.getBegin(), BuiltinRange.getBegin())); |
| BuiltinRange.setEnd(std::max(Range.getEnd(), BuiltinRange.getEnd())); |
| } |
| } |
| |
| SourceLocation getNameLoc() const { return getBuiltinLoc(); } |
| |
| WrittenBuiltinSpecs& getWrittenBuiltinSpecs() { |
| return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData())); |
| } |
| const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const { |
| return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData())); |
| } |
| |
| bool needsExtraLocalData() const { |
| BuiltinType::Kind bk = getTypePtr()->getKind(); |
| return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) |
| || (bk >= BuiltinType::Short && bk <= BuiltinType::Float128) |
| || bk == BuiltinType::UChar |
| || bk == BuiltinType::SChar; |
| } |
| |
| unsigned getExtraLocalDataSize() const { |
| return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0; |
| } |
| |
| unsigned getExtraLocalDataAlignment() const { |
| return needsExtraLocalData() ? alignof(WrittenBuiltinSpecs) : 1; |
| } |
| |
| SourceRange getLocalSourceRange() const { |
| return getLocalData()->BuiltinRange; |
| } |
| |
| TypeSpecifierSign getWrittenSignSpec() const { |
| if (needsExtraLocalData()) |
| return static_cast<TypeSpecifierSign>(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<TypeSpecifierWidth>(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; |
| } |
| } |
| }; |
| |
| /// Wrapper for source info for typedefs. |
| class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
| TypedefTypeLoc, |
| TypedefType> { |
| public: |
| TypedefNameDecl *getTypedefNameDecl() const { |
| return getTypePtr()->getDecl(); |
| } |
| }; |
| |
| /// Wrapper for source info for injected class names of class |
| /// templates. |
| class InjectedClassNameTypeLoc : |
| public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
| InjectedClassNameTypeLoc, |
| InjectedClassNameType> { |
| public: |
| CXXRecordDecl *getDecl() const { |
| return getTypePtr()->getDecl(); |
| } |
| }; |
| |
| /// Wrapper for source info for unresolved typename using decls. |
| class UnresolvedUsingTypeLoc : |
| public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
| UnresolvedUsingTypeLoc, |
| UnresolvedUsingType> { |
| public: |
| UnresolvedUsingTypenameDecl *getDecl() const { |
| return getTypePtr()->getDecl(); |
| } |
| }; |
| |
| /// 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<TypeSpecTypeLoc, |
| TagTypeLoc, |
| TagType> { |
| public: |
| TagDecl *getDecl() const { return getTypePtr()->getDecl(); } |
| |
| /// True if the tag was defined in this type specifier. |
| bool isDefinition() const { |
| TagDecl *D = getDecl(); |
| return D->isCompleteDefinition() && |
| (D->getIdentifier() == nullptr || D->getLocation() == getNameLoc()); |
| } |
| }; |
| |
| /// Wrapper for source info for record types. |
| class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, |
| RecordTypeLoc, |
| RecordType> { |
| public: |
| RecordDecl *getDecl() const { return getTypePtr()->getDecl(); } |
| }; |
| |
| /// Wrapper for source info for enum types. |
| class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, |
| EnumTypeLoc, |
| EnumType> { |
| public: |
| EnumDecl *getDecl() const { return getTypePtr()->getDecl(); } |
| }; |
| |
| /// Wrapper for template type parameters. |
| class TemplateTypeParmTypeLoc : |
| public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
| TemplateTypeParmTypeLoc, |
| TemplateTypeParmType> { |
| public: |
| TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); } |
| }; |
| |
| struct ObjCTypeParamTypeLocInfo { |
| SourceLocation NameLoc; |
| }; |
| |
| /// ProtocolLAngleLoc, ProtocolRAngleLoc, and the source locations for |
| /// protocol qualifiers are stored after Info. |
| class ObjCTypeParamTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
| ObjCTypeParamTypeLoc, |
| ObjCTypeParamType, |
| ObjCTypeParamTypeLocInfo> { |
| // SourceLocations are stored after Info, one for each protocol qualifier. |
| SourceLocation *getProtocolLocArray() const { |
| return (SourceLocation*)this->getExtraLocalData() + 2; |
| } |
| |
| public: |
| ObjCTypeParamDecl *getDecl() const { return getTypePtr()->getDecl(); } |
| |
| SourceLocation getNameLoc() const { |
| return this->getLocalData()->NameLoc; |
| } |
| |
| void setNameLoc(SourceLocation Loc) { |
| this->getLocalData()->NameLoc = Loc; |
| } |
| |
| SourceLocation getProtocolLAngleLoc() const { |
| return getNumProtocols() ? |
| *((SourceLocation*)this->getExtraLocalData()) : |
| SourceLocation(); |
| } |
| |
| void setProtocolLAngleLoc(SourceLocation Loc) { |
| *((SourceLocation*)this->getExtraLocalData()) = Loc; |
| } |
| |
| SourceLocation getProtocolRAngleLoc() const { |
| return getNumProtocols() ? |
| *((SourceLocation*)this->getExtraLocalData() + 1) : |
| SourceLocation(); |
| } |
| |
| void setProtocolRAngleLoc(SourceLocation Loc) { |
| *((SourceLocation*)this->getExtraLocalData() + 1) = 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); |
| } |
| |
| ArrayRef<SourceLocation> getProtocolLocs() const { |
| return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols()); |
| } |
| |
| void initializeLocal(ASTContext &Context, SourceLocation Loc); |
| |
| unsigned getExtraLocalDataSize() const { |
| if (!this->getNumProtocols()) return 0; |
| // When there are protocol qualifers, we have LAngleLoc and RAngleLoc |
| // as well. |
| return (this->getNumProtocols() + 2) * sizeof(SourceLocation) ; |
| } |
| |
| unsigned getExtraLocalDataAlignment() const { |
| return alignof(SourceLocation); |
| } |
| |
| SourceRange getLocalSourceRange() const { |
| SourceLocation start = getNameLoc(); |
| SourceLocation end = getProtocolRAngleLoc(); |
| if (end.isInvalid()) return SourceRange(start, start); |
| return SourceRange(start, end); |
| } |
| }; |
| |
| /// Wrapper for substituted template type parameters. |
| class SubstTemplateTypeParmTypeLoc : |
| public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
| SubstTemplateTypeParmTypeLoc, |
| SubstTemplateTypeParmType> { |
| }; |
| |
| /// Wrapper for substituted template type parameters. |
| class SubstTemplateTypeParmPackTypeLoc : |
| public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
| SubstTemplateTypeParmPackTypeLoc, |
| SubstTemplateTypeParmPackType> { |
| }; |
| |
| struct AttributedLocInfo { |
| const Attr *TypeAttr; |
| }; |
| |
| /// Type source information for an attributed type. |
| class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
| AttributedTypeLoc, |
| AttributedType, |
| AttributedLocInfo> { |
| public: |
| attr::Kind getAttrKind() const { |
| return getTypePtr()->getAttrKind(); |
| } |
| |
| bool isQualifier() const { |
| return getTypePtr()->isQualifier(); |
| } |
| |
| /// The modified type, which is generally canonically different from |
| /// the attribute type. |
| /// int main(int, char**) __attribute__((noreturn)) |
| /// ~~~ ~~~~~~~~~~~~~ |
| TypeLoc getModifiedLoc() const { |
| return getInnerTypeLoc(); |
| } |
| |
| /// The type attribute. |
| const Attr *getAttr() const { |
| return getLocalData()->TypeAttr; |
| } |
| void setAttr(const Attr *A) { |
| getLocalData()->TypeAttr = A; |
| } |
| |
| template<typename T> const T *getAttrAs() { |
| return dyn_cast_or_null<T>(getAttr()); |
| } |
| |
| 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. |
| return getAttr() ? getAttr()->getRange() : SourceRange(); |
| } |
| |
| void initializeLocal(ASTContext &Context, SourceLocation loc) { |
| setAttr(nullptr); |
| } |
| |
| QualType getInnerType() const { |
| return getTypePtr()->getModifiedType(); |
| } |
| }; |
| |
| struct ObjCObjectTypeLocInfo { |
| SourceLocation TypeArgsLAngleLoc; |
| SourceLocation TypeArgsRAngleLoc; |
| SourceLocation ProtocolLAngleLoc; |
| SourceLocation ProtocolRAngleLoc; |
| 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<UnqualTypeLoc, |
| ObjCObjectTypeLoc, |
| ObjCObjectType, |
| ObjCObjectTypeLocInfo> { |
| // TypeSourceInfo*'s are stored after Info, one for each type argument. |
| TypeSourceInfo **getTypeArgLocArray() const { |
| return (TypeSourceInfo**)this->getExtraLocalData(); |
| } |
| |
| // SourceLocations are stored after the type argument information, one for |
| // each Protocol. |
| SourceLocation *getProtocolLocArray() const { |
| return (SourceLocation*)(getTypeArgLocArray() + getNumTypeArgs()); |
| } |
| |
| public: |
| SourceLocation getTypeArgsLAngleLoc() const { |
| return this->getLocalData()->TypeArgsLAngleLoc; |
| } |
| |
| void setTypeArgsLAngleLoc(SourceLocation Loc) { |
| this->getLocalData()->TypeArgsLAngleLoc = Loc; |
| } |
| |
| SourceLocation getTypeArgsRAngleLoc() const { |
| return this->getLocalData()->TypeArgsRAngleLoc; |
| } |
| |
| void setTypeArgsRAngleLoc(SourceLocation Loc) { |
| this->getLocalData()->TypeArgsRAngleLoc = Loc; |
| } |
| |
| unsigned getNumTypeArgs() const { |
| return this->getTypePtr()->getTypeArgsAsWritten().size(); |
| } |
| |
| TypeSourceInfo *getTypeArgTInfo(unsigned i) const { |
| assert(i < getNumTypeArgs() && "Index is out of bounds!"); |
| return getTypeArgLocArray()[i]; |
| } |
| |
| void setTypeArgTInfo(unsigned i, TypeSourceInfo *TInfo) { |
| assert(i < getNumTypeArgs() && "Index is out of bounds!"); |
| getTypeArgLocArray()[i] = TInfo; |
| } |
| |
| SourceLocation getProtocolLAngleLoc() const { |
| return this->getLocalData()->ProtocolLAngleLoc; |
| } |
| |
| void setProtocolLAngleLoc(SourceLocation Loc) { |
| this->getLocalData()->ProtocolLAngleLoc = Loc; |
| } |
| |
| SourceLocation getProtocolRAngleLoc() const { |
| return this->getLocalData()->ProtocolRAngleLoc; |
| } |
| |
| void setProtocolRAngleLoc(SourceLocation Loc) { |
| this->getLocalData()->ProtocolRAngleLoc = 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); |
| } |
| |
| |
| ArrayRef<SourceLocation> getProtocolLocs() const { |
| return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols()); |
| } |
| |
| bool hasBaseTypeAsWritten() const { |
| return getLocalData()->HasBaseTypeAsWritten; |
| } |
| |
| void setHasBaseTypeAsWritten(bool HasBaseType) { |
| getLocalData()->HasBaseTypeAsWritten = HasBaseType; |
| } |
| |
| TypeLoc getBaseLoc() const { |
| return getInnerTypeLoc(); |
| } |
| |
| SourceRange getLocalSourceRange() const { |
| SourceLocation start = getTypeArgsLAngleLoc(); |
| if (start.isInvalid()) |
| start = getProtocolLAngleLoc(); |
| SourceLocation end = getProtocolRAngleLoc(); |
| if (end.isInvalid()) |
| end = getTypeArgsRAngleLoc(); |
| return SourceRange(start, end); |
| } |
| |
| void initializeLocal(ASTContext &Context, SourceLocation Loc); |
| |
| unsigned getExtraLocalDataSize() const { |
| return this->getNumTypeArgs() * sizeof(TypeSourceInfo *) |
| + this->getNumProtocols() * sizeof(SourceLocation); |
| } |
| |
| unsigned getExtraLocalDataAlignment() const { |
| static_assert(alignof(ObjCObjectTypeLoc) >= alignof(TypeSourceInfo *), |
| "not enough alignment for tail-allocated data"); |
| return alignof(TypeSourceInfo *); |
| } |
| |
| QualType getInnerType() const { |
| return getTypePtr()->getBaseType(); |
| } |
| }; |
| |
| struct ObjCInterfaceLocInfo { |
| SourceLocation NameLoc; |
| SourceLocation NameEndLoc; |
| }; |
| |
| /// Wrapper for source info for ObjC interfaces. |
| class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<ObjCObjectTypeLoc, |
| ObjCInterfaceTypeLoc, |
| ObjCInterfaceType, |
| ObjCInterfaceLocInfo> { |
| 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 MacroQualifiedLocInfo { |
| SourceLocation ExpansionLoc; |
| }; |
| |
| class MacroQualifiedTypeLoc |
| : public ConcreteTypeLoc<UnqualTypeLoc, MacroQualifiedTypeLoc, |
| MacroQualifiedType, MacroQualifiedLocInfo> { |
| public: |
| void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
| setExpansionLoc(Loc); |
| } |
| |
| TypeLoc getInnerLoc() const { return getInnerTypeLoc(); } |
| |
| const IdentifierInfo *getMacroIdentifier() const { |
| return getTypePtr()->getMacroIdentifier(); |
| } |
| |
| SourceLocation getExpansionLoc() const { |
| return this->getLocalData()->ExpansionLoc; |
| } |
| |
| void setExpansionLoc(SourceLocation Loc) { |
| this->getLocalData()->ExpansionLoc = Loc; |
| } |
| |
| QualType getInnerType() const { return getTypePtr()->getUnderlyingType(); } |
| |
| SourceRange getLocalSourceRange() const { |
| return getInnerLoc().getLocalSourceRange(); |
| } |
| }; |
| |
| struct ParenLocInfo { |
| SourceLocation LParenLoc; |
| SourceLocation RParenLoc; |
| }; |
| |
| class ParenTypeLoc |
| : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType, |
| ParenLocInfo> { |
| 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 AdjustedLocInfo {}; // Nothing. |
| |
| class AdjustedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AdjustedTypeLoc, |
| AdjustedType, AdjustedLocInfo> { |
| public: |
| TypeLoc getOriginalLoc() const { |
| return getInnerTypeLoc(); |
| } |
| |
| void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
| // do nothing |
| } |
| |
| QualType getInnerType() const { |
| // The inner type is the undecayed type, since that's what we have source |
| // location information for. |
| return getTypePtr()->getOriginalType(); |
| } |
| |
| SourceRange getLocalSourceRange() const { return {}; } |
| |
| unsigned getLocalDataSize() const { |
| // sizeof(AdjustedLocInfo) is 1, but we don't need its address to be unique |
| // anyway. TypeLocBuilder can't handle data sizes of 1. |
| return 0; // No data. |
| } |
| }; |
| |
| /// Wrapper for source info for pointers decayed from arrays and |
| /// functions. |
| class DecayedTypeLoc : public InheritingConcreteTypeLoc< |
| AdjustedTypeLoc, DecayedTypeLoc, DecayedType> { |
| }; |
| |
| struct PointerLikeLocInfo { |
| SourceLocation StarLoc; |
| }; |
| |
| /// A base class for |
| template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo> |
| class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived, |
| TypeClass, LocalData> { |
| 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(); |
| } |
| }; |
| |
| /// Wrapper for source info for pointers. |
| class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc, |
| PointerType> { |
| public: |
| SourceLocation getStarLoc() const { |
| return getSigilLoc(); |
| } |
| |
| void setStarLoc(SourceLocation Loc) { |
| setSigilLoc(Loc); |
| } |
| }; |
| |
| /// Wrapper for source info for block pointers. |
| class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc, |
| BlockPointerType> { |
| public: |
| SourceLocation getCaretLoc() const { |
| return getSigilLoc(); |
| } |
| |
| void setCaretLoc(SourceLocation Loc) { |
| setSigilLoc(Loc); |
| } |
| }; |
| |
| struct MemberPointerLocInfo : public PointerLikeLocInfo { |
| TypeSourceInfo *ClassTInfo; |
| }; |
| |
| /// Wrapper for source info for member pointers. |
| class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc, |
| MemberPointerType, |
| MemberPointerLocInfo> { |
| 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(nullptr); |
| } |
| |
| 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<ObjCObjectPointerTypeLoc, |
| ObjCObjectPointerType> { |
| public: |
| SourceLocation getStarLoc() const { |
| return getSigilLoc(); |
| } |
| |
| void setStarLoc(SourceLocation Loc) { |
| setSigilLoc(Loc); |
| } |
| }; |
| |
| class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc, |
| ReferenceType> { |
| public: |
| QualType getInnerType() const { |
| return getTypePtr()->getPointeeTypeAsWritten(); |
| } |
| }; |
| |
| class LValueReferenceTypeLoc : |
| public InheritingConcreteTypeLoc<ReferenceTypeLoc, |
| LValueReferenceTypeLoc, |
| LValueReferenceType> { |
| public: |
| SourceLocation getAmpLoc() const { |
| return getSigilLoc(); |
| } |
| |
| void setAmpLoc(SourceLocation Loc) { |
| setSigilLoc(Loc); |
| } |
| }; |
| |
| class RValueReferenceTypeLoc : |
| public InheritingConcreteTypeLoc<ReferenceTypeLoc, |
| RValueReferenceTypeLoc, |
| RValueReferenceType> { |
| public: |
| SourceLocation getAmpAmpLoc() const { |
| return getSigilLoc(); |
| } |
| |
| void setAmpAmpLoc(SourceLocation Loc) { |
| setSigilLoc(Loc); |
| } |
| }; |
| |
| struct FunctionLocInfo { |
| SourceLocation LocalRangeBegin; |
| SourceLocation LParenLoc; |
| SourceLocation RParenLoc; |
| SourceLocation LocalRangeEnd; |
| }; |
| |
| /// Wrapper for source info for functions. |
| class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
| FunctionTypeLoc, |
| FunctionType, |
| FunctionLocInfo> { |
| bool hasExceptionSpec() const { |
| if (auto *FPT = dyn_cast<FunctionProtoType>(getTypePtr())) { |
| return FPT->hasExceptionSpec(); |
| } |
| return false; |
| } |
| |
| SourceRange *getExceptionSpecRangePtr() const { |
| assert(hasExceptionSpec() && "No exception spec range"); |
| // After the Info comes the ParmVarDecl array, and after that comes the |
| // exception specification information. |
| return (SourceRange *)(getParmArray() + getNumParams()); |
| } |
| |
| 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()); |
| } |
| |
| SourceRange getExceptionSpecRange() const { |
| if (hasExceptionSpec()) |
| return *getExceptionSpecRangePtr(); |
| return {}; |
| } |
| |
| void setExceptionSpecRange(SourceRange R) { |
| if (hasExceptionSpec()) |
| *getExceptionSpecRangePtr() = R; |
| } |
| |
| ArrayRef<ParmVarDecl *> getParams() const { |
| return llvm::makeArrayRef(getParmArray(), getNumParams()); |
| } |
| |
| // ParmVarDecls* are stored after Info, one for each parameter. |
| ParmVarDecl **getParmArray() const { |
| return (ParmVarDecl**) getExtraLocalData(); |
| } |
| |
| unsigned getNumParams() const { |
| if (isa<FunctionNoProtoType>(getTypePtr())) |
| return 0; |
| return cast<FunctionProtoType>(getTypePtr())->getNumParams(); |
| } |
| |
| ParmVarDecl *getParam(unsigned i) const { return getParmArray()[i]; } |
| void setParam(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; } |
| |
| TypeLoc getReturnLoc() 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 = getNumParams(); i != e; ++i) |
| setParam(i, nullptr); |
| if (hasExceptionSpec()) |
| setExceptionSpecRange(Loc); |
| } |
| |
| /// Returns the size of the type source info data block that is |
| /// specific to this type. |
| unsigned getExtraLocalDataSize() const { |
| unsigned ExceptSpecSize = hasExceptionSpec() ? sizeof(SourceRange) : 0; |
| return (getNumParams() * sizeof(ParmVarDecl *)) + ExceptSpecSize; |
| } |
| |
| unsigned getExtraLocalDataAlignment() const { return alignof(ParmVarDecl *); } |
| |
| QualType getInnerType() const { return getTypePtr()->getReturnType(); } |
| }; |
| |
| class FunctionProtoTypeLoc : |
| public InheritingConcreteTypeLoc<FunctionTypeLoc, |
| FunctionProtoTypeLoc, |
| FunctionProtoType> { |
| }; |
| |
| class FunctionNoProtoTypeLoc : |
| public InheritingConcreteTypeLoc<FunctionTypeLoc, |
| FunctionNoProtoTypeLoc, |
| FunctionNoProtoType> { |
| }; |
| |
| struct ArrayLocInfo { |
| SourceLocation LBracketLoc, RBracketLoc; |
| Expr *Size; |
| }; |
| |
| /// Wrapper for source info for arrays. |
| class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
| ArrayTypeLoc, |
| ArrayType, |
| ArrayLocInfo> { |
| 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(nullptr); |
| } |
| |
| QualType getInnerType() const { return getTypePtr()->getElementType(); } |
| }; |
| |
| class ConstantArrayTypeLoc : |
| public InheritingConcreteTypeLoc<ArrayTypeLoc, |
| ConstantArrayTypeLoc, |
| ConstantArrayType> { |
| }; |
| |
| class IncompleteArrayTypeLoc : |
| public InheritingConcreteTypeLoc<ArrayTypeLoc, |
| IncompleteArrayTypeLoc, |
| IncompleteArrayType> { |
| }; |
| |
| class DependentSizedArrayTypeLoc : |
| public InheritingConcreteTypeLoc<ArrayTypeLoc, |
| DependentSizedArrayTypeLoc, |
| DependentSizedArrayType> { |
| public: |
| void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
| ArrayTypeLoc::initializeLocal(Context, Loc); |
| setSizeExpr(getTypePtr()->getSizeExpr()); |
| } |
| }; |
| |
| class VariableArrayTypeLoc : |
| public InheritingConcreteTypeLoc<ArrayTypeLoc, |
| VariableArrayTypeLoc, |
| VariableArrayType> { |
| }; |
| |
| // 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<UnqualTypeLoc, |
| TemplateSpecializationTypeLoc, |
| TemplateSpecializationType, |
| TemplateSpecializationLocInfo> { |
| 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; |
| } |
| |
| /// - 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); |
| } |
| |
| unsigned getExtraLocalDataAlignment() const { |
| return alignof(TemplateArgumentLocInfo); |
| } |
| |
| private: |
| TemplateArgumentLocInfo *getArgInfos() const { |
| return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); |
| } |
| }; |
| |
| struct DependentAddressSpaceLocInfo { |
| Expr *ExprOperand; |
| SourceRange OperandParens; |
| SourceLocation AttrLoc; |
| }; |
| |
| class DependentAddressSpaceTypeLoc |
| : public ConcreteTypeLoc<UnqualTypeLoc, |
| DependentAddressSpaceTypeLoc, |
| DependentAddressSpaceType, |
| DependentAddressSpaceLocInfo> { |
| public: |
| /// The location of the attribute name, i.e. |
| /// int * __attribute__((address_space(11))) |
| /// ^~~~~~~~~~~~~ |
| SourceLocation getAttrNameLoc() const { |
| return getLocalData()->AttrLoc; |
| } |
| void setAttrNameLoc(SourceLocation loc) { |
| getLocalData()->AttrLoc = loc; |
| } |
| |
| /// The attribute's expression operand, if it has one. |
| /// int * __attribute__((address_space(11))) |
| /// ^~ |
| Expr *getAttrExprOperand() const { |
| return getLocalData()->ExprOperand; |
| } |
| void setAttrExprOperand(Expr *e) { |
| getLocalData()->ExprOperand = e; |
| } |
| |
| /// The location of the parentheses around the operand, if there is |
| /// an operand. |
| /// int * __attribute__((address_space(11))) |
| /// ^ ^ |
| SourceRange getAttrOperandParensRange() const { |
| return getLocalData()->OperandParens; |
| } |
| void setAttrOperandParensRange(SourceRange range) { |
| getLocalData()->OperandParens = range; |
| } |
| |
| SourceRange getLocalSourceRange() const { |
| SourceRange range(getAttrNameLoc()); |
| range.setEnd(getAttrOperandParensRange().getEnd()); |
| return range; |
| } |
| |
| /// Returns the type before the address space attribute application |
| /// area. |
| /// int * __attribute__((address_space(11))) * |
| /// ^ ^ |
| QualType getInnerType() const { |
| return this->getTypePtr()->getPointeeType(); |
| } |
| |
| TypeLoc getPointeeTypeLoc() const { |
| return this->getInnerTypeLoc(); |
| } |
| |
| void initializeLocal(ASTContext &Context, SourceLocation loc) { |
| setAttrNameLoc(loc); |
| setAttrOperandParensRange(SourceRange(loc)); |
| setAttrExprOperand(getTypePtr()->getAddrSpaceExpr()); |
| } |
| }; |
| |
| //===----------------------------------------------------------------------===// |
| // |
| // 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<TypeSpecTypeLoc, |
| VectorTypeLoc, |
| VectorType> { |
| }; |
| |
| // FIXME: size expression and attribute locations (or keyword if we |
| // ever fully support altivec syntax). |
| class DependentVectorTypeLoc |
| : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
| DependentVectorTypeLoc, |
| DependentVectorType> {}; |
| |
| // FIXME: size expression and attribute locations. |
| class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc, |
| ExtVectorTypeLoc, |
| ExtVectorType> { |
| }; |
| |
| // FIXME: attribute locations. |
| // For some reason, this isn't a subtype of VectorType. |
| class DependentSizedExtVectorTypeLoc : |
| public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
| DependentSizedExtVectorTypeLoc, |
| DependentSizedExtVectorType> { |
| }; |
| |
| // FIXME: location of the '_Complex' keyword. |
| class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
| ComplexTypeLoc, |
| ComplexType> { |
| }; |
| |
| struct TypeofLocInfo { |
| SourceLocation TypeofLoc; |
| SourceLocation LParenLoc; |
| SourceLocation RParenLoc; |
| }; |
| |
| struct TypeOfExprTypeLocInfo : public TypeofLocInfo { |
| }; |
| |
| struct TypeOfTypeLocInfo : public TypeofLocInfo { |
| TypeSourceInfo* UnderlyingTInfo; |
| }; |
| |
| template <class Derived, class TypeClass, class LocalData = TypeofLocInfo> |
| class TypeofLikeTypeLoc |
| : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> { |
| 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<TypeOfExprTypeLoc, |
| TypeOfExprType, |
| TypeOfExprTypeLocInfo> { |
| 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<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> { |
| public: |
| QualType getUnderlyingType() const { |
| return this->getTypePtr()->getUnderlyingType(); |
| } |
| |
| TypeSourceInfo* getUnderlyingTInfo() const { |
| return this->getLocalData()->UnderlyingTInfo; |
| } |
| |
| void setUnderlyingTInfo(TypeSourceInfo* TI) const { |
| this->getLocalData()->UnderlyingTInfo = TI; |
| } |
| |
| void initializeLocal(ASTContext &Context, SourceLocation Loc); |
| }; |
| |
| // FIXME: location of the 'decltype' and parens. |
| class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
| DecltypeTypeLoc, |
| DecltypeType> { |
| 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<UnqualTypeLoc, |
| UnaryTransformTypeLoc, |
| UnaryTransformType, |
| UnaryTransformTypeLocInfo> { |
| 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); |
| }; |
| |
| class DeducedTypeLoc |
| : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DeducedTypeLoc, |
| DeducedType> {}; |
| |
| class AutoTypeLoc |
| : public InheritingConcreteTypeLoc<DeducedTypeLoc, AutoTypeLoc, AutoType> { |
| }; |
| |
| class DeducedTemplateSpecializationTypeLoc |
| : public InheritingConcreteTypeLoc<DeducedTypeLoc, |
| DeducedTemplateSpecializationTypeLoc, |
| DeducedTemplateSpecializationType> { |
| public: |
| SourceLocation getTemplateNameLoc() const { |
| return getNameLoc(); |
| } |
| |
| void setTemplateNameLoc(SourceLocation Loc) { |
| setNameLoc(Loc); |
| } |
| }; |
| |
| struct ElaboratedLocInfo { |
| SourceLocation ElaboratedKWLoc; |
| |
| /// Data associated with the nested-name-specifier location. |
| void *QualifierData; |
| }; |
| |
| class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
| ElaboratedTypeLoc, |
| ElaboratedType, |
| ElaboratedLocInfo> { |
| 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<UnqualTypeLoc, |
| DependentNameTypeLoc, |
| DependentNameType, |
| DependentNameLocInfo> { |
| 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<UnqualTypeLoc, |
| DependentTemplateSpecializationTypeLoc, |
| DependentTemplateSpecializationType, |
| DependentTemplateSpecializationLocInfo> { |
| 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 = nullptr; |
| 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); |
| } |
| |
| unsigned getExtraLocalDataAlignment() const { |
| return alignof(TemplateArgumentLocInfo); |
| } |
| |
| private: |
| TemplateArgumentLocInfo *getArgInfos() const { |
| return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); |
| } |
| }; |
| |
| struct PackExpansionTypeLocInfo { |
| SourceLocation EllipsisLoc; |
| }; |
| |
| class PackExpansionTypeLoc |
| : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc, |
| PackExpansionType, PackExpansionTypeLocInfo> { |
| 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<UnqualTypeLoc, AtomicTypeLoc, |
| AtomicType, AtomicTypeLocInfo> { |
| 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(); |
| } |
| }; |
| |
| struct PipeTypeLocInfo { |
| SourceLocation KWLoc; |
| }; |
| |
| class PipeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, PipeTypeLoc, PipeType, |
| PipeTypeLocInfo> { |
| public: |
| TypeLoc getValueLoc() const { return this->getInnerTypeLoc(); } |
| |
| SourceRange getLocalSourceRange() const { return SourceRange(getKWLoc()); } |
| |
| SourceLocation getKWLoc() const { return this->getLocalData()->KWLoc; } |
| void setKWLoc(SourceLocation Loc) { this->getLocalData()->KWLoc = Loc; } |
| |
| void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
| setKWLoc(Loc); |
| } |
| |
| QualType getInnerType() const { return this->getTypePtr()->getElementType(); } |
| }; |
| |
| template <typename T> |
| inline T TypeLoc::getAsAdjusted() const { |
| TypeLoc Cur = *this; |
| while (!T::isKind(Cur)) { |
| if (auto PTL = Cur.getAs<ParenTypeLoc>()) |
| Cur = PTL.getInnerLoc(); |
| else if (auto ATL = Cur.getAs<AttributedTypeLoc>()) |
| Cur = ATL.getModifiedLoc(); |
| else if (auto ETL = Cur.getAs<ElaboratedTypeLoc>()) |
| Cur = ETL.getNamedTypeLoc(); |
| else if (auto ATL = Cur.getAs<AdjustedTypeLoc>()) |
| Cur = ATL.getOriginalLoc(); |
| else if (auto MQL = Cur.getAs<MacroQualifiedTypeLoc>()) |
| Cur = MQL.getInnerLoc(); |
| else |
| break; |
| } |
| return Cur.getAs<T>(); |
| } |
| |
| } // namespace clang |
| |
| #endif // LLVM_CLANG_AST_TYPELOC_H |