diff options
-rw-r--r-- | include/clang/AST/TypeLoc.h | 521 | ||||
-rw-r--r-- | include/clang/AST/TypeLocNodes.def | 16 | ||||
-rw-r--r-- | include/clang/AST/TypeLocVisitor.h | 25 | ||||
-rw-r--r-- | lib/AST/TypeLoc.cpp | 213 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderDecl.cpp | 5 | ||||
-rw-r--r-- | lib/Frontend/PCHWriterDecl.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 3 |
7 files changed, 396 insertions, 392 deletions
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index a6184375e0..ab23a7985c 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -20,6 +20,7 @@ namespace clang { class ParmVarDecl; class TypeSpecLoc; class DeclaratorInfo; + class UnqualTypeLoc; /// \brief Base wrapper for a particular "section" of type source info. /// @@ -27,22 +28,31 @@ namespace clang { /// get at the actual information. class TypeLoc { protected: - QualType Ty; + // The correctness of this relies on the property that, for Type *Ty, + // QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty + void *Ty; void *Data; public: - TypeLoc() : Data(0) { } - TypeLoc(QualType ty, void *opaqueData) : Ty(ty), Data(opaqueData) { } + TypeLoc() : Ty(0), Data(0) { } + TypeLoc(QualType ty, void *opaqueData) + : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { } + TypeLoc(Type *ty, void *opaqueData) + : Ty(ty), Data(opaqueData) { } - bool isNull() const { return Ty.isNull(); } - operator bool() const { return !isNull(); } + 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 getSourceType() const { return Ty; } + QualType getSourceType() const { return QualType::getFromOpaquePtr(Ty); } + + Type *getSourceTypePtr() const { + return QualType::getFromOpaquePtr(Ty).getTypePtr(); + } /// \brief Get the pointer where source information is stored. void *getOpaqueData() const { return Data; } @@ -57,12 +67,17 @@ public: SourceRange getTypeSpecRange() const; /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const; + unsigned getFullDataSize() const { + return getFullDataSizeForType(getSourceType()); + } /// \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; + /// \brief Skips past any qualifiers, if this is qualified. + UnqualTypeLoc getUnqualifiedLoc() const; + friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) { return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data; } @@ -74,144 +89,296 @@ public: static bool classof(const TypeLoc *TL) { return true; } }; +/// \brief Wrapper of type source information for a type with +/// no direct quqlaifiers. +class UnqualTypeLoc : public TypeLoc { +public: + UnqualTypeLoc() {} + UnqualTypeLoc(Type *Ty, void *Data) : TypeLoc(Ty, Data) {} + + Type *getSourceTypePtr() const { + return reinterpret_cast<Type*>(Ty); + } + + static bool classof(const TypeLoc *TL) { + return !TL->getSourceType().hasQualifiers(); + } + static bool classof(const UnqualTypeLoc *TL) { return true; } +}; + +/// \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 QualifiedLoc : public TypeLoc { +public: + SourceRange getSourceRange() const { + return SourceRange(); + } + + UnqualTypeLoc getUnqualifiedLoc() const { + return UnqualTypeLoc(getSourceTypePtr(), Data); + } + + /// \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(getSourceType().getUnqualifiedType()); + } + + static bool classof(const TypeLoc *TL) { + return TL->getSourceType().hasQualifiers(); + } + static bool classof(const QualifiedLoc *TL) { return true; } +}; + +inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { + if (isa<QualifiedLoc>(this)) + return cast<QualifiedLoc>(this)->getUnqualifiedLoc(); + return cast<UnqualTypeLoc>(*this); +} + /// \brief Base wrapper of type source info data for type-spec types. -class TypeSpecLoc : public TypeLoc { +class TypeSpecLoc : public UnqualTypeLoc { public: - static bool classof(const TypeLoc *TL); + static bool classof(const TypeLoc *TL) { + return (UnqualTypeLoc::classof(TL) && + classof(static_cast<const UnqualTypeLoc*>(TL))); + } + static bool classof(const UnqualTypeLoc *TL); static bool classof(const TypeSpecLoc *TL) { return true; } }; +inline SourceRange TypeLoc::getTypeSpecRange() const { + return getTypeSpecLoc().getSourceRange(); +} + /// \brief Base wrapper of type source info data for types part of a declarator, /// excluding type-spec types. -class DeclaratorLoc : public TypeLoc { +class DeclaratorLoc : public UnqualTypeLoc { public: /// \brief Find the TypeSpecLoc that is part of this DeclaratorLoc. TypeSpecLoc getTypeSpecLoc() const; - static bool classof(const TypeLoc *TL); + static bool classof(const TypeLoc *TL) { + return (UnqualTypeLoc::classof(TL) && + classof(static_cast<const UnqualTypeLoc*>(TL))); + } + static bool classof(const UnqualTypeLoc *TL); static bool classof(const DeclaratorLoc *TL) { return true; } }; + +/// A metaprogramming base class for TypeLoc classes which correspond +/// to a particular Type subclass. +/// +/// \param Base a class from which to derive +/// \param Derived the class deriving from this one +/// \param TypeClass the concrete Type subclass which this +/// \param 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 override ha +template <class Base, class Derived, class TypeClass, class LocalData> +class ConcreteTypeLoc : public Base { + + const Derived *asDerived() const { + return static_cast<const Derived*>(this); + } + +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(); + } + + static bool classof(const TypeLoc *TL) { + return Derived::classofType(TL->getSourceTypePtr()); + } + static bool classof(const UnqualTypeLoc *TL) { + return Derived::classofType(TL->getSourceTypePtr()); + } + static bool classof(const Derived *TL) { + return true; + } + + static bool classofType(const Type *Ty) { + return TypeClass::classof(Ty); + } + +protected: + TypeClass *getTypePtr() const { + return cast<TypeClass>(Base::getSourceTypePtr()); + } + + unsigned getExtraLocalDataSize() const { + return 0; + } + + 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 { + return getLocalData() + 1; + } + + void *getNonLocalData() const { + return static_cast<char*>(Base::Data) + asDerived()->getLocalDataSize(); + } + + bool hasInnerType() const { + return false; + } + + TypeLoc getInnerTypeLoc() const { + assert(asDerived()->hasInnerType()); + return TypeLoc(asDerived()->getInnerType(), getNonLocalData()); + } + +private: + unsigned getInnerTypeSize() const { + if (asDerived()->hasInnerType()) + return getInnerTypeLoc().getFullDataSize(); + return 0; + } + + // Required here because my metaprogramming is too weak to avoid it. + QualType getInnerType() const { + assert(0 && "getInnerType() not overridden"); + return QualType(); + } +}; + + +struct DefaultTypeSpecLocInfo { + SourceLocation StartLoc; +}; + /// \brief The default wrapper for type-spec types that are not handled by /// another specific wrapper. -class DefaultTypeSpecLoc : public TypeSpecLoc { - struct Info { - SourceLocation StartLoc; - }; - +class DefaultTypeSpecLoc : public ConcreteTypeLoc<TypeSpecLoc, + DefaultTypeSpecLoc, + Type, + DefaultTypeSpecLocInfo> { public: SourceLocation getStartLoc() const { - return static_cast<Info*>(Data)->StartLoc; + return getLocalData()->StartLoc; } void setStartLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->StartLoc = Loc; + getLocalData()->StartLoc = Loc; } SourceRange getSourceRange() const { return SourceRange(getStartLoc(), getStartLoc()); } - /// \brief Returns the size of the type source info data block that is - /// specific to this type. - unsigned getLocalDataSize() const { return sizeof(Info); } + static bool classofType(const Type *T); +}; - /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const { return getLocalDataSize(); } - static bool classof(const TypeLoc *TL); - static bool classof(const DefaultTypeSpecLoc *TL) { return true; } +struct TypedefLocInfo { + SourceLocation NameLoc; }; /// \brief Wrapper for source info for typedefs. -class TypedefLoc : public TypeSpecLoc { - struct Info { - SourceLocation NameLoc; - }; - +class TypedefLoc : public ConcreteTypeLoc<TypeSpecLoc,TypedefLoc, + TypedefType,TypedefLocInfo> { public: SourceLocation getNameLoc() const { - return static_cast<Info*>(Data)->NameLoc; + return getLocalData()->NameLoc; } void setNameLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->NameLoc = Loc; + getLocalData()->NameLoc = Loc; } SourceRange getSourceRange() const { return SourceRange(getNameLoc(), getNameLoc()); } TypedefDecl *getTypedefDecl() const { - return cast<TypedefType>(Ty)->getDecl(); + return getTypePtr()->getDecl(); } +}; - /// \brief Returns the size of the type source info data block that is - /// specific to this type. - unsigned getLocalDataSize() const { return sizeof(Info); } - - /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const { return getLocalDataSize(); } - static bool classof(const TypeLoc *TL); - static bool classof(const TypedefLoc *TL) { return true; } +struct ObjCInterfaceLocInfo { + SourceLocation NameLoc; }; /// \brief Wrapper for source info for ObjC interfaces. -class ObjCInterfaceLoc : public TypeSpecLoc { - struct Info { - SourceLocation NameLoc; - }; - +class ObjCInterfaceLoc : public ConcreteTypeLoc<TypeSpecLoc, + ObjCInterfaceLoc, + ObjCInterfaceType, + ObjCInterfaceLocInfo> { public: SourceLocation getNameLoc() const { - return static_cast<Info*>(Data)->NameLoc; + return getLocalData()->NameLoc; } void setNameLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->NameLoc = Loc; + getLocalData()->NameLoc = Loc; } SourceRange getSourceRange() const { return SourceRange(getNameLoc(), getNameLoc()); } ObjCInterfaceDecl *getIFaceDecl() const { - return cast<ObjCInterfaceType>(Ty)->getDecl(); + return getTypePtr()->getDecl(); } +}; - /// \brief Returns the size of the type source info data block that is - /// specific to this type. - unsigned getLocalDataSize() const { return sizeof(Info); } - - /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const { return getLocalDataSize(); } - static bool classof(const TypeLoc *TL); - static bool classof(const TypedefLoc *TL) { return true; } +struct ObjCProtocolListLocInfo { + SourceLocation LAngleLoc, RAngleLoc; }; /// \brief Wrapper for source info for ObjC protocol lists. -class ObjCProtocolListLoc : public TypeSpecLoc { - struct Info { - SourceLocation LAngleLoc, RAngleLoc; - }; +class ObjCProtocolListLoc : public ConcreteTypeLoc<TypeSpecLoc, + ObjCProtocolListLoc, + ObjCProtocolListType, + ObjCProtocolListLocInfo> { // SourceLocations are stored after Info, one for each Protocol. SourceLocation *getProtocolLocArray() const { - return reinterpret_cast<SourceLocation*>(static_cast<Info*>(Data) + 1); + return (SourceLocation*) getExtraLocalData(); } public: SourceLocation getLAngleLoc() const { - return static_cast<Info*>(Data)->LAngleLoc; + return getLocalData()->LAngleLoc; } void setLAngleLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->LAngleLoc = Loc; + getLocalData()->LAngleLoc = Loc; } SourceLocation getRAngleLoc() const { - return static_cast<Info*>(Data)->RAngleLoc; + return getLocalData()->RAngleLoc; } void setRAngleLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->RAngleLoc = Loc; + getLocalData()->RAngleLoc = Loc; } unsigned getNumProtocols() const { - return cast<ObjCProtocolListType>(Ty)->getNumProtocols(); + return getTypePtr()->getNumProtocols(); } SourceLocation getProtocolLoc(unsigned i) const { @@ -225,12 +392,11 @@ public: ObjCProtocolDecl *getProtocol(unsigned i) const { assert(i < getNumProtocols() && "Index is out of bounds!"); - return *(cast<ObjCProtocolListType>(Ty)->qual_begin() + i); + return *(getTypePtr()->qual_begin() + i); } TypeLoc getBaseTypeLoc() const { - void *Next = static_cast<char*>(Data) + getLocalDataSize(); - return TypeLoc(cast<ObjCProtocolListType>(Ty)->getBaseType(), Next); + return getInnerTypeLoc(); } SourceRange getSourceRange() const { @@ -239,36 +405,34 @@ public: /// \brief Returns the size of the type source info data block that is /// specific to this type. - unsigned getLocalDataSize() const { - return sizeof(Info) + getNumProtocols() * sizeof(SourceLocation); + unsigned getExtraLocalDataSize() const { + return getNumProtocols() * sizeof(SourceLocation); } - /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const { - return getLocalDataSize() + getBaseTypeLoc().getFullDataSize(); - } + bool hasInnerType() const { return true; } + QualType getInnerType() const { return getTypePtr()->getBaseType(); } +}; - static bool classof(const TypeLoc *TL); - static bool classof(const ObjCProtocolListLoc *TL) { return true; } + +struct PointerLocInfo { + SourceLocation StarLoc; }; /// \brief Wrapper for source info for pointers. -class PointerLoc : public DeclaratorLoc { - struct Info { - SourceLocation StarLoc; - }; - +class PointerLoc : public ConcreteTypeLoc<DeclaratorLoc, + PointerLoc, + PointerType, + PointerLocInfo> { public: SourceLocation getStarLoc() const { - return static_cast<Info*>(Data)->StarLoc; + return getLocalData()->StarLoc; } void setStarLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->StarLoc = Loc; + getLocalData()->StarLoc = Loc; } TypeLoc getPointeeLoc() const { - void *Next = static_cast<char*>(Data) + getLocalDataSize(); - return TypeLoc(cast<PointerType>(Ty)->getPointeeType(), Next); + return getInnerTypeLoc(); } /// \brief Find the TypeSpecLoc that is part of this PointerLoc. @@ -280,36 +444,30 @@ public: return SourceRange(getStarLoc(), getStarLoc()); } - /// \brief Returns the size of the type source info data block that is - /// specific to this type. - unsigned getLocalDataSize() const { return sizeof(Info); } + bool hasInnerType() const { return true; } + QualType getInnerType() const { return getTypePtr()->getPointeeType(); } +}; - /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const { - return getLocalDataSize() + getPointeeLoc().getFullDataSize(); - } - static bool classof(const TypeLoc *TL); - static bool classof(const PointerLoc *TL) { return true; } +struct BlockPointerLocInfo { + SourceLocation CaretLoc; }; /// \brief Wrapper for source info for block pointers. -class BlockPointerLoc : public DeclaratorLoc { - struct Info { - SourceLocation CaretLoc; - }; - +class BlockPointerLoc : public ConcreteTypeLoc<DeclaratorLoc, + BlockPointerLoc, + BlockPointerType, + BlockPointerLocInfo> { public: SourceLocation getCaretLoc() const { - return static_cast<Info*>(Data)->CaretLoc; + return getLocalData()->CaretLoc; } void setCaretLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->CaretLoc = Loc; + getLocalData()->CaretLoc = Loc; } TypeLoc getPointeeLoc() const { - void *Next = static_cast<char*>(Data) + getLocalDataSize(); - return TypeLoc(cast<BlockPointerType>(Ty)->getPointeeType(), Next); + return getInnerTypeLoc(); } /// \brief Find the TypeSpecLoc that is part of this BlockPointerLoc. @@ -321,36 +479,30 @@ public: return SourceRange(getCaretLoc(), getCaretLoc()); } - /// \brief Returns the size of the type source info data block that is - /// specific to this type. - unsigned getLocalDataSize() const { return sizeof(Info); } + bool hasInnerType() const { return true; } + QualType getInnerType() const { return getTypePtr()->getPointeeType(); } +}; - /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const { - return getLocalDataSize() + getPointeeLoc().getFullDataSize(); - } - static bool classof(const TypeLoc *TL); - static bool classof(const BlockPointerLoc *TL) { return true; } +struct MemberPointerLocInfo { + SourceLocation StarLoc; }; /// \brief Wrapper for source info for member pointers. -class MemberPointerLoc : public DeclaratorLoc { - struct Info { - SourceLocation StarLoc; - }; - +class MemberPointerLoc : public ConcreteTypeLoc<DeclaratorLoc, + MemberPointerLoc, + MemberPointerType, + MemberPointerLocInfo> { public: SourceLocation getStarLoc() const { - return static_cast<Info*>(Data)->StarLoc; + return getLocalData()->StarLoc; } void setStarLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->StarLoc = Loc; + getLocalData()->StarLoc = Loc; } TypeLoc getPointeeLoc() const { - void *Next = static_cast<char*>(Data) + getLocalDataSize(); - return TypeLoc(cast<MemberPointerType>(Ty)->getPointeeType(), Next); + return getInnerTypeLoc(); } /// \brief Find the TypeSpecLoc that is part of this MemberPointerLoc. @@ -362,36 +514,30 @@ public: return SourceRange(getStarLoc(), getStarLoc()); } - /// \brief Returns the size of the type source info data block that is - /// specific to this type. - unsigned getLocalDataSize() const { return sizeof(Info); } + bool hasInnerType() const { return true; } + QualType getInnerType() const { return getTypePtr()->getPointeeType(); } +}; - /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const { - return getLocalDataSize() + getPointeeLoc().getFullDataSize(); - } - static bool classof(const TypeLoc *TL); - static bool classof(const MemberPointerLoc *TL) { return true; } +struct ReferenceLocInfo { + SourceLocation AmpLoc; }; /// \brief Wrapper for source info for references. -class ReferenceLoc : public DeclaratorLoc { - struct Info { - SourceLocation AmpLoc; - }; - +class ReferenceLoc : public ConcreteTypeLoc<DeclaratorLoc, + ReferenceLoc, + ReferenceType, + ReferenceLocInfo> { public: SourceLocation getAmpLoc() const { - return static_cast<Info*>(Data)->AmpLoc; + return getLocalData()->AmpLoc; } void setAmpLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->AmpLoc = Loc; + getLocalData()->AmpLoc = Loc; } TypeLoc getPointeeLoc() const { - void *Next = static_cast<char*>(Data) + getLocalDataSize(); - return TypeLoc(cast<ReferenceType>(Ty)->getPointeeType(), Next); + return TypeLoc(getTypePtr()->getPointeeType(), getNonLocalData()); } /// \brief Find the TypeSpecLoc that is part of this ReferenceLoc. @@ -403,48 +549,44 @@ public: return SourceRange(getAmpLoc(), getAmpLoc()); } - /// \brief Returns the size of the type source info data block that is - /// specific to this type. - unsigned getLocalDataSize() const { return sizeof(Info); } + bool hasInnerType() const { return true; } + QualType getInnerType() const { return getTypePtr()->getPointeeType(); } +}; - /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const { - return getLocalDataSize() + getPointeeLoc().getFullDataSize(); - } - static bool classof(const TypeLoc *TL); - static bool classof(const ReferenceLoc *TL) { return true; } +struct FunctionLocInfo { + SourceLocation LParenLoc, RParenLoc; }; /// \brief Wrapper for source info for functions. -class FunctionLoc : public DeclaratorLoc { - struct Info { - SourceLocation LParenLoc, RParenLoc; - }; +class FunctionLoc : public ConcreteTypeLoc<DeclaratorLoc, + FunctionLoc, + FunctionType, + FunctionLocInfo> { // ParmVarDecls* are stored after Info, one for each argument. ParmVarDecl **getParmArray() const { - return reinterpret_cast<ParmVarDecl**>(static_cast<Info*>(Data) + 1); + return (ParmVarDecl**) getExtraLocalData(); } public: SourceLocation getLParenLoc() const { - return static_cast<Info*>(Data)->LParenLoc; + return getLocalData()->LParenLoc; } void setLParenLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->LParenLoc = Loc; + getLocalData()->LParenLoc = Loc; } SourceLocation getRParenLoc() const { - return static_cast<Info*>(Data)->RParenLoc; + return getLocalData()->RParenLoc; } void setRParenLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->RParenLoc = Loc; + getLocalData()->RParenLoc = Loc; } unsigned getNumArgs() const { - if (isa<FunctionNoProtoType>(Ty)) + if (isa<FunctionNoProtoType>(getTypePtr())) return 0; - return cast<FunctionProtoType>(Ty)->getNumArgs(); + return cast<FunctionProtoType>(getTypePtr())->getNumArgs(); } ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; } void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; } @@ -452,8 +594,7 @@ public: TypeLoc getArgLoc(unsigned i) const; TypeLoc getResultLoc() const { - void *Next = static_cast<char*>(Data) + getLocalDataSize(); - return TypeLoc(cast<FunctionType>(Ty)->getResultType(), Next); + return getInnerTypeLoc(); } /// \brief Find the TypeSpecLoc that is part of this FunctionLoc. @@ -466,50 +607,49 @@ public: /// \brief Returns the size of the type source info data block that is /// specific to this type. - unsigned getLocalDataSize() const { - return sizeof(Info) + getNumArgs() * sizeof(ParmVarDecl*); + unsigned getExtraLocalDataSize() const { + return getNumArgs() * sizeof(ParmVarDecl*); } - /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const { - return getLocalDataSize() + getResultLoc().getFullDataSize(); - } + bool hasInnerType() const { return true; } + QualType getInnerType() const { return getTypePtr()->getResultType(); } +}; + - static bool classof(const TypeLoc *TL); - static bool classof(const FunctionLoc *TL) { return true; } +struct ArrayLocInfo { + SourceLocation LBracketLoc, RBracketLoc; + Expr *Size; }; /// \brief Wrapper for source info for arrays. -class ArrayLoc : public DeclaratorLoc { - struct Info { - SourceLocation LBracketLoc, RBracketLoc; - Expr *Size; - }; +class ArrayLoc : public ConcreteTypeLoc<DeclaratorLoc, + ArrayLoc, + ArrayType, + ArrayLocInfo> { public: SourceLocation getLBracketLoc() const { - return static_cast<Info*>(Data)->LBracketLoc; + return getLocalData()->LBracketLoc; } void setLBracketLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->LBracketLoc = Loc; + getLocalData()->LBracketLoc = Loc; } SourceLocation getRBracketLoc() const { - return static_cast<Info*>(Data)->RBracketLoc; + return getLocalData()->RBracketLoc; } void setRBracketLoc(SourceLocation Loc) { - static_cast<Info*>(Data)->RBracketLoc = Loc; + getLocalData()->RBracketLoc = Loc; } Expr *getSizeExpr() const { - return static_cast<Info*>(Data)->Size; + return getLocalData()->Size; } void setSizeExpr(Expr *Size) { - static_cast<Info*>(Data)->Size = Size; + getLocalData()->Size = Size; } TypeLoc getElementLoc() const { - void *Next = static_cast<char*>(Data) + getLocalDataSize(); - return TypeLoc(cast<ArrayType>(Ty)->getElementType(), Next); + return getInnerTypeLoc(); } /// \brief Find the TypeSpecLoc that is part of this ArrayLoc. @@ -520,17 +660,8 @@ public: return SourceRange(getLBracketLoc(), getRBracketLoc()); } - /// \brief Returns the size of the type source info data block that is - /// specific to this type. - unsigned getLocalDataSize() const { return sizeof(Info); } - - /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const { - return getLocalDataSize() + getElementLoc().getFullDataSize(); - } - - static bool classof(const TypeLoc *TL); - static bool classof(const ArrayLoc *TL) { return true; } + bool hasInnerType() const { return true; } + QualType getInnerType() const { return getTypePtr()->getElementType(); } }; } diff --git a/include/clang/AST/TypeLocNodes.def b/include/clang/AST/TypeLocNodes.def index 107ea85479..ecf7cc5c29 100644 --- a/include/clang/AST/TypeLocNodes.def +++ b/include/clang/AST/TypeLocNodes.def @@ -12,7 +12,9 @@ // base class (e.g., "TypeSpecLoc" or "DeclaratorLoc"), and the Type subclass // that the TypeLoc is associated with. // -// TYPELOC(Class, Base, Type) - Description of the TypeLoc subclass. +// TYPELOC(Class, Base) - A TypeLoc subclass. +// +// UNQUAL_TYPELOC(Class, Base, Type) - An UnqualTypeLoc subclass. // // ABSTRACT_TYPELOC(Class) - Refers to TypeSpecLoc and DeclaratorLoc. // @@ -23,16 +25,20 @@ // //===----------------------------------------------------------------------===// +#ifndef UNQUAL_TYPELOC +# define UNQUAL_TYPELOC(Class, Base, Type) TYPELOC(Class, Base) +#endif + #ifndef ABSTRACT_TYPELOC -# define ABSTRACT_TYPELOC(Class) TYPELOC(Class, TypeLoc, Type) +# define ABSTRACT_TYPELOC(Class) TYPELOC(Class, TypeLoc) #endif #ifndef TYPESPEC_TYPELOC -# define TYPESPEC_TYPELOC(Class, Type) TYPELOC(Class, TypeSpecLoc, Type) +# define TYPESPEC_TYPELOC(Class, Type) UNQUAL_TYPELOC(Class, TypeSpecLoc, Type) #endif #ifndef DECLARATOR_TYPELOC -# define DECLARATOR_TYPELOC(Class, Type) TYPELOC(Class, DeclaratorLoc, Type) +# define DECLARATOR_TYPELOC(Class, Type) UNQUAL_TYPELOC(Class, DeclaratorLoc, Type) #endif TYPESPEC_TYPELOC(DefaultTypeSpecLoc, Type) @@ -47,9 +53,11 @@ DECLARATOR_TYPELOC(FunctionLoc, FunctionType) DECLARATOR_TYPELOC(ArrayLoc, ArrayType) ABSTRACT_TYPELOC(DeclaratorLoc) ABSTRACT_TYPELOC(TypeSpecLoc) +TYPELOC(QualifiedLoc, TypeLoc) #undef DECLARATOR_TYPELOC #undef TYPESPEC_TYPELOC #undef ABSTRACT_TYPELOC +#undef UNQUAL_TYPELOC #undef TYPELOC diff --git a/include/clang/AST/TypeLocVisitor.h b/include/clang/AST/TypeLocVisitor.h index df386cab6f..a96757f123 100644 --- a/include/clang/AST/TypeLocVisitor.h +++ b/include/clang/AST/TypeLocVisitor.h @@ -25,12 +25,14 @@ template<typename ImplClass, typename RetTy=void> class TypeLocVisitor { class TypeDispatch : public TypeVisitor<TypeDispatch, RetTy> { ImplClass *Impl; - TypeLoc TyLoc; + UnqualTypeLoc TyLoc; public: - TypeDispatch(ImplClass *impl, TypeLoc &tyLoc) : Impl(impl), TyLoc(tyLoc) { } + TypeDispatch(ImplClass *impl, UnqualTypeLoc &tyLoc) + : Impl(impl), TyLoc(tyLoc) { } +#define TYPELOC(CLASS, BASE) #define ABSTRACT_TYPELOC(CLASS) -#define TYPELOC(CLASS, PARENT, TYPE) \ +#define UNQUAL_TYPELOC(CLASS, PARENT, TYPE) \ RetTy Visit##TYPE(TYPE *) { \ return Impl->Visit##CLASS(reinterpret_cast<CLASS&>(TyLoc)); \ } @@ -39,13 +41,22 @@ class TypeLocVisitor { public: RetTy Visit(TypeLoc TyLoc) { + if (isa<QualifiedLoc>(TyLoc)) + return static_cast<ImplClass*>(this)-> + VisitQualifiedLoc(cast<QualifiedLoc>(TyLoc)); + + return Visit(cast<UnqualTypeLoc>(TyLoc)); + } + + RetTy Visit(UnqualTypeLoc TyLoc) { TypeDispatch TD(static_cast<ImplClass*>(this), TyLoc); - return TD.Visit(TyLoc.getSourceType().getTypePtr()); + return TD.Visit(TyLoc.getSourceTypePtr()); } -#define TYPELOC(CLASS, PARENT, TYPE) RetTy Visit##CLASS(CLASS TyLoc) { \ - DISPATCH(PARENT); \ -} +#define TYPELOC(CLASS, PARENT) \ + RetTy Visit##CLASS(CLASS TyLoc) { \ + DISPATCH(PARENT); \ + } #include "clang/AST/TypeLocNodes.def" RetTy VisitTypeLoc(TypeLoc TyLoc) { return RetTy(); } diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index c24477ae81..04e708370a 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Support/raw_ostream.h" #include "clang/AST/TypeLocVisitor.h" using namespace clang; @@ -24,7 +25,7 @@ namespace { class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> { public: #define ABSTRACT_TYPELOC(CLASS) -#define TYPELOC(CLASS, PARENT, TYPE) \ +#define TYPELOC(CLASS, PARENT) \ SourceRange Visit##CLASS(CLASS TyLoc) { return TyLoc.getSourceRange(); } #include "clang/AST/TypeLocNodes.def" @@ -42,25 +43,14 @@ SourceRange TypeLoc::getSourceRange() const { return TypeLocRanger().Visit(*this); } -/// \brief Returns the size of type source info data block for the given type. -unsigned TypeLoc::getFullDataSizeForType(QualType Ty) { - return TypeLoc(Ty, 0).getFullDataSize(); -} - /// \brief Find the TypeSpecLoc that is part of this TypeLoc. TypeSpecLoc TypeLoc::getTypeSpecLoc() const { if (isNull()) return TypeSpecLoc(); - - if (const DeclaratorLoc *DL = dyn_cast<DeclaratorLoc>(this)) + UnqualTypeLoc Cur = getUnqualifiedLoc(); + if (const DeclaratorLoc *DL = dyn_cast<DeclaratorLoc>(&Cur)) return DL->getTypeSpecLoc(); - return cast<TypeSpecLoc>(*this); -} - -/// \brief Find the TypeSpecLoc that is part of this TypeLoc and return its -/// SourceRange. -SourceRange TypeLoc::getTypeSpecRange() const { - return getTypeSpecLoc().getSourceRange(); + return cast<TypeSpecLoc>(Cur); } namespace { @@ -69,7 +59,7 @@ namespace { class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> { public: #define ABSTRACT_TYPELOC(CLASS) -#define TYPELOC(CLASS, PARENT, TYPE) \ +#define TYPELOC(CLASS, PARENT) \ unsigned Visit##CLASS(CLASS TyLoc) { return TyLoc.getFullDataSize(); } #include "clang/AST/TypeLocNodes.def" @@ -82,9 +72,9 @@ public: } /// \brief Returns the size of the type source info data block. -unsigned TypeLoc::getFullDataSize() const { - if (isNull()) return 0; - return TypeSizer().Visit(*this); +unsigned TypeLoc::getFullDataSizeForType(QualType Ty) { + if (Ty.isNull()) return 0; + return TypeSizer().Visit(TypeLoc(Ty, 0)); } namespace { @@ -93,13 +83,16 @@ namespace { /// TypeLoc is a PointerLoc and next TypeLoc is for "int". class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> { public: -#define TYPELOC(CLASS, PARENT, TYPE) +#define TYPELOC(CLASS, PARENT) #define DECLARATOR_TYPELOC(CLASS, TYPE) \ - TypeLoc Visit##CLASS(CLASS TyLoc); + TypeLoc Visit##CLASS(CLASS TyLoc); #include "clang/AST/TypeLocNodes.def" TypeLoc VisitTypeSpecLoc(TypeLoc TyLoc) { return TypeLoc(); } TypeLoc VisitObjCProtocolListLoc(ObjCProtocolListLoc TL); + TypeLoc VisitQualifiedLoc(QualifiedLoc TyLoc) { + return TyLoc.getUnqualifiedLoc(); + } TypeLoc VisitTypeLoc(TypeLoc TyLoc) { assert(0 && "A declarator loc wrapper was not handled!"); @@ -135,7 +128,10 @@ TypeLoc NextLoc::VisitArrayLoc(ArrayLoc TL) { /// \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 TypeLoc::getNextTypeLoc() const { - return NextLoc().Visit(*this); + //llvm::errs() << "getNextTypeLoc: Ty=" << Ty << ", Data=" << Data << "\n"; + TypeLoc Tmp = NextLoc().Visit(*this); + //llvm::errs() << " result: Ty=" << Tmp.Ty << ", Data=" << Tmp.Data << "\n"; + return Tmp; } //===----------------------------------------------------------------------===// @@ -150,7 +146,7 @@ public: } -bool TypeSpecLoc::classof(const TypeLoc *TL) { +bool TypeSpecLoc::classof(const UnqualTypeLoc *TL) { return TypeSpecChecker().Visit(*TL); } @@ -163,7 +159,7 @@ namespace { /// \brief Return the TypeSpecLoc for the visited DeclaratorLoc. class TypeSpecGetter : public TypeLocVisitor<TypeSpecGetter, TypeSpecLoc> { public: -#define TYPELOC(CLASS, PARENT, TYPE) +#define TYPELOC(CLASS, PARENT) #define DECLARATOR_TYPELOC(CLASS, TYPE) \ TypeSpecLoc Visit##CLASS(CLASS TyLoc) { return TyLoc.getTypeSpecLoc(); } #include "clang/AST/TypeLocNodes.def" @@ -172,6 +168,10 @@ public: assert(0 && "A declarator loc wrapper was not handled!"); return TypeSpecLoc(); } + + TypeSpecLoc VisitQualifiedLoc(QualifiedLoc TyLoc) { + return Visit(TyLoc.getUnqualifiedLoc()); + } }; } @@ -190,7 +190,7 @@ public: } -bool DeclaratorLoc::classof(const TypeLoc *TL) { +bool DeclaratorLoc::classof(const UnqualTypeLoc *TL) { return DeclaratorLocChecker().Visit(*TL); } @@ -208,163 +208,8 @@ public: } -bool DefaultTypeSpecLoc::classof(const TypeLoc *TL) { - return DefaultTypeSpecLocChecker().Visit(*TL); -} - -//===----------------------------------------------------------------------===// -// TypedefLoc Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class TypedefLocChecker : public TypeLocVisitor<TypedefLocChecker, bool> { -public: - bool VisitTypedefLoc(TypedefLoc TyLoc) { return true; } -}; - -} - -bool TypedefLoc::classof(const TypeLoc *TL) { - return TypedefLocChecker().Visit(*TL); -} - -//===----------------------------------------------------------------------===// -// ObjCInterfaceLoc Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class ObjCInterfaceLocChecker : - public TypeLocVisitor<ObjCInterfaceLocChecker, bool> { -public: - bool VisitObjCInterfaceLoc(ObjCInterfaceLoc TyLoc) { return true; } -}; - -} - -bool ObjCInterfaceLoc::classof(const TypeLoc *TL) { - return ObjCInterfaceLocChecker().Visit(*TL); -} - -//===----------------------------------------------------------------------===// -// ObjCProtocolListLoc Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class ObjCProtocolListLocChecker : - public TypeLocVisitor<ObjCProtocolListLocChecker, bool> { -public: - bool VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) { return true; } -}; - -} - -bool ObjCProtocolListLoc::classof(const TypeLoc *TL) { - return ObjCProtocolListLocChecker().Visit(*TL); -} - -//===----------------------------------------------------------------------===// -// PointerLoc Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class PointerLocChecker : public TypeLocVisitor<PointerLocChecker, bool> { -public: - bool VisitPointerLoc(PointerLoc TyLoc) { return true; } -}; - -} - -bool PointerLoc::classof(const TypeLoc *TL) { - return PointerLocChecker().Visit(*TL); -} - -//===----------------------------------------------------------------------===// -// BlockPointerLoc Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class BlockPointerLocChecker : - public TypeLocVisitor<BlockPointerLocChecker, bool> { -public: - bool VisitBlockPointerLoc(BlockPointerLoc TyLoc) { return true; } -}; - -} - -bool BlockPointerLoc::classof(const TypeLoc *TL) { - return BlockPointerLocChecker().Visit(*TL); -} - -//===----------------------------------------------------------------------===// -// MemberPointerLoc Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class MemberPointerLocChecker : - public TypeLocVisitor<MemberPointerLocChecker, bool> { -public: - bool VisitMemberPointerLoc(MemberPointerLoc TyLoc) { return true; } -}; - -} - -bool MemberPointerLoc::classof(const TypeLoc *TL) { - return MemberPointerLocChecker().Visit(*TL); -} - -//===----------------------------------------------------------------------===// -// ReferenceLoc Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class ReferenceLocChecker : public TypeLocVisitor<ReferenceLocChecker, bool> { -public: - bool VisitReferenceLoc(ReferenceLoc TyLoc) { return true; } -}; - -} - -bool ReferenceLoc::classof(const TypeLoc *TL) { - return ReferenceLocChecker().Visit(*TL); -} - -//===----------------------------------------------------------------------===// -// FunctionLoc Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class FunctionLocChecker : public TypeLocVisitor<FunctionLocChecker, bool> { -public: - bool VisitFunctionLoc(FunctionLoc TyLoc) { return true; } -}; - -} - -bool FunctionLoc::classof(const TypeLoc *TL) { - return FunctionLocChecker().Visit(*TL); -} - -//===----------------------------------------------------------------------===// -// ArrayLoc Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class ArrayLocChecker : public TypeLocVisitor<ArrayLocChecker, bool> { -public: - bool VisitArrayLoc(ArrayLoc TyLoc) { return true; } -}; - -} - -bool ArrayLoc::classof(const TypeLoc *TL) { - return ArrayLocChecker().Visit(*TL); +bool DefaultTypeSpecLoc::classofType(const Type *Ty) { + return + DefaultTypeSpecLocChecker().Visit(UnqualTypeLoc(const_cast<Type*>(Ty), 0)); } + diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 353a6464b1..b6732561df 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -162,7 +162,7 @@ public: : Reader(Reader), Record(Record), Idx(Idx) { } #define ABSTRACT_TYPELOC(CLASS) -#define TYPELOC(CLASS, PARENT, TYPE) \ +#define TYPELOC(CLASS, PARENT) \ void Visit##CLASS(CLASS TyLoc); #include "clang/AST/TypeLocNodes.def" @@ -173,6 +173,9 @@ public: } +void TypeLocReader::VisitQualifiedLoc(QualifiedLoc TyLoc) { + // nothing to do +} void TypeLocReader::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { TyLoc.setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index 4527bb1f90..ef7c5ec4b1 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -160,7 +160,7 @@ public: : Writer(Writer), Record(Record) { } #define ABSTRACT_TYPELOC(CLASS) -#define TYPELOC(CLASS, PARENT, TYPE) \ +#define TYPELOC(CLASS, PARENT) \ void Visit##CLASS(CLASS TyLoc); #include "clang/AST/TypeLocNodes.def" @@ -171,6 +171,9 @@ public: } +void TypeLocWriter::VisitQualifiedLoc(QualifiedLoc TyLoc) { + // nothing to do here +} void TypeLocWriter::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { Writer.AddSourceLocation(TyLoc.getStartLoc(), Record); } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 3cdf615423..9603ca8a51 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1333,6 +1333,9 @@ Sema::GetDeclaratorInfoForDeclarator(Declarator &D, QualType T, unsigned Skip) { for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) { assert(!CurrTL.isNull()); + + // Don't bother recording source locations for qualifiers. + CurrTL = CurrTL.getUnqualifiedLoc(); DeclaratorChunk &DeclType = D.getTypeObject(i); switch (DeclType.Kind) { |