When querying type qualifiers on QualType via one of the "non-local"
interfaces (which are used throughout the front end), combine the
qualifiers on the QualType instance with the qualifiers on the
canonical type to produce the set of qualifiers that, semantically,
apply to that type. This should design away a large category of
"qualifier-hidden-behind-a-typedef" buts like we saw in PR5383.
Performance-wise, this caused a regression of ~0.5% on Cocoa.h, but
it's totally worth it. We may actually be able to get a little more
performance back by using CanQualType more often.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89018 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 5ecc33c..297534e 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -98,6 +98,44 @@
->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