Refactor the representation of qualifiers to bring ExtQualType out of the
Type hierarchy.  Demote 'volatile' to extended-qualifier status.  Audit our
use of qualifiers and fix a few places that weren't dealing with qualifiers
quite right;  many more remain.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82705 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 63b252a..81f7283 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -44,9 +44,7 @@
 
     // If this is a sugared type (like a typedef, typeof, etc), then unwrap one
     // level of the sugar so that the type is more obvious to the user.
-    QualType DesugaredTy = Ty->getDesugaredType(true);
-    DesugaredTy.setCVRQualifiers(DesugaredTy.getCVRQualifiers() |
-                                 Ty.getCVRQualifiers());
+    QualType DesugaredTy = Ty.getDesugaredType(true);
 
     if (Ty != DesugaredTy &&
         // If the desugared type is a vector type, we don't want to expand it,
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index d1a8b6d..ab085fb 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -186,12 +186,12 @@
          "Destination type is not pointer or pointer to member.");
 
   QualType UnwrappedSrcType = SrcType, UnwrappedDestType = DestType;
-  llvm::SmallVector<unsigned, 8> cv1, cv2;
+  llvm::SmallVector<Qualifiers, 8> cv1, cv2;
 
   // Find the qualifications.
   while (Self.UnwrapSimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
-    cv1.push_back(UnwrappedSrcType.getCVRQualifiers());
-    cv2.push_back(UnwrappedDestType.getCVRQualifiers());
+    cv1.push_back(UnwrappedSrcType.getQualifiers());
+    cv2.push_back(UnwrappedDestType.getQualifiers());
   }
   assert(cv1.size() > 0 && "Must have at least one pointer level.");
 
@@ -199,13 +199,14 @@
   // unwrapping, of course).
   QualType SrcConstruct = Self.Context.VoidTy;
   QualType DestConstruct = Self.Context.VoidTy;
-  for (llvm::SmallVector<unsigned, 8>::reverse_iterator i1 = cv1.rbegin(),
-                                                        i2 = cv2.rbegin();
+  ASTContext &Context = Self.Context;
+  for (llvm::SmallVector<Qualifiers, 8>::reverse_iterator i1 = cv1.rbegin(),
+                                                          i2 = cv2.rbegin();
        i1 != cv1.rend(); ++i1, ++i2) {
-    SrcConstruct = Self.Context.getPointerType(
-      SrcConstruct.getQualifiedType(*i1));
-    DestConstruct = Self.Context.getPointerType(
-      DestConstruct.getQualifiedType(*i2));
+    SrcConstruct
+      = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1));
+    DestConstruct
+      = Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2));
   }
 
   // Test if they're compatible.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 084b2ef..ec27814 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1814,14 +1814,16 @@
   // constant expression folding, like struct {char x[(int)(char*)2];}
   SizeIsNegative = false;
 
-  if (const PointerType* PTy = dyn_cast<PointerType>(T)) {
+  QualifierCollector Qs;
+  const Type *Ty = Qs.strip(T);
+
+  if (const PointerType* PTy = dyn_cast<PointerType>(Ty)) {
     QualType Pointee = PTy->getPointeeType();
     QualType FixedType =
         TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative);
     if (FixedType.isNull()) return FixedType;
     FixedType = Context.getPointerType(FixedType);
-    FixedType.setCVRQualifiers(T.getCVRQualifiers());
-    return FixedType;
+    return Qs.apply(FixedType);
   }
 
   const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
@@ -2968,7 +2970,7 @@
       //   char const * const *
       //   char * const *
 
-      QualifierSet qs;
+      QualifierCollector qs;
       const PointerType* PT;
       if ((PT = qs.strip(AT)->getAs<PointerType>()) &&
           (PT = qs.strip(PT->getPointeeType())->getAs<PointerType>()) &&
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 5cced5a..390a804 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2046,13 +2046,13 @@
 
   DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
   if (FTI.TypeQuals != 0) {
-    if (FTI.TypeQuals & QualType::Const)
+    if (FTI.TypeQuals & Qualifiers::Const)
       Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
         << "const" << SourceRange(D.getIdentifierLoc());
-    if (FTI.TypeQuals & QualType::Volatile)
+    if (FTI.TypeQuals & Qualifiers::Volatile)
       Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
         << "volatile" << SourceRange(D.getIdentifierLoc());
-    if (FTI.TypeQuals & QualType::Restrict)
+    if (FTI.TypeQuals & Qualifiers::Restrict)
       Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
         << "restrict" << SourceRange(D.getIdentifierLoc());
   }
@@ -2159,13 +2159,13 @@
 
   DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
   if (FTI.TypeQuals != 0 && !D.isInvalidType()) {
-    if (FTI.TypeQuals & QualType::Const)
+    if (FTI.TypeQuals & Qualifiers::Const)
       Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
         << "const" << SourceRange(D.getIdentifierLoc());
-    if (FTI.TypeQuals & QualType::Volatile)
+    if (FTI.TypeQuals & Qualifiers::Volatile)
       Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
         << "volatile" << SourceRange(D.getIdentifierLoc());
-    if (FTI.TypeQuals & QualType::Restrict)
+    if (FTI.TypeQuals & Qualifiers::Restrict)
       Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
         << "restrict" << SourceRange(D.getIdentifierLoc());
     D.setInvalidType();
@@ -2844,10 +2844,8 @@
   // If class's assignment operator argument is const/volatile qualified,
   // look for operator = (const/volatile B&). Otherwise, look for
   // operator = (B&).
-  if (ParmDecl->getType().isConstQualified())
-    RHSType.addConst();
-  if (ParmDecl->getType().isVolatileQualified())
-    RHSType.addVolatile();
+  RHSType = Context.getCVRQualifiedType(RHSType,
+                                     ParmDecl->getType().getCVRQualifiers());
   ExprOwningPtr<Expr> LHS(this,  new (Context) DeclRefExpr(ParmDecl,
                                                           LHSType,
                                                           SourceLocation()));
@@ -3575,7 +3573,7 @@
   //     -- Otherwise, the reference shall be to a non-volatile const
   //        type (i.e., cv1 shall be const), or the reference shall be an
   //        rvalue reference and the initializer expression shall be an rvalue.
-  if (!isRValRef && T1.getCVRQualifiers() != QualType::Const) {
+  if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) {
     if (!ICS)
       Diag(DeclLoc, diag::err_not_reference_to_const_init)
         << T1 << (InitLvalue != Expr::LV_Valid? "temporary" : "value")
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9695814..5bc8818 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -566,7 +566,7 @@
   // of the anonymous union objects and, eventually, the field we
   // found via name lookup.
   bool BaseObjectIsPointer = false;
-  unsigned ExtraQuals = 0;
+  Qualifiers BaseQuals;
   if (BaseObject) {
     // BaseObject is an anonymous struct/union variable (and is,
     // therefore, not part of another non-anonymous record).
@@ -574,8 +574,8 @@
     MarkDeclarationReferenced(Loc, BaseObject);
     BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(),
                                                SourceLocation());
-    ExtraQuals
-      = Context.getCanonicalType(BaseObject->getType()).getCVRQualifiers();
+    BaseQuals
+      = Context.getCanonicalType(BaseObject->getType()).getQualifiers();
   } else if (BaseObjectExpr) {
     // The caller provided the base object expression. Determine
     // whether its a pointer and whether it adds any qualifiers to the
@@ -585,7 +585,8 @@
       BaseObjectIsPointer = true;
       ObjectType = ObjectPtr->getPointeeType();
     }
-    ExtraQuals = Context.getCanonicalType(ObjectType).getCVRQualifiers();
+    BaseQuals
+      = Context.getCanonicalType(ObjectType).getQualifiers();
   } else {
     // We've found a member of an anonymous struct/union that is
     // inside a non-anonymous struct/union, so in a well-formed
@@ -608,7 +609,7 @@
         return ExprError(Diag(Loc,diag::err_invalid_member_use_in_static_method)
           << Field->getDeclName());
       }
-      ExtraQuals = MD->getTypeQualifiers();
+      BaseQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers());
     }
 
     if (!BaseObjectExpr)
