diff options
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 46 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 78 |
2 files changed, 73 insertions, 51 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 2e1a8c2d4b..ec9de25017 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2626,30 +2626,50 @@ CanQualType ASTContext::getCanonicalType(QualType T) const { VAT->getBracketsRange())); } -QualType ASTContext::getUnqualifiedArrayType(QualType T, - Qualifiers &Quals) { - Quals = T.getQualifiers(); - const ArrayType *AT = getAsArrayType(T); +QualType ASTContext::getUnqualifiedArrayType(QualType type, + Qualifiers &quals) { + SplitQualType splitType = type.getSplitUnqualifiedType(); + + // FIXME: getSplitUnqualifiedType() actually walks all the way to + // the unqualified desugared type and then drops it on the floor. + // We then have to strip that sugar back off with + // getUnqualifiedDesugaredType(), which is silly. + const ArrayType *AT = + dyn_cast<ArrayType>(splitType.first->getUnqualifiedDesugaredType()); + + // If we don't have an array, just use the results in splitType. if (!AT) { - return T.getUnqualifiedType(); + quals = splitType.second; + return QualType(splitType.first, 0); } - QualType Elt = AT->getElementType(); - QualType UnqualElt = getUnqualifiedArrayType(Elt, Quals); - if (Elt == UnqualElt) - return T; + // Otherwise, recurse on the array's element type. + QualType elementType = AT->getElementType(); + QualType unqualElementType = getUnqualifiedArrayType(elementType, quals); + + // If that didn't change the element type, AT has no qualifiers, so we + // can just use the results in splitType. + if (elementType == unqualElementType) { + assert(quals.empty()); // from the recursive call + quals = splitType.second; + return QualType(splitType.first, 0); + } + + // Otherwise, add in the qualifiers from the outermost type, then + // build the type back up. + quals.addConsistentQualifiers(splitType.second); if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { - return getConstantArrayType(UnqualElt, CAT->getSize(), + return getConstantArrayType(unqualElementType, CAT->getSize(), CAT->getSizeModifier(), 0); } if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) { - return getIncompleteArrayType(UnqualElt, IAT->getSizeModifier(), 0); + return getIncompleteArrayType(unqualElementType, IAT->getSizeModifier(), 0); } if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT)) { - return getVariableArrayType(UnqualElt, + return getVariableArrayType(unqualElementType, VAT->getSizeExpr(), VAT->getSizeModifier(), VAT->getIndexTypeCVRQualifiers(), @@ -2657,7 +2677,7 @@ QualType ASTContext::getUnqualifiedArrayType(QualType T, } const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(AT); - return getDependentSizedArrayType(UnqualElt, DSAT->getSizeExpr(), + return getDependentSizedArrayType(unqualElementType, DSAT->getSizeExpr(), DSAT->getSizeModifier(), 0, SourceRange()); } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 3882f4960a..f69c38f4ab 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -150,44 +150,6 @@ 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<Class##Type>(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 @@ -220,7 +182,47 @@ SplitQualType QualType::getSplitDesugaredType(QualType T) { } } +SplitQualType QualType::getSplitUnqualifiedTypeImpl(QualType type) { + SplitQualType split = type.split(); + + // All the qualifiers we've seen so far. + Qualifiers quals = split.second; + + // The last type node we saw with any nodes inside it. + const Type *lastTypeWithQuals = split.first; + + while (true) { + QualType next; + + // Do a single-step desugar, aborting the loop if the type isn't + // sugared. + switch (split.first->getTypeClass()) { +#define ABSTRACT_TYPE(Class, Parent) +#define TYPE(Class, Parent) \ + case Type::Class: { \ + const Class##Type *ty = cast<Class##Type>(split.first); \ + if (!ty->isSugared()) goto done; \ + next = ty->desugar(); \ + break; \ + } +#include "clang/AST/TypeNodes.def" + } + + // Otherwise, split the underlying type. If that yields qualifiers, + // update the information. + split = next.split(); + if (!split.second.empty()) { + lastTypeWithQuals = split.first; + quals.addConsistentQualifiers(split.second); + } + } + + done: + return SplitQualType(lastTypeWithQuals, quals); +} + QualType QualType::IgnoreParens(QualType T) { + // FIXME: this seems inherently un-qualifiers-safe. while (const ParenType *PT = T->getAs<ParenType>()) T = PT->getInnerType(); return T; |