aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-01-18 07:41:22 +0000
committerJohn McCall <rjmccall@apple.com>2011-01-18 07:41:22 +0000
commit62c28c831bbf207cc36e683e7c321fc33bf8928c (patch)
treee809da00dde162c3d4cf53dad86ba9cf05af774e /lib
parent8e26222104a3fbdbed5322dc60800e32620a2a90 (diff)
Generalize some operations on qualifiers. QualType::getQualifiers() and
::getCVRQualifiers() now look through array types, like all the other standard queries. Also, make a 'split' variant of getUnqualifiedType(). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123751 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp46
-rw-r--r--lib/AST/Type.cpp78
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp3
3 files changed, 75 insertions, 52 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;
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 0d074e0333..812c633c58 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -476,6 +476,7 @@ static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
case Type::DependentName:
case Type::Decltype:
case Type::UnresolvedUsing:
+ case Type::TemplateTypeParm:
return true;
case Type::ConstantArray:
@@ -876,7 +877,7 @@ DeduceTemplateArguments(Sema &S,
Qualifiers Quals;
QualType UnqualParam = S.Context.getUnqualifiedArrayType(Param, Quals);
Quals.setCVRQualifiers(Quals.getCVRQualifiers() &
- Arg.getCVRQualifiersThroughArrayTypes());
+ Arg.getCVRQualifiers());
Param = S.Context.getQualifiedType(UnqualParam, Quals);
}
}