@@ -619,24 +620,35 @@
   // Build the implicit member references to the field of the
   // anonymous struct/union.
   Expr *Result = BaseObjectExpr;
-  unsigned BaseAddrSpace = BaseObjectExpr->getType().getAddressSpace();
+  Qualifiers ResultQuals = BaseQuals;
   for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator
          FI = AnonFields.rbegin(), FIEnd = AnonFields.rend();
        FI != FIEnd; ++FI) {
     QualType MemberType = (*FI)->getType();
-    if (!(*FI)->isMutable()) {
-      unsigned combinedQualifiers
-        = MemberType.getCVRQualifiers() | ExtraQuals;
-      MemberType = MemberType.getQualifiedType(combinedQualifiers);
-    }
-    if (BaseAddrSpace != MemberType.getAddressSpace())
-      MemberType = Context.getAddrSpaceQualType(MemberType, BaseAddrSpace);
+    Qualifiers MemberTypeQuals =
+      Context.getCanonicalType(MemberType).getQualifiers();
+
+    // CVR attributes from the base are picked up by members,
+    // except that 'mutable' members don't pick up 'const'.
+    if ((*FI)->isMutable())
+      ResultQuals.removeConst();
+
+    // GC attributes are never picked up by members.
+    ResultQuals.removeObjCGCAttr();
+
+    // TR 18037 does not allow fields to be declared with address spaces.
+    assert(!MemberTypeQuals.hasAddressSpace());
+
+    Qualifiers NewQuals = ResultQuals + MemberTypeQuals;
+    if (NewQuals != MemberTypeQuals)
+      MemberType = Context.getQualifiedType(MemberType, NewQuals);
+
     MarkDeclarationReferenced(Loc, *FI);
     // FIXME: Might this end up being a qualified name?
     Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,
                                       OpLoc, MemberType);
     BaseObjectIsPointer = false;
-    ExtraQuals = Context.getCanonicalType(MemberType).getCVRQualifiers();
+    ResultQuals = NewQuals;
   }
 
   return Owned(Result);
@@ -948,11 +960,10 @@
 
         if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>())
           MemberType = RefType->getPointeeType();
-        else if (!FD->isMutable()) {
-          unsigned combinedQualifiers
-            = MemberType.getCVRQualifiers() | MD->getTypeQualifiers();
-          MemberType = MemberType.getQualifiedType(combinedQualifiers);
-        }
+        else if (!FD->isMutable())
+          MemberType
+            = Context.getQualifiedType(MemberType,
+                            Qualifiers::fromCVRMask(MD->getTypeQualifiers()));
       } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
         if (!Method->isStatic()) {
           Ctx = Method->getParent();
@@ -1135,7 +1146,7 @@
     //    - a constant with integral or enumeration type and is
     //      initialized with an expression that is value-dependent
     else if (const VarDecl *Dcl = dyn_cast<VarDecl>(VD)) {
-      if (Dcl->getType().getCVRQualifiers() == QualType::Const &&
+      if (Dcl->getType().getCVRQualifiers() == Qualifiers::Const &&
           Dcl->getInit()) {
         ValueDependent = Dcl->getInit()->isValueDependent();
       }
@@ -1174,7 +1185,7 @@
       PredefinedExpr::ComputeName(Context, IT, currentDecl).length();
 
     llvm::APInt LengthI(32, Length + 1);
-    ResTy = Context.CharTy.getQualifiedType(QualType::Const);
+    ResTy = Context.CharTy.withConst();
     ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
   }
   return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));
@@ -2235,14 +2246,16 @@
       if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>())
         MemberType = Ref->getPointeeType();
       else {
-        unsigned BaseAddrSpace = BaseType.getAddressSpace();
-        unsigned combinedQualifiers =
-          MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
-        if (FD->isMutable())
-          combinedQualifiers &= ~QualType::Const;
-        MemberType = MemberType.getQualifiedType(combinedQualifiers);
-        if (BaseAddrSpace != MemberType.getAddressSpace())
-           MemberType = Context.getAddrSpaceQualType(MemberType, BaseAddrSpace);
+        Qualifiers BaseQuals = BaseType.getQualifiers();
+        BaseQuals.removeObjCGCAttr();
+        if (FD->isMutable()) BaseQuals.removeConst();
+
+        Qualifiers MemberQuals
+          = Context.getCanonicalType(MemberType).getQualifiers();
+
+        Qualifiers Combined = BaseQuals + MemberQuals;
+        if (Combined != MemberQuals)
+          MemberType = Context.getQualifiedType(MemberType, Combined);
       }
 
       MarkDeclarationReferenced(MemberLoc, FD);
