diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 66853b8c9ad7..c28bafe9a30f 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -404,6 +404,8 @@ class QualType { return Value.getPointer().get(); } + QualType getUnqualifiedTypeSlow() const; + friend class QualifierCollector; public: QualType() {} @@ -456,10 +458,7 @@ public: } /// \brief Determine whether this type is const-qualified. - bool isConstQualified() const { - // FIXME: Look through sugar types. - return isLocalConstQualified(); - } + bool isConstQualified() const; /// \brief Determine whether this particular QualType instance has the /// "restrict" qualifier set, without looking through typedefs that may have @@ -469,10 +468,7 @@ public: } /// \brief Determine whether this type is restrict-qualified. - bool isRestrictQualified() const { - // FIXME: Look through sugar types. - return isLocalRestrictQualified(); - } + bool isRestrictQualified() const; /// \brief Determine whether this particular QualType instance has the /// "volatile" qualifier set, without looking through typedefs that may have @@ -482,10 +478,7 @@ public: } /// \brief Determine whether this type is volatile-qualified. - bool isVolatileQualified() const { - // FIXME: Look through sugar types. - return isLocalVolatileQualified(); - } + bool isVolatileQualified() const; /// \brief Determine whether this particular QualType instance has any /// qualifiers, without looking through any typedefs that might add @@ -495,10 +488,7 @@ public: } /// \brief Determine whether this type has any qualifiers. - bool hasQualifiers() const { - // FIXME: Look for qualifiers at any level. - return hasLocalQualifiers(); - } + bool hasQualifiers() const; /// \brief Determine whether this particular QualType instance has any /// "non-fast" qualifiers, e.g., those that are stored in an ExtQualType @@ -519,10 +509,7 @@ public: } /// \brief Retrieve the set of qualifiers applied to this type. - Qualifiers getQualifiers() const { - // FIXME: Collect qualifiers from all levels. - return getLocalQualifiers(); - } + Qualifiers getQualifiers() const; /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers /// local to this particular QualType instance, not including any qualifiers @@ -536,10 +523,7 @@ public: /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers /// applied to this type. - unsigned getCVRQualifiers() const { - // FIXME: Collect qualifiers from all levels. - return getLocalCVRQualifiers(); - } + unsigned getCVRQualifiers() const; bool isConstant(ASTContext& Ctx) const { return QualType::isConstant(*this, Ctx); @@ -604,9 +588,12 @@ public: /// \brief Return the unqualified form of the given type, which might be /// desugared to eliminate qualifiers introduced via typedefs. - QualType getUnqualifiedType() const { - // FIXME: We may have to desugar the type to remove qualifiers. - return getLocalUnqualifiedType(); + QualType getUnqualifiedType() const { + QualType T = getLocalUnqualifiedType(); + if (!T.hasQualifiers()) + return T; + + return getUnqualifiedTypeSlow(); } bool isMoreQualifiedThan(QualType Other) const; @@ -2631,6 +2618,39 @@ inline bool QualType::isCanonicalAsParam() const { !isa(T) && !isa(T); } +inline bool QualType::isConstQualified() const { + return isLocalConstQualified() || + getTypePtr()->getCanonicalTypeInternal().isLocalConstQualified(); +} + +inline bool QualType::isRestrictQualified() const { + return isLocalRestrictQualified() || + getTypePtr()->getCanonicalTypeInternal().isLocalRestrictQualified(); +} + + +inline bool QualType::isVolatileQualified() const { + return isLocalVolatileQualified() || + getTypePtr()->getCanonicalTypeInternal().isLocalVolatileQualified(); +} + +inline bool QualType::hasQualifiers() const { + return hasLocalQualifiers() || + getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers(); +} + +inline Qualifiers QualType::getQualifiers() const { + Qualifiers Quals = getLocalQualifiers(); + Quals.addQualifiers( + getTypePtr()->getCanonicalTypeInternal().getLocalQualifiers()); + return Quals; +} + +inline unsigned QualType::getCVRQualifiers() const { + return getLocalCVRQualifiers() | + getTypePtr()->getCanonicalTypeInternal().getLocalCVRQualifiers(); +} + inline void QualType::removeConst() { removeFastQualifiers(Qualifiers::Const); } diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 8ac8c22a8eee..f08ca6bf469b 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -196,7 +196,7 @@ public: /// \brief Returns the size of the type source info data block. unsigned getFullDataSize() const { return getLocalDataSize() + - getFullDataSizeForType(getType().getUnqualifiedType()); + getFullDataSizeForType(getType().getLocalUnqualifiedType()); } static bool classof(const TypeLoc *TL) { diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 5ecc33cd8f6d..297534eaf1fc 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -98,6 +98,44 @@ const Type *Type::getArrayElementTypeNoTypeQual() const { ->getElementType().getTypePtr(); } +/// \brief Retrieve the unqualified variant of the given type, removing as +/// little sugar as possible. +/// +/// This routine looks through various kinds of sugar to find the +/// least-desuraged type that is unqualified. For example, given: +/// +/// \code +/// typedef int Integer; +/// typedef const Integer CInteger; +/// typedef CInteger DifferenceType; +/// \endcode +/// +/// Executing \c getUnqualifiedTypeSlow() on the type \c DifferenceType will +/// desugar until we hit the type \c Integer, which has no qualifiers on it. +QualType QualType::getUnqualifiedTypeSlow() const { + QualType Cur = *this; + while (true) { + if (!Cur.hasQualifiers()) + return Cur; + + const Type *CurTy = Cur.getTypePtr(); + switch (CurTy->getTypeClass()) { +#define ABSTRACT_TYPE(Class, Parent) +#define TYPE(Class, Parent) \ + case Type::Class: { \ + const Class##Type *Ty = cast(CurTy); \ + if (!Ty->isSugared()) \ + return Cur.getLocalUnqualifiedType(); \ + Cur = Ty->desugar(); \ + break; \ + } +#include "clang/AST/TypeNodes.def" + } + } + + return Cur.getUnqualifiedType(); +} + /// getDesugaredType - Return the specified type with any "sugar" removed from /// the type. This takes off typedefs, typeof's etc. If the outer level of /// the type is already concrete, it returns it unmodified. This is similar