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/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp
index a6af2f8..d92d4cb 100644
--- a/lib/Frontend/DocumentXML.cpp
+++ b/lib/Frontend/DocumentXML.cpp
@@ -135,7 +135,7 @@
 
   for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end();
        i != e; ++i) {
-    if (i->first.getCVRQualifiers() != 0) {
+    if (i->first.hasQualifiers()) {
       writeTypeToXML(i->first);
       addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
       toParent();
@@ -205,7 +205,7 @@
   {
     addTypeRecursively(pType.getTypePtr());
     // beautifier: a non-qualified type shall be transparent
-    if (pType.getCVRQualifiers() == 0)
+    if (!pType.hasQualifiers())
     {
       Types[pType] = BasicTypes[pType.getTypePtr()];
     }
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index c493e39..73c0b8d 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -1764,18 +1764,11 @@
   unsigned Code = Stream.ReadCode();
   switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
   case pch::TYPE_EXT_QUAL: {
-    assert(Record.size() == 3 &&
+    assert(Record.size() == 2 &&
            "Incorrect encoding of extended qualifier type");
     QualType Base = GetType(Record[0]);
-    QualType::GCAttrTypes GCAttr = (QualType::GCAttrTypes)Record[1];
-    unsigned AddressSpace = Record[2];
-
-    QualType T = Base;
-    if (GCAttr != QualType::GCNone)
-      T = Context->getObjCGCQualType(T, GCAttr);
-    if (AddressSpace)
-      T = Context->getAddrSpaceQualType(T, AddressSpace);
-    return T;
+    Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]);
+    return Context->getQualifiedType(Base, Quals);
   }
 
   case pch::TYPE_FIXED_WIDTH_INT: {
@@ -1984,8 +1977,8 @@
 
 
 QualType PCHReader::GetType(pch::TypeID ID) {
-  unsigned Quals = ID & 0x07;
-  unsigned Index = ID >> 3;
+  unsigned FastQuals = ID & Qualifiers::FastMask;
+  unsigned Index = ID >> Qualifiers::FastWidth;
 
   if (Index < pch::NUM_PREDEF_TYPE_IDS) {
     QualType T;
@@ -2026,15 +2019,15 @@
     }
 
     assert(!T.isNull() && "Unknown predefined type");
-    return T.getQualifiedType(Quals);
+    return T.withFastQualifiers(FastQuals);
   }
 
   Index -= pch::NUM_PREDEF_TYPE_IDS;
   //assert(Index < TypesLoaded.size() && "Type index out-of-range");
-  if (!TypesLoaded[Index])
-    TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]).getTypePtr();
+  if (TypesLoaded[Index].isNull())
+    TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]);
 
-  return QualType(TypesLoaded[Index], Quals);
+  return TypesLoaded[Index].withFastQualifiers(FastQuals);
 }
 
 Decl *PCHReader::GetDecl(pch::DeclID ID) {
@@ -2155,7 +2148,7 @@
 
   unsigned NumTypesLoaded
     = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
-                                      (Type *)0);
+                                      QualType());
   unsigned NumDeclsLoaded
     = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
                                       (Decl *)0);
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 531c6f7..8ef846f 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -64,13 +64,6 @@
   };
 }
 
-void PCHTypeWriter::VisitExtQualType(const ExtQualType *T) {
-  Writer.AddTypeRef(QualType(T->getBaseType(), 0), Record);
-  Record.push_back(T->getObjCGCAttr()); // FIXME: use stable values
-  Record.push_back(T->getAddressSpace());
-  Code = pch::TYPE_EXT_QUAL;
-}
-
 void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) {
   assert(false && "Built-in types are never serialized");
 }
@@ -115,7 +108,7 @@
 void PCHTypeWriter::VisitArrayType(const ArrayType *T) {
   Writer.AddTypeRef(T->getElementType(), Record);
   Record.push_back(T->getSizeModifier()); // FIXME: stable values
-  Record.push_back(T->getIndexTypeQualifier()); // FIXME: stable values
+  Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values
 }
 
 void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
@@ -1087,7 +1080,7 @@
 //===----------------------------------------------------------------------===//
 
 /// \brief Write the representation of a type to the PCH stream.