@@ -3510,7 +3523,8 @@
   if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) {
     QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
     QualType rhptee = RHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
-    QualType destPointee = lhptee.getQualifiedType(rhptee.getCVRQualifiers());
+    QualType destPointee
+      = Context.getQualifiedType(lhptee, rhptee.getQualifiers());
     QualType destType = Context.getPointerType(destPointee);
     ImpCastExprToType(LHS, destType); // add qualifiers if necessary
     ImpCastExprToType(RHS, destType); // promote to void*
@@ -3519,7 +3533,8 @@
   if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {
     QualType lhptee = LHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
     QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
-    QualType destPointee = rhptee.getQualifiedType(lhptee.getCVRQualifiers());
+    QualType destPointee
+      = Context.getQualifiedType(rhptee, lhptee.getQualifiers());
     QualType destType = Context.getPointerType(destPointee);
     ImpCastExprToType(RHS, destType); // add qualifiers if necessary
     ImpCastExprToType(LHS, destType); // promote to void*
@@ -3534,14 +3549,16 @@
     // ignore qualifiers on void (C99 6.5.15p3, clause 6)
     if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) {
       // Figure out necessary qualifiers (C99 6.5.15p6)
-      QualType destPointee=lhptee.getQualifiedType(rhptee.getCVRQualifiers());
+      QualType destPointee
+        = Context.getQualifiedType(lhptee, rhptee.getQualifiers());
       QualType destType = Context.getPointerType(destPointee);
       ImpCastExprToType(LHS, destType); // add qualifiers if necessary
       ImpCastExprToType(RHS, destType); // promote to void*
       return destType;
     }
     if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
-      QualType destPointee=rhptee.getQualifiedType(lhptee.getCVRQualifiers());
+      QualType destPointee
+        = Context.getQualifiedType(rhptee, lhptee.getQualifiers());
       QualType destType = Context.getPointerType(destPointee);
       ImpCastExprToType(LHS, destType); // add qualifiers if necessary
       ImpCastExprToType(RHS, destType); // promote to void*
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index ff6ae50..e93929e 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -972,7 +972,7 @@
           = ToPtrType->getPointeeType()->getAs<BuiltinType>()) {
         // This conversion is considered only when there is an
         // explicit appropriate pointer target type (C++ 4.2p2).
-        if (ToPtrType->getPointeeType().getCVRQualifiers() == 0 &&
+        if (!ToPtrType->getPointeeType().hasQualifiers() &&
             ((StrLit->isWide() && ToPointeeType->isWideCharType()) ||
              (!StrLit->isWide() &&
               (ToPointeeType->getKind() == BuiltinType::Char_U ||
@@ -1316,10 +1316,7 @@
   // argument.
   // We probably need a "MemberFunctionClosureType" or something like that.
   QualType Result = MemPtr->getPointeeType();
-  if (LType.isConstQualified())
-    Result.addConst();
-  if (LType.isVolatileQualified())
-    Result.addVolatile();
+  Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers());
   return Result;
 }
 
@@ -1662,14 +1659,33 @@
   if (LMemPtr && RMemPtr) {
     QualType LPointee = LMemPtr->getPointeeType();
     QualType RPointee = RMemPtr->getPointeeType();
+
+    QualifierCollector LPQuals, RPQuals;
+    const Type *LPCan = LPQuals.strip(Context.getCanonicalType(LPointee));
+    const Type *RPCan = RPQuals.strip(Context.getCanonicalType(RPointee));
+
     // First, we check that the unqualified pointee type is the same. If it's
     // not, there's no conversion that will unify the two pointers.
-    if (Context.getCanonicalType(LPointee).getUnqualifiedType() ==
-        Context.getCanonicalType(RPointee).getUnqualifiedType()) {
-      // Second, we take the greater of the two cv qualifications. If neither
+    if (LPCan == RPCan) {
+
+      // Second, we take the greater of the two qualifications. If neither
       // is greater than the other, the conversion is not possible.
-      unsigned Q = LPointee.getCVRQualifiers() | RPointee.getCVRQualifiers();
-      if (Q == LPointee.getCVRQualifiers() || Q == RPointee.getCVRQualifiers()){
+
+      Qualifiers MergedQuals = LPQuals + RPQuals;
+
+      bool CompatibleQuals = true;
+      if (MergedQuals.getCVRQualifiers() != LPQuals.getCVRQualifiers() &&
+          MergedQuals.getCVRQualifiers() != RPQuals.getCVRQualifiers())
+        CompatibleQuals = false;
+      else if (LPQuals.getAddressSpace() != RPQuals.getAddressSpace())
+        // FIXME:
+        // C99 6.5.15 as modified by TR 18037:
+        //   If the second and third operands are pointers into different
+        //   address spaces, the address spaces must overlap.
+        CompatibleQuals = false;
+      // FIXME: GC qualifiers?
+
+      if (CompatibleQuals) {
         // Third, we check if either of the container classes is derived from
         // the other.
         QualType LContainer(LMemPtr->getClass(), 0);
@@ -1687,8 +1703,9 @@
           // The type 'Q Pointee (MoreDerived::*)' is the common type.
           // We don't use ImpCastExprToType here because this could still fail
           // for ambiguous or inaccessible conversions.
-          QualType Common = Context.getMemberPointerType(
-            LPointee.getQualifiedType(Q), MoreDerived.getTypePtr());
+          LPointee = Context.getQualifiedType(LPointee, MergedQuals);
+          QualType Common
+            = Context.getMemberPointerType(LPointee, MoreDerived.getTypePtr());
           if (PerformImplicitConversion(LHS, Common, "converting"))
             return QualType();
           if (PerformImplicitConversion(RHS, Common, "converting"))
@@ -1750,6 +1767,7 @@
   // What we do here is, we build the two possible composite types, and try the
   // conversions in both directions. If only one works, or if the two composite
   // types are the same, we have succeeded.
+  // FIXME: extended qualifiers?
   llvm::SmallVector<unsigned, 4> QualifierUnion;
   llvm::SmallVector<std::pair<const Type *, const Type *>, 4> MemberOfClass;
   QualType Composite1 = T1, Composite2 = T2;
@@ -1790,16 +1808,21 @@
          I = QualifierUnion.begin(),
          E = QualifierUnion.end();
        I != E; (void)++I, ++MOC) {
+    Qualifiers Quals = Qualifiers::fromCVRMask(*I);
     if (MOC->first && MOC->second) {
       // Rebuild member pointer type
-      Composite1 = Context.getMemberPointerType(Composite1.getQualifiedType(*I),
-                                                MOC->first);
-      Composite2 = Context.getMemberPointerType(Composite2.getQualifiedType(*I),
-                                                MOC->second);
+      Composite1 = Context.getMemberPointerType(
+                                    Context.getQualifiedType(Composite1, Quals),
+                                    MOC->first);
+      Composite2 = Context.getMemberPointerType(
+                                    Context.getQualifiedType(Composite2, Quals),
+                                    MOC->second);
     } else {
       // Rebuild pointer type
-      Composite1 = Context.getPointerType(Composite1.getQualifiedType(*I));
-      Composite2 = Context.getPointerType(Composite2.getQualifiedType(*I));
+      Composite1
+        = Context.getPointerType(Context.getQualifiedType(Composite1, Quals));
+      Composite2
+        = Context.getPointerType(Context.getQualifiedType(Composite2, Quals));
     }
   }
 
diff --git a/lib/Sema/SemaInherit.cpp b/lib/Sema/SemaInherit.cpp
index 01e856c..8f932ac 100644
--- a/lib/Sema/SemaInherit.cpp
+++ b/lib/Sema/SemaInherit.cpp
@@ -59,7 +59,7 @@
 /// an unqualified, canonical class type.
 bool BasePaths::isAmbiguous(QualType BaseType) {
   assert(BaseType->isCanonical() && "Base type must be the canonical type");
-  assert(BaseType.getCVRQualifiers() == 0 && "Base type must be unqualified");
+  assert(BaseType.hasQualifiers() == 0 && "Base type must be unqualified");
   std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
   return Subobjects.second + (Subobjects.first? 1 : 0) > 1;
 }
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 4232d54..edb854c 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -856,12 +856,12 @@
                                    ASTContext &Context) {
   QualType CanonFromPointee = Context.getCanonicalType(FromPtr->getPointeeType());
   QualType CanonToPointee = Context.getCanonicalType(ToPointee);
-  unsigned Quals = CanonFromPointee.getCVRQualifiers();
+  Qualifiers Quals = CanonFromPointee.getQualifiers();
 
   // Exact qualifier match -> return the pointer type we're converting to.
-  if (CanonToPointee.getCVRQualifiers() == Quals) {
+  if (CanonToPointee.getQualifiers() == Quals) {
     // ToType is exactly what we need. Return it.
-    if (ToType.getTypePtr())
+    if (!ToType.isNull())
       return ToType;
 
     // Build a pointer to ToPointee. It has the right qualifiers
@@ -870,7 +870,8 @@
   }
 
   // Just build a canonical type that has the right qualifiers.
-  return Context.getPointerType(CanonToPointee.getQualifiedType(Quals));
+  return Context.getPointerType(
+         Context.getQualifiedType(CanonToPointee.getUnqualifiedType(), Quals));
 }
 
 static bool isNullPointerConstantForConversion(Expr *Expr,
@@ -2022,8 +2023,8 @@
 ImplicitConversionSequence
 Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) {
   QualType ClassType = Context.getTypeDeclType(Method->getParent());
-  unsigned MethodQuals = Method->getTypeQualifiers();
-  QualType ImplicitParamType = ClassType.getQualifiedType(MethodQuals);
+  QualType ImplicitParamType
+    = Context.getCVRQualifiedType(ClassType, Method->getTypeQualifiers());
 
   // Set up the conversion sequence as a "bad" conversion, to allow us
   // to exit early.
@@ -2831,27 +2832,27 @@
 /// restrict *", and "int const volatile restrict *" to the set of
 /// pointer types. Returns true if the add of @p Ty itself succeeded,
 /// false otherwise.
+///
+/// FIXME: what to do about extended qualifiers?
 bool
 BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty) {
+
   // Insert this type.
   if (!PointerTypes.insert(Ty))
     return false;
 
-  if (const PointerType *PointerTy = Ty->getAs<PointerType>()) {
-    QualType PointeeTy = PointerTy->getPointeeType();
-    // FIXME: Optimize this so that we don't keep trying to add the same types.
+  const PointerType *PointerTy = Ty->getAs<PointerType>();
+  assert(PointerTy && "type was not a pointer type!");
 
-    // FIXME: Do we have to add CVR qualifiers at *all* levels to deal with all
-    // pointer conversions that don't cast away constness?
-    if (!PointeeTy.isConstQualified())
-      AddPointerWithMoreQualifiedTypeVariants
-        (Context.getPointerType(PointeeTy.withConst()));
-    if (!PointeeTy.isVolatileQualified())
-      AddPointerWithMoreQualifiedTypeVariants
-        (Context.getPointerType(PointeeTy.withVolatile()));
-    if (!PointeeTy.isRestrictQualified())
-      AddPointerWithMoreQualifiedTypeVariants
-        (Context.getPointerType(PointeeTy.withRestrict()));
+  QualType PointeeTy = PointerTy->getPointeeType();
+  unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+
+  // Iterate through all strict supersets of BaseCVR.
+  for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
+    if ((CVR | BaseCVR) != CVR) continue;
+    
+    QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
+    PointerTypes.insert(Context.getPointerType(QPointeeTy));
   }
 
   return true;
@@ -2864,6 +2865,8 @@
 /// restrict *", and "int const volatile restrict *" to the set of
 /// pointer types. Returns true if the add of @p Ty itself succeeded,
 /// false otherwise.
+///
+/// FIXME: what to do about extended qualifiers?
 bool
 BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
     QualType Ty) {
@@ -2871,20 +2874,20 @@
   if (!MemberPointerTypes.insert(Ty))
     return false;
 
-  if (const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>()) {
-    QualType PointeeTy = PointerTy->getPointeeType();
-    const Type *ClassTy = PointerTy->getClass();
-    // FIXME: Optimize this so that we don't keep trying to add the same types.
+  const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>();
+  assert(PointerTy && "type was not a member pointer type!");
 
-    if (!PointeeTy.isConstQualified())
-      AddMemberPointerWithMoreQualifiedTypeVariants
-        (Context.getMemberPointerType(PointeeTy.withConst(), ClassTy));
-    if (!PointeeTy.isVolatileQualified())
-      AddMemberPointerWithMoreQualifiedTypeVariants
-        (Context.getMemberPointerType(PointeeTy.withVolatile(), ClassTy));
-    if (!PointeeTy.isRestrictQualified())
-      AddMemberPointerWithMoreQualifiedTypeVariants
-        (Context.getMemberPointerType(PointeeTy.withRestrict(), ClassTy));
+  QualType PointeeTy = PointerTy->getPointeeType();
+  const Type *ClassTy = PointerTy->getClass();
+
+  // Iterate through all strict supersets of the pointee type's CVR
+  // qualifiers.
+  unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+  for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
+    if ((CVR | BaseCVR) != CVR) continue;
+    
+    QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
+    MemberPointerTypes.insert(Context.getMemberPointerType(QPointeeTy, ClassTy));
   }
 
   return true;
@@ -2924,7 +2927,8 @@
     // Add 'cv void*' to our set of types.
     if (!Ty->isVoidType()) {
       QualType QualVoid
-        = Context.VoidTy.getQualifiedType(PointeeTy.getCVRQualifiers());
+        = Context.getCVRQualifiedType(Context.VoidTy,
+                                   PointeeTy.getCVRQualifiers());
       AddPointerWithMoreQualifiedTypeVariants(Context.getPointerType(QualVoid));
     }
 
@@ -2936,7 +2940,8 @@
       for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
            Base != ClassDecl->bases_end(); ++Base) {
         QualType BaseTy = Context.getCanonicalType(Base->getType());
-        BaseTy = BaseTy.getQualifiedType(PointeeTy.getCVRQualifiers());
+        BaseTy = Context.getCVRQualifiedType(BaseTy.getUnqualifiedType(),
+                                          PointeeTy.getCVRQualifiers());
 
         // Add the pointer type, recursively, so that we get all of
         // the indirect base classes, too.
@@ -2997,7 +3002,8 @@
 
   if (!S.Context.getCanonicalType(T).isVolatileQualified()) {
     // volatile T& operator=(volatile T&, T)
-    ParamTypes[0] = S.Context.getLValueReferenceType(T.withVolatile());
+    ParamTypes[0]
+      = S.Context.getLValueReferenceType(S.Context.getVolatileType(T));
     ParamTypes[1] = T;
     S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
                           /*IsAssignmentOperator=*/true);
@@ -3119,7 +3125,8 @@
         AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
 
       // Volatile version
-      ParamTypes[0] = Context.getLValueReferenceType(ArithTy.withVolatile());
+      ParamTypes[0]
+        = Context.getLValueReferenceType(Context.getVolatileType(ArithTy));
       if (NumArgs == 1)
         AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
       else
@@ -3154,7 +3161,8 @@
 
       if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
         // With volatile
-        ParamTypes[0] = Context.getLValueReferenceType((*Ptr).withVolatile());
+        ParamTypes[0]
+          = Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
         if (NumArgs == 1)
           AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
         else
@@ -3465,7 +3473,8 @@
 
       if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
         // volatile version
-        ParamTypes[0] = Context.getLValueReferenceType((*Ptr).withVolatile());
+        ParamTypes[0]
+          = Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
         AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
                             /*IsAssigmentOperator=*/Op == OO_Equal);
       }
@@ -3498,7 +3507,7 @@
                             /*IsAssigmentOperator=*/Op == OO_Equal);
 
         // Add this built-in operator as a candidate (VQ is 'volatile').
-        ParamTypes[0] = ArithmeticTypes[Left].withVolatile();
+        ParamTypes[0] = Context.getVolatileType(ArithmeticTypes[Left]);
         ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
         AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
                             /*IsAssigmentOperator=*/Op == OO_Equal);
@@ -3536,7 +3545,7 @@
 
         // Add this built-in operator as a candidate (VQ is 'volatile').
         ParamTypes[0] = ArithmeticTypes[Left];
-        ParamTypes[0].addVolatile();
+        ParamTypes[0] = Context.getVolatileType(ParamTypes[0]);
         ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
         AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
       }
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 4ffca8c..a73c261 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -1295,22 +1295,19 @@
   TypeWithHandler(const QualType &type, CXXCatchStmt *statement)
   : t(type), stmt(statement) {}
 
+  // An arbitrary order is fine as long as it places identical
+  // types next to each other.
   bool operator<(const TypeWithHandler &y) const {
-    if (t.getTypePtr() < y.t.getTypePtr())
+    if (t.getAsOpaquePtr() < y.t.getAsOpaquePtr())
       return true;
-    else if (t.getTypePtr() > y.t.getTypePtr())
-      return false;
-    else if (t.getCVRQualifiers() < y.t.getCVRQualifiers())
-      return true;
-    else if (t.getCVRQualifiers() < y.t.getCVRQualifiers())
+    if (t.getAsOpaquePtr() > y.t.getAsOpaquePtr())
       return false;
     else
       return getTypeSpecStartLoc() < y.getTypeSpecStartLoc();
   }
 
   bool operator==(const TypeWithHandler& other) const {
-    return t.getTypePtr() == other.t.getTypePtr()
-        && t.getCVRQualifiers() == other.t.getCVRQualifiers();
+    return t == other.t;
   }
 
   QualType getQualType() const { return t; }
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 8d4999b..2ad1a61 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -300,28 +300,30 @@
 }
 
 /// \brief Returns a completely-unqualified array type, capturing the
-/// qualifiers in CVRQuals.
+/// qualifiers in Quals.
 ///
 /// \param Context the AST context in which the array type was built.
 ///
 /// \param T a canonical type that may be an array type.
 ///
-/// \param CVRQuals will receive the set of const/volatile/restrict qualifiers
-/// that were applied to the element type of the array.
+/// \param Quals will receive the full set of qualifiers that were
+/// applied to the element type of the array.
 ///
 /// \returns if \p T is an array type, the completely unqualified array type
 /// that corresponds to T. Otherwise, returns T.
 static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T,
-                                        unsigned &CVRQuals) {
+                                        Qualifiers &Quals) {
   assert(T->isCanonical() && "Only operates on canonical types");
   if (!isa<ArrayType>(T)) {
-    CVRQuals = T.getCVRQualifiers();
+    Quals = T.getQualifiers();
     return T.getUnqualifiedType();
   }
 
+  assert(!T.hasQualifiers() && "canonical array type has qualifiers!");
+
   if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) {
     QualType Elt = getUnqualifiedArrayType(Context, CAT->getElementType(),
-                                           CVRQuals);
+                                           Quals);
     if (Elt == CAT->getElementType())
       return T;
 
@@ -331,7 +333,7 @@
 
   if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(T)) {
     QualType Elt = getUnqualifiedArrayType(Context, IAT->getElementType(),
-                                           CVRQuals);
+                                           Quals);
     if (Elt == IAT->getElementType())
       return T;
 
@@ -340,7 +342,7 @@
 
   const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T);
   QualType Elt = getUnqualifiedArrayType(Context, DSAT->getElementType(),
-                                         CVRQuals);
+                                         Quals);
   if (Elt == DSAT->getElementType())
     return T;
 
@@ -387,9 +389,9 @@
   //     referred to by the reference) can be more cv-qualified than the
   //     transformed A.
   if (TDF & TDF_ParamWithReferenceType) {
-    unsigned ExtraQualsOnParam
-      = Param.getCVRQualifiers() & ~Arg.getCVRQualifiers();
-    Param.setCVRQualifiers(Param.getCVRQualifiers() & ~ExtraQualsOnParam);
+    Qualifiers Quals = Param.getQualifiers();
+    Quals.setCVRQualifiers(Quals.getCVRQualifiers() & Arg.getCVRQualifiers());
+    Param = Context.getQualifiedType(Param.getUnqualifiedType(), Quals);
   }
 
   // If the parameter type is not dependent, there is nothing to deduce.
@@ -418,10 +420,10 @@
     // top level, so they can be matched with the qualifiers on the parameter.
     // FIXME: address spaces, ObjC GC qualifiers
     if (isa<ArrayType>(Arg)) {
-      unsigned CVRQuals = 0;
-      Arg = getUnqualifiedArrayType(Context, Arg, CVRQuals);
-      if (CVRQuals) {
-        Arg = Arg.getWithAdditionalQualifiers(CVRQuals);
+      Qualifiers Quals;
+      Arg = getUnqualifiedArrayType(Context, Arg, Quals);
+      if (Quals) {
+        Arg = Context.getQualifiedType(Arg, Quals);
         RecanonicalizeArg = true;
       }
     }
@@ -437,8 +439,8 @@
 
     assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
 
-    unsigned Quals = Arg.getCVRQualifiers() & ~Param.getCVRQualifiers();
-    QualType DeducedType = Arg.getQualifiedType(Quals);
+    QualType DeducedType = Arg;
+    DeducedType.removeCVRQualifiers(Param.getCVRQualifiers());
     if (RecanonicalizeArg)
       DeducedType = Context.getCanonicalType(DeducedType);
 
@@ -2022,13 +2024,6 @@
 
   T = SemaRef.Context.getCanonicalType(T);
   switch (T->getTypeClass()) {
-  case Type::ExtQual:
-    MarkUsedTemplateParameters(SemaRef,
-                               QualType(cast<ExtQualType>(T)->getBaseType(), 0),
-                               OnlyDeduced,
-                               Used);
-    break;
-
   case Type::Pointer:
     MarkUsedTemplateParameters(SemaRef,
                                cast<PointerType>(T)->getPointeeType(),
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 86b49d4..90a0397 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -496,7 +496,7 @@
     PredefinedExpr::ComputeName(getSema().Context, IT, currentDecl).length();
 
   llvm::APInt LengthI(32, Length + 1);
-  QualType ResTy = getSema().Context.CharTy.getQualifiedType(QualType::Const);
+  QualType ResTy = getSema().Context.CharTy.withConst();
   ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI, 
                                                  ArrayType::Normal, 0);
   PredefinedExpr *PE =
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 6fee787..c297694 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -312,7 +312,7 @@
     // Enforce C99 6.7.3p2: "Types other than pointer types derived from object
     // or incomplete types shall not be restrict-qualified."  C++ also allows
     // restrict-qualified references.
-    if (TypeQuals & QualType::Restrict) {
+    if (TypeQuals & DeclSpec::TQ_restrict) {
       if (Result->isPointerType() || Result->isReferenceType()) {
         QualType EltTy = Result->isPointerType() ?
           Result->getAs<PointerType>()->getPointeeType() :
@@ -324,13 +324,13 @@
           Diag(DS.getRestrictSpecLoc(),
                diag::err_typecheck_invalid_restrict_invalid_pointee)
             << EltTy << DS.getSourceRange();
-          TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier.
+          TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
         }
       } else {
         Diag(DS.getRestrictSpecLoc(),
              diag::err_typecheck_invalid_restrict_not_pointer)
           << Result << DS.getSourceRange();
-        TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier.
+        TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
       }
     }
 
@@ -340,12 +340,14 @@
     if (Result->isFunctionType() && TypeQuals) {
       // Get some location to point at, either the C or V location.
       SourceLocation Loc;
-      if (TypeQuals & QualType::Const)
+      if (TypeQuals & DeclSpec::TQ_const)
         Loc = DS.getConstSpecLoc();
-      else {
-        assert((TypeQuals & QualType::Volatile) &&
-               "Has CV quals but not C or V?");
+      else if (TypeQuals & DeclSpec::TQ_volatile)
         Loc = DS.getVolatileSpecLoc();
+      else {
+        assert((TypeQuals & DeclSpec::TQ_restrict) &&
+               "Has CVR quals but not C, V, or R?");
+        Loc = DS.getRestrictSpecLoc();
       }
       Diag(Loc, diag::warn_typecheck_function_qualifiers)
         << Result << DS.getSourceRange();
@@ -359,12 +361,14 @@
     // FIXME: Shouldn't we be checking SCS_typedef here?
     if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
         TypeQuals && Result->isReferenceType()) {
-      TypeQuals &= ~QualType::Const;
-      TypeQuals &= ~QualType::Volatile;
+      TypeQuals &= ~DeclSpec::TQ_const;
+      TypeQuals &= ~DeclSpec::TQ_volatile;
     }
 
-    Result = Result.getQualifiedType(TypeQuals);
+    Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals);
+    Result = Context.getQualifiedType(Result, Quals);
   }
+
   return Result;
 }
 