-void PCHWriter::WriteType(const Type *T) {
+void PCHWriter::WriteType(QualType T) {
   pch::TypeID &ID = TypeIDs[T];
   if (ID == 0) // we haven't seen this type before.
     ID = NextTypeID++;
@@ -1104,22 +1097,30 @@
 
   // Emit the type's representation.
   PCHTypeWriter W(*this, Record);
-  switch (T->getTypeClass()) {
-    // For all of the concrete, non-dependent types, call the
-    // appropriate visitor function.
+
+  if (T.hasNonFastQualifiers()) {
+    Qualifiers Qs = T.getQualifiers();
+    AddTypeRef(T.getUnqualifiedType(), Record);
+    Record.push_back(Qs.getAsOpaqueValue());
+    W.Code = pch::TYPE_EXT_QUAL;
+  } else {
+    switch (T->getTypeClass()) {
+      // For all of the concrete, non-dependent types, call the
+      // appropriate visitor function.
 #define TYPE(Class, Base) \
-    case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
+      case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
 #define ABSTRACT_TYPE(Class, Base)
 #define DEPENDENT_TYPE(Class, Base)
 #include "clang/AST/TypeNodes.def"
 
-    // For all of the dependent type nodes (which only occur in C++
-    // templates), produce an error.
+      // For all of the dependent type nodes (which only occur in C++
+      // templates), produce an error.
 #define TYPE(Class, Base)
 #define DEPENDENT_TYPE(Class, Base) case Type::Class:
 #include "clang/AST/TypeNodes.def"
-    assert(false && "Cannot serialize dependent type nodes");
-    break;
+      assert(false && "Cannot serialize dependent type nodes");
+      break;
+    }
   }
 
   // Emit the serialized record.
@@ -1136,9 +1137,8 @@
 
   // Emit all of the types that need to be emitted (so far).
   while (!TypesToEmit.empty()) {
-    const Type *T = TypesToEmit.front();
+    QualType T = TypesToEmit.front();
     TypesToEmit.pop();
-    assert(!isa<BuiltinType>(T) && "Built-in types are not serialized");
     WriteType(T);
   }
 
@@ -1975,6 +1975,26 @@
     return;
   }
 
+  unsigned FastQuals = T.getFastQualifiers();
+  T.removeFastQualifiers();
+
+  if (T.hasNonFastQualifiers()) {
+    pch::TypeID &ID = TypeIDs[T];
+    if (ID == 0) {
+      // We haven't seen these qualifiers applied to this type before.
+      // Assign it a new ID.  This is the only time we enqueue a
+      // qualified type, and it has no CV qualifiers.
+      ID = NextTypeID++;
+      TypesToEmit.push(T);
+    }
+    
+    // Encode the type qualifiers in the type reference.
+    Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
+    return;
+  }
+
+  assert(!T.hasQualifiers());
+  
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
     pch::TypeID ID = 0;
     switch (BT->getKind()) {
@@ -2010,20 +2030,20 @@
       break;
     }
 
-    Record.push_back((ID << 3) | T.getCVRQualifiers());
+    Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
     return;
   }
 
-  pch::TypeID &ID = TypeIDs[T.getTypePtr()];
+  pch::TypeID &ID = TypeIDs[T];
   if (ID == 0) {
     // We haven't seen this type before. Assign it a new ID and put it
-    // into the queu of types to emit.
+    // into the queue of types to emit.
     ID = NextTypeID++;
-    TypesToEmit.push(T.getTypePtr());
+    TypesToEmit.push(T);
   }
 
   // Encode the type qualifiers in the type reference.
-  Record.push_back((ID << 3) | T.getCVRQualifiers());
+  Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
 }
 
 void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index 57b1fc3..55ab78e 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -1937,8 +1937,7 @@
 void RewriteObjC::SynthSelGetUidFunctionDecl() {
   IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
   llvm::SmallVector<QualType, 16> ArgTys;
-  ArgTys.push_back(Context->getPointerType(
-    Context->CharTy.getQualifiedType(QualType::Const)));
+  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
   QualType getFuncType = Context->getFunctionType(Context->getObjCSelType(),
                                                    &ArgTys[0], ArgTys.size(),
                                                    false /*isVariadic*/, 0);
@@ -2084,8 +2083,7 @@
 void RewriteObjC::SynthGetClassFunctionDecl() {
   IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
   llvm::SmallVector<QualType, 16> ArgTys;
-  ArgTys.push_back(Context->getPointerType(
-                     Context->CharTy.getQualifiedType(QualType::Const)));
+  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
   QualType getClassType = Context->getFunctionType(Context->getObjCIdType(),
                                                    &ArgTys[0], ArgTys.size(),
                                                    false /*isVariadic*/, 0);
@@ -2099,8 +2097,7 @@
 void RewriteObjC::SynthGetMetaClassFunctionDecl() {
   IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
   llvm::SmallVector<QualType, 16> ArgTys;
-  ArgTys.push_back(Context->getPointerType(
-                     Context->CharTy.getQualifiedType(QualType::Const)));
+  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
   QualType getClassType = Context->getFunctionType(Context->getObjCIdType(),
                                                    &ArgTys[0], ArgTys.size(),
                                                    false /*isVariadic*/, 0);