@@ -399,23 +403,25 @@
     return QualType();
   }
 
+  Qualifiers Qs = Qualifiers::fromCVRMask(Quals);
+
   // Enforce C99 6.7.3p2: "Types other than pointer types derived from
   // object or incomplete types shall not be restrict-qualified."
-  if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
+  if (Qs.hasRestrict() && !T->isIncompleteOrObjectType()) {
     Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
       << T;
-    Quals &= ~QualType::Restrict;
+    Qs.removeRestrict();
   }
 
   // Build the pointer type.
-  return Context.getPointerType(T).getQualifiedType(Quals);
+  return Context.getQualifiedType(Context.getPointerType(T), Qs);
 }
 
 /// \brief Build a reference type.
 ///
 /// \param T The type to which we'll be building a reference.
 ///
-/// \param Quals The cvr-qualifiers to be applied to the reference type.
+/// \param CVR The cvr-qualifiers to be applied to the reference type.
 ///
 /// \param Loc The location of the entity whose type involves this
 /// reference type or, if there is no such entity, the location of the
@@ -426,8 +432,9 @@
 ///
 /// \returns A suitable reference type, if there are no
 /// errors. Otherwise, returns a NULL type.
-QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
+QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned CVR,
                                   SourceLocation Loc, DeclarationName Entity) {
+  Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
   if (LValueRef) {
     if (const RValueReferenceType *R = T->getAs<RValueReferenceType>()) {
       // C++0x [dcl.typedef]p9: If a typedef TD names a type that is a
@@ -435,8 +442,8 @@
       //   reference to cv TD" creates the type "lvalue reference to T".
       // We use the qualifiers (restrict or none) of the original reference,
       // not the new ones. This is consistent with GCC.
-      return Context.getLValueReferenceType(R->getPointeeType()).
-               getQualifiedType(T.getCVRQualifiers());
+      QualType LVRT = Context.getLValueReferenceType(R->getPointeeType());
+      return Context.getQualifiedType(LVRT, T.getQualifiers());
     }
   }
   if (T->isReferenceType()) {
@@ -449,7 +456,7 @@
     //   typedef int& intref;
     //   typedef intref& intref2;
     //
-    // Parser::ParserDeclaratorInternal diagnoses the case where
+    // Parser::ParseDeclaratorInternal diagnoses the case where
     // references are written directly; here, we handle the
     // collapsing of references-to-references as described in C++
     // DR 106 and amended by C++ DR 540.
@@ -466,10 +473,10 @@
 
   // Enforce C99 6.7.3p2: "Types other than pointer types derived from
   // object or incomplete types shall not be restrict-qualified."
-  if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
+  if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) {
     Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
       << T;
-    Quals &= ~QualType::Restrict;
+    Quals.removeRestrict();
   }
 
   // C++ [dcl.ref]p1:
@@ -481,13 +488,13 @@
   // We diagnose extraneous cv-qualifiers for the non-typedef,
   // non-template type argument case within the parser. Here, we just
   // ignore any extraneous cv-qualifiers.
-  Quals &= ~QualType::Const;
-  Quals &= ~QualType::Volatile;
+  Quals.removeConst();
+  Quals.removeVolatile();
 
   // Handle restrict on references.
   if (LValueRef)
-    return Context.getLValueReferenceType(T).getQualifiedType(Quals);
-  return Context.getRValueReferenceType(T).getQualifiedType(Quals);
+    return Context.getQualifiedType(Context.getLValueReferenceType(T), Quals);
+  return Context.getQualifiedType(Context.getRValueReferenceType(T), Quals);
 }
 
 /// \brief Build an array type.
@@ -513,6 +520,7 @@
 QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
                               Expr *ArraySize, unsigned Quals,
                               SourceRange Brackets, DeclarationName Entity) {
+
   SourceLocation Loc = Brackets.getBegin();
   // C99 6.7.5.2p1: If the element type is an incomplete or function type,
   // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
@@ -706,15 +714,17 @@
 ///
 /// \param T the type to which the member pointer refers.
 /// \param Class the class type into which the member pointer points.
-/// \param Quals Qualifiers applied to the member pointer type
+/// \param CVR Qualifiers applied to the member pointer type
 /// \param Loc the location where this type begins
 /// \param Entity the name of the entity that will have this member pointer type
 ///
 /// \returns a member pointer type, if successful, or a NULL type if there was
 /// an error.
 QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
-                                      unsigned Quals, SourceLocation Loc,
+                                      unsigned CVR, SourceLocation Loc,
                                       DeclarationName Entity) {
+  Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
+
   // Verify that we're not building a pointer to pointer to function with
   // exception specification.
   if (CheckDistantExceptionSpec(T)) {
@@ -744,13 +754,13 @@
 
   // Enforce C99 6.7.3p2: "Types other than pointer types derived from
   // object or incomplete types shall not be restrict-qualified."
-  if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
+  if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) {
     Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
       << T;
 
     // FIXME: If we're doing this as part of template instantiation,
     // we should return immediately.
-    Quals &= ~QualType::Restrict;
+    Quals.removeRestrict();
   }
 
   if (!Class->isDependentType() && !Class->isRecordType()) {
@@ -758,15 +768,15 @@
     return QualType();
   }
 
-  return Context.getMemberPointerType(T, Class.getTypePtr())
-           .getQualifiedType(Quals);
+  return Context.getQualifiedType(
+           Context.getMemberPointerType(T, Class.getTypePtr()), Quals);
 }
 
 /// \brief Build a block pointer type.
 ///
 /// \param T The type to which we'll be building a block pointer.
 ///
-/// \param Quals The cvr-qualifiers to be applied to the block pointer type.
+/// \param CVR The cvr-qualifiers to be applied to the block pointer type.
 ///
 /// \param Loc The location of the entity whose type involves this
 /// block pointer type or, if there is no such entity, the location of the
@@ -777,15 +787,16 @@
 ///
 /// \returns A suitable block pointer type, if there are no
 /// errors. Otherwise, returns a NULL type.
-QualType Sema::BuildBlockPointerType(QualType T, unsigned Quals,
+QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR,
                                      SourceLocation Loc,
                                      DeclarationName Entity) {
-  if (!T.getTypePtr()->isFunctionType()) {
+  if (!T->isFunctionType()) {
     Diag(Loc, diag::err_nonfunction_block_type);
     return QualType();
   }
 
-  return Context.getBlockPointerType(T).getQualifiedType(Quals);
+  Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
+  return Context.getQualifiedType(Context.getBlockPointerType(T), Quals);
 }
 
 QualType Sema::GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo) {
@@ -921,8 +932,9 @@
     case DeclaratorChunk::BlockPointer:
       if (ShouldBuildInfo) {
         if (SourceTy->isFunctionType())
-          SourceTy = Context.getBlockPointerType(SourceTy)
-                                      .getQualifiedType(DeclType.Cls.TypeQuals);
+          SourceTy
+            = Context.getQualifiedType(Context.getBlockPointerType(SourceTy),
+                             Qualifiers::fromCVRMask(DeclType.Cls.TypeQuals));
         else
           // If not function type Context::getBlockPointerType asserts,
           // so just give up.
@@ -939,8 +951,8 @@
     case DeclaratorChunk::Pointer:
       //FIXME: Use ObjCObjectPointer for info when appropriate.
       if (ShouldBuildInfo)
-        SourceTy = Context.getPointerType(SourceTy)
-                                      .getQualifiedType(DeclType.Ptr.TypeQuals);
+        SourceTy = Context.getQualifiedType(Context.getPointerType(SourceTy),
+                             Qualifiers::fromCVRMask(DeclType.Ptr.TypeQuals));
       // Verify that we're not building a pointer to pointer to function with
       // exception specification.
       if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
@@ -957,14 +969,16 @@
       }
       T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
       break;
-    case DeclaratorChunk::Reference:
+    case DeclaratorChunk::Reference: {
+      Qualifiers Quals;
+      if (DeclType.Ref.HasRestrict) Quals.addRestrict();
+
       if (ShouldBuildInfo) {
         if (DeclType.Ref.LValueRef)
           SourceTy = Context.getLValueReferenceType(SourceTy);
         else
           SourceTy = Context.getRValueReferenceType(SourceTy);
-        unsigned Quals = DeclType.Ref.HasRestrict ? QualType::Restrict : 0;
-        SourceTy = SourceTy.getQualifiedType(Quals);
+        SourceTy = Context.getQualifiedType(SourceTy, Quals);
       }
 
       // Verify that we're not building a reference to pointer to function with
@@ -974,15 +988,15 @@
         D.setInvalidType(true);
         // Build the type anyway.
       }
-      T = BuildReferenceType(T, DeclType.Ref.LValueRef,
-                             DeclType.Ref.HasRestrict ? QualType::Restrict : 0,
+      T = BuildReferenceType(T, DeclType.Ref.LValueRef, Quals,
                              DeclType.Loc, Name);
       break;
+    }
     case DeclaratorChunk::Array: {
       if (ShouldBuildInfo)
         // We just need to get an array type, the exact type doesn't matter.
         SourceTy = Context.getIncompleteArrayType(SourceTy, ArrayType::Normal,
-                                                DeclType.Arr.TypeQuals);
+                                                  DeclType.Arr.TypeQuals);
 
       // Verify that we're not building an array of pointers to function with
       // exception specification.
@@ -1009,7 +1023,8 @@
         ASM = ArrayType::Normal;
         D.setInvalidType(true);
       }
-      T = BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
+      T = BuildArrayType(T, ASM, ArraySize,
+                         Qualifiers::fromCVRMask(ATI.TypeQuals),
                          SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
       break;
     }
@@ -1028,7 +1043,8 @@
         }
         SourceTy = Context.getFunctionType(SourceTy, ArgTys.data(),
                                            ArgTys.size(),
-                                           FTI.isVariadic, FTI.TypeQuals);
+                                           FTI.isVariadic,
+                                           FTI.TypeQuals);
       }
 
       // If the function declarator has a prototype (i.e. it is not () and
@@ -1132,7 +1148,7 @@
               Param->setType(ArgTy);
             } else {
               // Reject, but continue to parse 'float(const void)'.
-              if (ArgTy.getCVRQualifiers())
+              if (ArgTy.hasQualifiers())
                 Diag(DeclType.Loc, diag::err_void_param_qualified);
 
               // Do not add 'void' to the ArgTys list.
@@ -1198,8 +1214,9 @@
 
       if (ShouldBuildInfo) {
         QualType cls = !ClsType.isNull() ? ClsType : Context.IntTy;
-        SourceTy = Context.getMemberPointerType(SourceTy, cls.getTypePtr())
-                                      .getQualifiedType(DeclType.Mem.TypeQuals);
+        SourceTy = Context.getQualifiedType(
+                      Context.getMemberPointerType(SourceTy, cls.getTypePtr()),
+                      Qualifiers::fromCVRMask(DeclType.Mem.TypeQuals));
       }
 
       if (!ClsType.isNull())
@@ -1479,7 +1496,7 @@
       SubIsPointer = true;
     }
     bool SubIsClass = CanonicalSubT->isRecordType();
-    CanonicalSubT.setCVRQualifiers(0);
+    CanonicalSubT = CanonicalSubT.getUnqualifiedType();
 
     BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
                     /*DetectVirtual=*/false);
@@ -1501,7 +1518,7 @@
           continue;
         }
       }
-      CanonicalSuperT.setCVRQualifiers(0);
+      CanonicalSuperT = CanonicalSuperT.getUnqualifiedType();
       // If the types are the same, move on to the next type in the subset.
       if (CanonicalSubT == CanonicalSuperT) {
         Contained = true;
@@ -1633,6 +1650,7 @@
 /// space for the type.
 static void HandleAddressSpaceTypeAttribute(QualType &Type,
                                             const AttributeList &Attr, Sema &S){
+
   // If this type is already address space qualified, reject it.
   // Clause 6.7.3 - Type qualifiers: "No type shall be qualified by qualifiers
   // for two or more different address spaces."
@@ -1664,10 +1682,10 @@
     addrSpace.setIsSigned(false);
   }
   llvm::APSInt max(addrSpace.getBitWidth());
-  max = QualType::MaxAddressSpace;
+  max = Qualifiers::MaxAddressSpace;
   if (addrSpace > max) {
     S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
-      << QualType::MaxAddressSpace << ASArgExpr->getSourceRange();
+      << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange();
     return;
   }
 
@@ -1679,7 +1697,7 @@
 /// specified type.  The attribute contains 1 argument, weak or strong.
 static void HandleObjCGCTypeAttribute(QualType &Type,
                                       const AttributeList &Attr, Sema &S) {
-  if (Type.getObjCGCAttr() != QualType::GCNone) {
+  if (Type.getObjCGCAttr() != Qualifiers::GCNone) {
     S.Diag(Attr.getLoc(), diag::err_attribute_multiple_objc_gc);
     return;
   }
@@ -1690,15 +1708,15 @@
       << "objc_gc" << 1;
     return;
   }
-  QualType::GCAttrTypes GCAttr;
+  Qualifiers::GC GCAttr;
   if (Attr.getNumArgs() != 0) {
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     return;
   }
   if (Attr.getParameterName()->isStr("weak"))
-    GCAttr = QualType::Weak;
+    GCAttr = Qualifiers::Weak;
   else if (Attr.getParameterName()->isStr("strong"))
-    GCAttr = QualType::Strong;
+    GCAttr = Qualifiers::Strong;
   else {
     S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
       << "objc_gc" << Attr.getParameterName();
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index bd7fb4f..ffbf69b 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -188,7 +188,7 @@
   /// not permitted (e.g., qualifiers on reference or function types). This
   /// is the right thing for template instantiation, but probably not for
   /// other clients.
-  QualType AddTypeQualifiers(QualType T, unsigned CVRQualifiers);
+  QualType AddTypeQualifiers(QualType T, Qualifiers Qs);
 
   /// \brief Transform the given statement.
   ///
@@ -1935,13 +1935,16 @@
   if (getDerived().AlreadyTransformed(T))
     return T;
 
+  QualifierCollector Qs;
+  const Type *Ty = Qs.strip(T);
+
   QualType Result;
-  switch (T->getTypeClass()) {
+  switch (Ty->getTypeClass()) {
 #define ABSTRACT_TYPE(CLASS, PARENT)
 #define TYPE(CLASS, PARENT)                                                  \
     case Type::CLASS:                                                        \
       Result = getDerived().Transform##CLASS##Type(                          \
-                                  static_cast<CLASS##Type*>(T.getTypePtr())); \
+                                       static_cast<const CLASS##Type*>(Ty)); \
       break;
 #include "clang/AST/TypeNodes.def"
   }
@@ -1949,25 +1952,19 @@
   if (Result.isNull() || T == Result)
     return Result;
 
-  return getDerived().AddTypeQualifiers(Result, T.getCVRQualifiers());
+  return getDerived().AddTypeQualifiers(Result, Qs);
 }
 
 template<typename Derived>
 QualType
-TreeTransform<Derived>::AddTypeQualifiers(QualType T, unsigned CVRQualifiers) {
-  if (CVRQualifiers && !T->isFunctionType() && !T->isReferenceType())
-    return T.getWithAdditionalQualifiers(CVRQualifiers);
+TreeTransform<Derived>::AddTypeQualifiers(QualType T, Qualifiers Quals) {
+  if (!Quals.empty() && !T->isFunctionType() && !T->isReferenceType())
+    return SemaRef.Context.getQualifiedType(T, Quals);
 
   return T;
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformExtQualType(const ExtQualType *T) {
-  // FIXME: Implement
-  return QualType(T, 0);
-}
-
-template<typename Derived>
 QualType TreeTransform<Derived>::TransformBuiltinType(const BuiltinType *T) {
   // Nothing to do
   return QualType(T, 0);
@@ -2076,7 +2073,7 @@
   return getDerived().RebuildConstantArrayType(ElementType,
                                                T->getSizeModifier(),
                                                T->getSize(),
-                                               T->getIndexTypeQualifier());
+                                               T->getIndexTypeCVRQualifiers());
 }
 
 template<typename Derived>
@@ -2103,7 +2100,7 @@
                                                        T->getSizeModifier(),
                                                        T->getSize(),
                                                        Size.takeAs<Expr>(),
-                                                   T->getIndexTypeQualifier(),
+                                               T->getIndexTypeCVRQualifiers(),
                                                        T->getBracketsRange());
 }
 
@@ -2122,7 +2119,7 @@
   return getDerived().RebuildConstantArrayWithoutExprType(ElementType,
                                                        T->getSizeModifier(),
                                                        T->getSize(),
-                                                    T->getIndexTypeQualifier());
+                                             T->getIndexTypeCVRQualifiers());
 }
 
 template<typename Derived>
@@ -2138,7 +2135,7 @@
 
   return getDerived().RebuildIncompleteArrayType(ElementType,
                                                  T->getSizeModifier(),
-                                                 T->getIndexTypeQualifier());
+                                               T->getIndexTypeCVRQualifiers());
 }
 
 template<typename Derived>
@@ -2165,7 +2162,7 @@
   return getDerived().RebuildVariableArrayType(ElementType,
                                                T->getSizeModifier(),
                                                move(Size),
-                                               T->getIndexTypeQualifier(),
+                                               T->getIndexTypeCVRQualifiers(),
                                                T->getBracketsRange());
 }
 
@@ -2193,7 +2190,7 @@
   return getDerived().RebuildDependentSizedArrayType(ElementType,
                                                      T->getSizeModifier(),
                                                      move(Size),
-                                                     T->getIndexTypeQualifier(),
+                                            T->getIndexTypeCVRQualifiers(),
                                                      T->getBracketsRange());
 }
 
@@ -4462,14 +4459,14 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType) {
-  return SemaRef.BuildPointerType(PointeeType, 0,
+  return SemaRef.BuildPointerType(PointeeType, Qualifiers(),
                                   getDerived().getBaseLocation(),
                                   getDerived().getBaseEntity());
 }
 
 template<typename Derived>
 QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) {
-  return SemaRef.BuildBlockPointerType(PointeeType, 0,
+  return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(),
                                        getDerived().getBaseLocation(),
                                        getDerived().getBaseEntity());
 }
@@ -4477,7 +4474,7 @@
 template<typename Derived>
 QualType
 TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) {
-  return SemaRef.BuildReferenceType(ReferentType, true, 0,
+  return SemaRef.BuildReferenceType(ReferentType, true, Qualifiers(),
                                     getDerived().getBaseLocation(),
                                     getDerived().getBaseEntity());
 }
@@ -4485,7 +4482,7 @@
 template<typename Derived>
 QualType
 TreeTransform<Derived>::RebuildRValueReferenceType(QualType ReferentType) {
-  return SemaRef.BuildReferenceType(ReferentType, false, 0,
+  return SemaRef.BuildReferenceType(ReferentType, false, Qualifiers(),
                                     getDerived().getBaseLocation(),
                                     getDerived().getBaseEntity());
 }
@@ -4493,7 +4490,7 @@
 template<typename Derived>
 QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
                                                           QualType ClassType) {
-  return SemaRef.BuildMemberPointerType(PointeeType, ClassType, 0,
+  return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Qualifiers(),
                                         getDerived().getBaseLocation(),
                                         getDerived().getBaseEntity());
 }
@@ -4700,7 +4697,7 @@
                                                    QualType T) {
   if (T->isDependentType() || T->isRecordType() ||
       (SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) {
-    assert(T.getCVRQualifiers() == 0 && "Can't get cv-qualifiers here");
+    assert(!T.hasQualifiers() && "Can't get cv-qualifiers here");
     return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW,
                                        T.getTypePtr());
   }