[cfe-commits] r82705 - in /cfe/trunk: include/clang/AST/ include/clang/Frontend/ include/clang/Parse/ lib/AST/ lib/CodeGen/ lib/Frontend/ lib/Sema/ test/Sema/

John McCall rjmccall at apple.com
Thu Sep 24 12:53:01 PDT 2009


Author: rjmccall
Date: Thu Sep 24 14:53:00 2009
New Revision: 82705

URL: http://llvm.org/viewvc/llvm-project?rev=82705&view=rev
Log:
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.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/CanonicalType.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/AST/TypeNodes.def
    cfe/trunk/include/clang/Frontend/DocumentXML.h
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/include/clang/Frontend/PCHWriter.h
    cfe/trunk/include/clang/Frontend/TypeXML.def
    cfe/trunk/include/clang/Parse/DeclSpec.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/DeclarationName.cpp
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/AST/StmtDumper.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp
    cfe/trunk/lib/CodeGen/CGValue.h
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
    cfe/trunk/lib/CodeGen/Mangle.cpp
    cfe/trunk/lib/Frontend/DocumentXML.cpp
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Frontend/RewriteObjC.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaCXXCast.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaInherit.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/Sema/address_spaces.c

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu Sep 24 14:53:00 2009
@@ -63,7 +63,7 @@
 /// decls) that can be referred to throughout the semantic analysis of a file.
 class ASTContext {
   std::vector<Type*> Types;
-  llvm::FoldingSet<ExtQualType> ExtQualTypes;
+  llvm::FoldingSet<ExtQuals> ExtQualNodes;
   llvm::FoldingSet<ComplexType> ComplexTypes;
   llvm::FoldingSet<PointerType> PointerTypes;
   llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
@@ -332,6 +332,11 @@
   //                           Type Constructors
   //===--------------------------------------------------------------------===//
 
+private:
+  /// getExtQualType - Return a type with extended qualifiers.
+  QualType getExtQualType(const Type *Base, Qualifiers Quals);
+
+public:
   /// getAddSpaceQualType - Return the uniqued reference to the type for an
   /// address space qualified type with the specified type and address space.
   /// The resulting type has a union of the qualifiers from T and the address
@@ -342,7 +347,27 @@
   /// getObjCGCQualType - Returns the uniqued reference to the type for an
   /// objc gc qualified type. The retulting type has a union of the qualifiers
   /// from T and the gc attribute.
-  QualType getObjCGCQualType(QualType T, QualType::GCAttrTypes gcAttr);
+  QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr);
+
+  /// getRestrictType - Returns the uniqued reference to the type for a
+  /// 'restrict' qualified type.  The resulting type has a union of the
+  /// qualifiers from T and 'restrict'.
+  QualType getRestrictType(QualType T) {
+    return T.withFastQualifiers(Qualifiers::Restrict);
+  }
+
+  /// getVolatileType - Returns the uniqued reference to the type for a
+  /// 'volatile' qualified type.  The resulting type has a union of the
+  /// qualifiers from T and 'volatile'.
+  QualType getVolatileType(QualType T);
+
+  /// getConstType - Returns the uniqued reference to the type for a
+  /// 'const' qualified type.  The resulting type has a union of the
+  /// qualifiers from T and 'const'.
+  ///
+  /// It can be reasonably expected that this will always be
+  /// equivalent to calling T.withConst().
+  QualType getConstType(QualType T) { return T.withConst(); }
 
   /// getNoReturnType - Add the noreturn attribute to the given type which must
   /// be a FunctionType or a pointer to an allowable type or a BlockPointer.
@@ -636,6 +661,28 @@
 
   QualType getFixedWidthIntType(unsigned Width, bool Signed);
 
+  /// getCVRQualifiedType - Returns a type with additional const,
+  /// volatile, or restrict qualifiers.
+  QualType getCVRQualifiedType(QualType T, unsigned CVR) {
+    return getQualifiedType(T, Qualifiers::fromCVRMask(CVR));
+  }
+
+  /// getQualifiedType - Returns a type with additional qualifiers.
+  QualType getQualifiedType(QualType T, Qualifiers Qs) {
+    if (!Qs.hasNonFastQualifiers())
+      return T.withFastQualifiers(Qs.getFastQualifiers());
+    QualifierCollector Qc(Qs);
+    const Type *Ptr = Qc.strip(T);
+    return getExtQualType(Ptr, Qc);
+  }
+
+  /// getQualifiedType - Returns a type with additional qualifiers.
+  QualType getQualifiedType(const Type *T, Qualifiers Qs) {
+    if (!Qs.hasNonFastQualifiers())
+      return QualType(T, Qs.getFastQualifiers());
+    return getExtQualType(T, Qs);
+  }
+
   TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
                                         bool TemplateKeyword,
                                         TemplateDecl *Template);
@@ -666,7 +713,7 @@
   /// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
   /// garbage collection attribute.
   ///
-  QualType::GCAttrTypes getObjCGCAttrKind(const QualType &Ty) const;
+  Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const;
 
   /// isObjCNSObjectType - Return true if this is an NSObject object with
   /// its NSObject attribute set.

Modified: cfe/trunk/include/clang/AST/CanonicalType.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CanonicalType.h?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/CanonicalType.h (original)
+++ cfe/trunk/include/clang/AST/CanonicalType.h Thu Sep 24 14:53:00 2009
@@ -103,20 +103,23 @@
   /// proxy.
   CanProxy<T> operator->() const;
 
+  /// \brief Retrieve all qualifiers.
+  Qualifiers getQualifiers() const { return Stored.getQualifiers(); }
+
   /// \brief Retrieve the const/volatile/restrict qualifiers.
   unsigned getCVRQualifiers() const { return Stored.getCVRQualifiers(); }
 
-  /// \brief Set the const/volatile/restrict qualifiers
-  void setCVRQualifiers(unsigned Quals) { Stored.setCVRQualifiers(Quals); }
+  /// \brief Determines whether this type has any qualifiers
+  bool hasQualifiers() const { return Stored.hasQualifiers(); }
 
   bool isConstQualified() const {
-    return (getCVRQualifiers() & QualType::Const) ? true : false;
+    return Stored.isConstQualified();
   }
   bool isVolatileQualified() const {
-    return (getCVRQualifiers() & QualType::Volatile) ? true : false;
+    return Stored.isVolatileQualified();
   }
   bool isRestrictQualified() const {
-    return (getCVRQualifiers() & QualType::Restrict) ? true : false;
+    return Stored.isRestrictQualified();
   }
 
   /// \brief Retrieve the unqualified form of this type.
@@ -322,7 +325,7 @@
   static inline clang::CanQual<T> getFromVoidPointer(void *P) {
     return clang::CanQual<T>::getFromOpaquePtr(P);
   }
-  // CVR qualifiers go in low bits.
+  // qualifier information is encoded in the low bits.
   enum { NumLowBitsAvailable = 0 };
 };
 
@@ -426,13 +429,6 @@
 };
 
 template<>
-struct CanProxyAdaptor<ExtQualType> : public CanProxyBase<ExtQualType> {
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type*, getBaseType)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(QualType::GCAttrTypes, getObjCGCAttr)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getAddressSpace)
-};
-
-template<>
 struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> {
   LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
 };
@@ -477,7 +473,7 @@
   LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
                                       getSizeModifier)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
+  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
 };
 
 template<>
@@ -486,7 +482,7 @@
   LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
                                       getSizeModifier)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
+  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
 };
 
@@ -496,7 +492,7 @@
   LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
                                       getSizeModifier)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
+  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
@@ -510,7 +506,7 @@
   LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
                                       getSizeModifier)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
+  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
 };
 
@@ -520,7 +516,7 @@
   LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
                                       getSizeModifier)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
+  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
 };
 
 template<>
@@ -529,7 +525,7 @@
   LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
                                       getSizeModifier)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
+  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
@@ -666,9 +662,7 @@
 //----------------------------------------------------------------------------//
 template<typename T>
 inline CanQual<T> CanQual<T>::getUnqualifiedType() const {
-  if (CanQual<ExtQualType> EQ = getAs<ExtQualType>())
-    return CanQual<T>::CreateUnsafe(QualType(EQ->getBaseType(), 0));
-  return CanQual<T>::CreateUnsafe(QualType(Stored.getTypePtr(), 0));
+  return CanQual<T>::CreateUnsafe(Stored.getUnqualifiedType());
 }
 
 template<typename T>
@@ -707,10 +701,6 @@
   if (isa<U>(Stored.getTypePtr()))
     return CanQual<U>::CreateUnsafe(Stored);
 
-  if (const ExtQualType *EQ = Stored->getAs<ExtQualType>())
-    return CanQual<T>::CreateUnsafe(QualType(EQ->getBaseType(), 0))
-             .template getAs<U>();
-
   return CanProxy<U>();
 }
 

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Sep 24 14:53:00 2009
@@ -30,7 +30,7 @@
 using llvm::cast_or_null;
 using llvm::dyn_cast;
 using llvm::dyn_cast_or_null;
-namespace clang { class Type; }
+namespace clang { class Type; class ExtQuals; }
 
 namespace llvm {
   template <typename T>
@@ -44,6 +44,15 @@
     }
     enum { NumLowBitsAvailable = 3 };
   };
+  template<>
+  class PointerLikeTypeTraits< ::clang::ExtQuals*> {
+  public:
+    static inline void *getAsVoidPointer(::clang::ExtQuals *P) { return P; }
+    static inline ::clang::ExtQuals *getFromVoidPointer(void *P) {
+      return static_cast< ::clang::ExtQuals*>(P);
+    }
+    enum { NumLowBitsAvailable = 3 };
+  };
 }
 
 namespace clang {
@@ -73,43 +82,345 @@
 #define TYPE(Class, Base) class Class##Type;
 #include "clang/AST/TypeNodes.def"
 
-/// QualType - For efficiency, we don't store CVR-qualified types as nodes on
-/// their own: instead each reference to a type stores the qualifiers.  This
-/// greatly reduces the number of nodes we need to allocate for types (for
-/// example we only need one for 'int', 'const int', 'volatile int',
-/// 'const volatile int', etc).
-///
-/// As an added efficiency bonus, instead of making this a pair, we just store
-/// the three bits we care about in the low bits of the pointer.  To handle the
-/// packing/unpacking, we make QualType be a simple wrapper class that acts like
-/// a smart pointer.
-class QualType {
-  llvm::PointerIntPair<Type*, 3> Value;
+/// Qualifiers - The collection of all-type qualifiers we support.
+/// Clang supports five independent qualifiers:
+/// * C99: const, volatile, and restrict
+/// * Embedded C (TR18037): address spaces
+/// * Objective C: the GC attributes (none, weak, or strong)
+class Qualifiers {
 public:
-  enum TQ {   // NOTE: These flags must be kept in sync with DeclSpec::TQ.
+  enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ.
     Const    = 0x1,
     Restrict = 0x2,
     Volatile = 0x4,
-    CVRFlags = Const|Restrict|Volatile
+    CVRMask = Const | Volatile | Restrict
   };
 
-  enum GCAttrTypes {
+  enum GC {
     GCNone = 0,
     Weak,
     Strong
   };
 
-  // 24 bits should be enough for anyone.
-  static const unsigned MaxAddressSpace = 0xffffffu;
+  enum {
+    /// The maximum supported address space number.
+    /// 24 bits should be enough for anyone.
+    MaxAddressSpace = 0xffffffu,
+
+    /// The width of the "fast" qualifier mask.
+    FastWidth = 2,
+
+    /// The fast qualifier mask.
+    FastMask = (1 << FastWidth) - 1
+  };
+
+  Qualifiers() : Mask(0) {}
+
+  static Qualifiers fromFastMask(unsigned Mask) {
+    Qualifiers Qs;
+    Qs.addFastQualifiers(Mask);
+    return Qs;
+  }
+
+  static Qualifiers fromCVRMask(unsigned CVR) {
+    Qualifiers Qs;
+    Qs.addCVRQualifiers(CVR);
+    return Qs;
+  }
+
+  // Deserialize qualifiers from an opaque representation.
+  static Qualifiers fromOpaqueValue(unsigned opaque) {
+    Qualifiers Qs;
+    Qs.Mask = opaque;
+    return Qs;
+  }
+
+  // Serialize these qualifiers into an opaque representation.
+  unsigned getAsOpaqueValue() const {
+    return Mask;
+  }
+
+  bool hasConst() const { return Mask & Const; }
+  void setConst(bool flag) {
+    Mask = (Mask & ~Const) | (flag ? Const : 0);
+  }
+  void removeConst() { Mask &= ~Const; }
+  void addConst() { Mask |= Const; }
+
+  bool hasVolatile() const { return Mask & Volatile; }
+  void setVolatile(bool flag) {
+    Mask = (Mask & ~Volatile) | (flag ? Volatile : 0);
+  }
+  void removeVolatile() { Mask &= ~Volatile; }
+  void addVolatile() { Mask |= Volatile; }
+
+  bool hasRestrict() const { return Mask & Restrict; }
+  void setRestrict(bool flag) {
+    Mask = (Mask & ~Restrict) | (flag ? Restrict : 0);
+  }
+  void removeRestrict() { Mask &= ~Restrict; }
+  void addRestrict() { Mask |= Restrict; }
+
+  bool hasCVRQualifiers() const { return getCVRQualifiers(); }
+  unsigned getCVRQualifiers() const { return Mask & CVRMask; }
+  void setCVRQualifiers(unsigned mask) {
+    assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
+    Mask = (Mask & ~CVRMask) | mask;
+  }
+  void removeCVRQualifiers(unsigned mask) {
+    assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
+    Mask &= ~mask;
+  }
+  void removeCVRQualifiers() {
+    removeCVRQualifiers(CVRMask);
+  }
+  void addCVRQualifiers(unsigned mask) {
+    assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
+    Mask |= mask;
+  }
+
+  bool hasObjCGCAttr() const { return Mask & GCAttrMask; }
+  GC getObjCGCAttr() const { return GC((Mask & GCAttrMask) >> GCAttrShift); }
+  void setObjCGCAttr(GC type) {
+    Mask = (Mask & ~GCAttrMask) | (type << GCAttrShift);
+  }
+  void removeObjCGCAttr() { setObjCGCAttr(GCNone); }
+  void addObjCGCAttr(GC type) {
+    assert(type);
+    setObjCGCAttr(type);
+  }
+
+  bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
+  unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
+  void setAddressSpace(unsigned space) {
+    assert(space <= MaxAddressSpace);
+    Mask = (Mask & ~AddressSpaceMask)
+         | (((uint32_t) space) << AddressSpaceShift);
+  }
+  void removeAddressSpace() { setAddressSpace(0); }
+  void addAddressSpace(unsigned space) {
+    assert(space);
+    setAddressSpace(space);
+  }
+
+  // Fast qualifiers are those that can be allocated directly
+  // on a QualType object.
+  bool hasFastQualifiers() const { return getFastQualifiers(); }
+  unsigned getFastQualifiers() const { return Mask & FastMask; }
+  void setFastQualifiers(unsigned mask) {
+    assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
+    Mask = (Mask & ~FastMask) | mask;
+  }
+  void removeFastQualifiers(unsigned mask) {
+    assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
+    Mask &= ~mask;
+  }
+  void removeFastQualifiers() {
+    removeFastQualifiers(FastMask);
+  }
+  void addFastQualifiers(unsigned mask) {
+    assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
+    Mask |= mask;
+  }
+
+  /// hasNonFastQualifiers - Return true if the set contains any
+  /// qualifiers which require an ExtQuals node to be allocated.
+  bool hasNonFastQualifiers() const { return Mask & ~FastMask; }
+  Qualifiers getNonFastQualifiers() const {
+    Qualifiers Quals = *this;
+    Quals.setFastQualifiers(0);
+    return Quals;
+  }
+
+  /// hasQualifiers - Return true if the set contains any qualifiers.
+  bool hasQualifiers() const { return Mask; }
+  bool empty() const { return !Mask; }
+
+  /// \brief Add the qualifiers from the given set to this set.
+  void addQualifiers(Qualifiers Q) {
+    // If the other set doesn't have any non-boolean qualifiers, just
+    // bit-or it in.
+    if (!(Q.Mask & ~CVRMask))
+      Mask |= Q.Mask;
+    else {
+      Mask |= (Q.Mask & CVRMask);
+      if (Q.hasAddressSpace())
+        addAddressSpace(Q.getAddressSpace());
+      if (Q.hasObjCGCAttr())
+        addObjCGCAttr(Q.getObjCGCAttr());
+    }
+  }
+
+  bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
+  bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
+
+  operator bool() const { return hasQualifiers(); }
+
+  Qualifiers &operator+=(Qualifiers R) {
+    addQualifiers(R);
+    return *this;
+  }
+
+  // Union two qualifier sets.  If an enumerated qualifier appears
+  // in both sets, use the one from the right.
+  friend Qualifiers operator+(Qualifiers L, Qualifiers R) {
+    L += R;
+    return L;
+  }
+
+  std::string getAsString() const;
+  std::string getAsString(const PrintingPolicy &Policy) const {
+    std::string Buffer;
+    getAsStringInternal(Buffer, Policy);
+    return Buffer;
+  }
+  void getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const;
+
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    ID.AddInteger(Mask);
+  }
+
+private:
+
+  // bits:     |0 1 2|3 .. 4|5  ..  31|
+  //           |C R V|GCAttr|AddrSpace|
+  uint32_t Mask;
+
+  static const uint32_t GCAttrMask = 0x18;
+  static const uint32_t GCAttrShift = 3;
+  static const uint32_t AddressSpaceMask = ~(CVRMask | GCAttrMask);
+  static const uint32_t AddressSpaceShift = 5;
+};
+
+
+/// ExtQuals - We can encode up to three bits in the low bits of a
+/// type pointer, but there are many more type qualifiers that we want
+/// to be able to apply to an arbitrary type.  Therefore we have this
+/// struct, intended to be heap-allocated and used by QualType to
+/// store qualifiers.
+///
+/// The current design tags the 'const' and 'restrict' qualifiers in
+/// two low bits on the QualType pointer; a third bit records whether
+/// the pointer is an ExtQuals node.  'const' was chosen because it is
+/// orders of magnitude more common than the other two qualifiers, in
+/// both library and user code.  It's relatively rare to see
+/// 'restrict' in user code, but many standard C headers are saturated
+/// with 'restrict' declarations, so that representing them efficiently
+/// is a critical goal of this representation.
+class ExtQuals : public llvm::FoldingSetNode {
+  // NOTE: changing the fast qualifiers should be straightforward as
+  // long as you don't make 'const' non-fast.
+  // 1. Qualifiers:
+  //    a) Modify the bitmasks (Qualifiers::TQ and DeclSpec::TQ).
+  //       Fast qualifiers must occupy the low-order bits.
+  //    b) Update Qualifiers::FastWidth and FastMask.
+  // 2. QualType:
+  //    a) Update is{Volatile,Restrict}Qualified(), defined inline.
+  //    b) Update remove{Volatile,Restrict}, defined near the end of
+  //       this header.
+  // 3. ASTContext:
+  //    a) Update get{Volatile,Restrict}Type.
+
+  /// Context - the context to which this set belongs.  We save this
+  /// here so that QualifierCollector can use it to reapply extended
+  /// qualifiers to an arbitrary type without requiring a context to
+  /// be pushed through every single API dealing with qualifiers.
+  ASTContext& Context;
+
+  /// BaseType - the underlying type that this qualifies
+  const Type *BaseType;
+
+  /// Quals - the immutable set of qualifiers applied by this
+  /// node;  always contains extended qualifiers.
+  Qualifiers Quals;
+
+public:
+  ExtQuals(ASTContext& Context, const Type *Base, Qualifiers Quals)
+    : Context(Context), BaseType(Base), Quals(Quals)
+  {
+    assert(Quals.hasNonFastQualifiers()
+           && "ExtQuals created with no fast qualifiers");
+    assert(!Quals.hasFastQualifiers()
+           && "ExtQuals created with fast qualifiers");
+  }
+
+  Qualifiers getQualifiers() const { return Quals; }
+
+  bool hasVolatile() const { return Quals.hasVolatile(); }
+
+  bool hasObjCGCAttr() const { return Quals.hasObjCGCAttr(); }
+  Qualifiers::GC getObjCGCAttr() const { return Quals.getObjCGCAttr(); }
+
+  bool hasAddressSpace() const { return Quals.hasAddressSpace(); }
+  unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
+
+  const Type *getBaseType() const { return BaseType; }
+
+  ASTContext &getContext() const { return Context; }
+
+public:
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    Profile(ID, getBaseType(), Quals);
+  }
+  static void Profile(llvm::FoldingSetNodeID &ID,
+                      const Type *BaseType,
+                      Qualifiers Quals) {
+    assert(!Quals.hasFastQualifiers() && "fast qualifiers in ExtQuals hash!");
+    ID.AddPointer(BaseType);
+    Quals.Profile(ID);
+  }
+};
+
+
+/// QualType - For efficiency, we don't store CV-qualified types as nodes on
+/// their own: instead each reference to a type stores the qualifiers.  This
+/// greatly reduces the number of nodes we need to allocate for types (for
+/// example we only need one for 'int', 'const int', 'volatile int',
+/// 'const volatile int', etc).
+///
+/// As an added efficiency bonus, instead of making this a pair, we
+/// just store the two bits we care about in the low bits of the
+/// pointer.  To handle the packing/unpacking, we make QualType be a
+/// simple wrapper class that acts like a smart pointer.  A third bit
+/// indicates whether there are extended qualifiers present, in which
+/// case the pointer points to a special structure.
+class QualType {
+  // Thankfully, these are efficiently composable.
+  llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>,
+                       Qualifiers::FastWidth> Value;
+
+  bool hasExtQuals() const {
+    return Value.getPointer().is<const ExtQuals*>();
+  }
+
+  const ExtQuals *getExtQualsUnsafe() const {
+    return Value.getPointer().get<const ExtQuals*>();
+  }
 
+  const Type *getTypePtrUnsafe() const {
+    return Value.getPointer().get<const Type*>();
+  }
+
+  friend class QualifierCollector;
+public:
   QualType() {}
 
   QualType(const Type *Ptr, unsigned Quals)
-    : Value(const_cast<Type*>(Ptr), Quals) {}
-
-  unsigned getCVRQualifiers() const { return Value.getInt(); }
-  void setCVRQualifiers(unsigned Quals) { Value.setInt(Quals); }
-  Type *getTypePtr() const { return Value.getPointer(); }
+    : Value(Ptr, Quals) {}
+  QualType(const ExtQuals *Ptr, unsigned Quals)
+    : Value(Ptr, Quals) {}
+
+  unsigned getFastQualifiers() const { return Value.getInt(); }
+  void setFastQualifiers(unsigned Quals) { Value.setInt(Quals); }
+
+  /// Retrieves a pointer to the underlying (unqualified) type.
+  /// This should really return a const Type, but it's not worth
+  /// changing all the users right now.
+  Type *getTypePtr() const {
+    if (hasNonFastQualifiers())
+      return const_cast<Type*>(getExtQualsUnsafe()->getBaseType());
+    return const_cast<Type*>(getTypePtrUnsafe());
+  }
 
   void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
   static QualType getFromOpaquePtr(void *Ptr) {
@@ -128,43 +439,97 @@
 
   /// isNull - Return true if this QualType doesn't point to a type yet.
   bool isNull() const {
-    return getTypePtr() == 0;
+    return Value.getPointer().isNull();
   }
 
   bool isConstQualified() const {
-    return (getCVRQualifiers() & Const) ? true : false;
+    return (getFastQualifiers() & Qualifiers::Const);
+  }
+  bool isRestrictQualified() const {
+    return (getFastQualifiers() & Qualifiers::Restrict);
   }
   bool isVolatileQualified() const {
-    return (getCVRQualifiers() & Volatile) ? true : false;
+    return (hasNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile());
   }
-  bool isRestrictQualified() const {
-    return (getCVRQualifiers() & Restrict) ? true : false;
+
+  // Determines whether this type has any direct qualifiers.
+  bool hasQualifiers() const {
+    return getFastQualifiers() || hasNonFastQualifiers();
+  }
+
+  bool hasNonFastQualifiers() const {
+    return hasExtQuals();
+  }
+
+  // Retrieves the set of qualifiers belonging to this type.
+  Qualifiers getQualifiers() const {
+    Qualifiers Quals;
+    if (hasNonFastQualifiers())
+      Quals = getExtQualsUnsafe()->getQualifiers();
+    Quals.addFastQualifiers(getFastQualifiers());
+    return Quals;
+  }
+
+  // Retrieves the CVR qualifiers of this type.
+  unsigned getCVRQualifiers() const {
+    unsigned CVR = getFastQualifiers();
+    if (isVolatileQualified()) CVR |= Qualifiers::Volatile;
+    return CVR;
   }
 
   bool isConstant(ASTContext& Ctx) const;
 
-  /// addConst/addVolatile/addRestrict - add the specified type qual to this
-  /// QualType.
-  void addConst()    { Value.setInt(Value.getInt() | Const); }
-  void addVolatile() { Value.setInt(Value.getInt() | Volatile); }
-  void addRestrict() { Value.setInt(Value.getInt() | Restrict); }
+  // Don't promise in the API that anything besides 'const' can be
+  // easily added.
 
-  void removeConst()    { Value.setInt(Value.getInt() & ~Const); }
-  void removeVolatile() { Value.setInt(Value.getInt() & ~Volatile); }
-  void removeRestrict() { Value.setInt(Value.getInt() & ~Restrict); }
+  /// addConst - add the specified type qualifier to this QualType.  
+  void addConst() {
+    addFastQualifiers(Qualifiers::Const);
+  }
+  QualType withConst() const {
+    return withFastQualifiers(Qualifiers::Const);
+  }
+
+  void addFastQualifiers(unsigned TQs) {
+    assert(!(TQs & ~Qualifiers::FastMask)
+           && "non-fast qualifier bits set in mask!");
+    Value.setInt(Value.getInt() | TQs);
+  }
+
+  void removeConst();
+  void removeVolatile();
+  void removeRestrict();
+  void removeCVRQualifiers(unsigned Mask);
+
+  void removeFastQualifiers() { Value.setInt(0); }
+  void removeFastQualifiers(unsigned Mask) {
+    assert(!(Mask & ~Qualifiers::FastMask) && "mask has non-fast qualifiers");
+    Value.setInt(Value.getInt() & ~Mask);
+  }
+
+  // Creates a type with the given qualifiers in addition to any
+  // qualifiers already on this type.
+  QualType withFastQualifiers(unsigned TQs) const {
+    QualType T = *this;
+    T.addFastQualifiers(TQs);
+    return T;
+  }
 
-  QualType getQualifiedType(unsigned TQs) const {
-    return QualType(getTypePtr(), TQs);
+  // Creates a type with exactly the given fast qualifiers, removing
+  // any existing fast qualifiers.
+  QualType withExactFastQualifiers(unsigned TQs) const {
+    return withoutFastQualifiers().withFastQualifiers(TQs);
   }
-  QualType getWithAdditionalQualifiers(unsigned TQs) const {
-    return QualType(getTypePtr(), TQs|getCVRQualifiers());
+
+  // Removes fast qualifiers, but leaves any extended qualifiers in place.
+  QualType withoutFastQualifiers() const {
+    QualType T = *this;
+    T.removeFastQualifiers();
+    return T;
   }
 
-  QualType withConst() const { return getWithAdditionalQualifiers(Const); }
-  QualType withVolatile() const { return getWithAdditionalQualifiers(Volatile);}
-  QualType withRestrict() const { return getWithAdditionalQualifiers(Restrict);}
+  QualType getUnqualifiedType() const { return QualType(getTypePtr(), 0); }
 
-  QualType getUnqualifiedType() const;
   bool isMoreQualifiedThan(QualType Other) const;
   bool isAtLeastAsQualifiedAs(QualType Other) const;
   QualType getNonReferenceType() const;
@@ -175,6 +540,8 @@
   /// to getting the canonical type, but it doesn't remove *all* typedefs.  For
   /// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
   /// concrete.
+  ///
+  /// Qualifiers are left in place.
   QualType getDesugaredType(bool ForDisplay = false) const;
 
   /// operator==/!= - Indicate whether the specified types and qualifiers are
@@ -202,22 +569,20 @@
     ID.AddPointer(getAsOpaquePtr());
   }
 
-public:
-
   /// getAddressSpace - Return the address space of this type.
   inline unsigned getAddressSpace() const;
 
   /// GCAttrTypesAttr - Returns gc attribute of this type.
-  inline QualType::GCAttrTypes getObjCGCAttr() const;
+  inline Qualifiers::GC getObjCGCAttr() const;
 
   /// isObjCGCWeak true when Type is objc's weak.
   bool isObjCGCWeak() const {
-    return getObjCGCAttr() == Weak;
+    return getObjCGCAttr() == Qualifiers::Weak;
   }
 
   /// isObjCGCStrong true when Type is objc's strong.
   bool isObjCGCStrong() const {
-    return getObjCGCAttr() == Strong;
+    return getObjCGCAttr() == Qualifiers::Strong;
   }
 
   /// getNoReturnAttr - Returns true if the type has the noreturn attribute,
@@ -249,7 +614,7 @@
   static inline clang::QualType getFromVoidPointer(void *P) {
     return clang::QualType::getFromOpaquePtr(P);
   }
-  // CVR qualifiers go in low bits.
+  // Various qualifiers go in low bits.
   enum { NumLowBitsAvailable = 0 };
 };
 
@@ -519,151 +884,11 @@
 #define TYPE(Class, Base)
 #define LEAF_TYPE(Class) \
 template <> inline const Class##Type *Type::getAs() const { \
-  return dyn_cast<Class##Type>(CanonicalType.getUnqualifiedType()); \
+  return dyn_cast<Class##Type>(CanonicalType); \
 }
 #include "clang/AST/TypeNodes.def"
 
 
-/// ExtQualType - TR18037 (C embedded extensions) 6.2.5p26
-/// This supports all kinds of type attributes; including,
-/// address space qualified types, objective-c's __weak and
-/// __strong attributes.
-///
-class ExtQualType : public Type, public llvm::FoldingSetNode {
-  /// BaseType - This is the underlying type that this qualifies.  All CVR
-  /// qualifiers are stored on the QualType that references this type, so we
-  /// can't have any here.
-  Type *BaseType;
-
-  /// Address Space ID - The address space ID this type is qualified with.
-  unsigned AddressSpace;
-  /// GC __weak/__strong attributes
-  QualType::GCAttrTypes GCAttrType;
-
-  ExtQualType(Type *Base, QualType CanonicalPtr, unsigned AddrSpace,
-              QualType::GCAttrTypes gcAttr) :
-      Type(ExtQual, CanonicalPtr, Base->isDependentType()), BaseType(Base),
-      AddressSpace(AddrSpace), GCAttrType(gcAttr) {
-    assert(!isa<ExtQualType>(BaseType) &&
-           "Cannot have ExtQualType of ExtQualType");
-  }
-  friend class ASTContext;  // ASTContext creates these.
-public:
-  Type *getBaseType() const { return BaseType; }
-  QualType::GCAttrTypes getObjCGCAttr() const { return GCAttrType; }
-  unsigned getAddressSpace() const { return AddressSpace; }
-
-  virtual void getAsStringInternal(std::string &InnerString,
-                                   const PrintingPolicy &Policy) const;
-
-  void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getBaseType(), AddressSpace, GCAttrType);
-  }
-  static void Profile(llvm::FoldingSetNodeID &ID, Type *Base,
-                      unsigned AddrSpace, QualType::GCAttrTypes gcAttr) {
-    ID.AddPointer(Base);
-    ID.AddInteger(AddrSpace);
-    ID.AddInteger(gcAttr);
-  }
-
-  static bool classof(const Type *T) { return T->getTypeClass() == ExtQual; }
-  static bool classof(const ExtQualType *) { return true; }
-};
-
-
-/// QualifierSet - This class is used to collect qualifiers.
-/// Clang supports five independent qualifiers:
-/// * C99: const, volatile, and restrict
-/// * Embedded C (TR18037): address spaces
-/// * Objective C: the GC attributes (none, weak, or strong)
-class QualifierSet {
-public:
-  QualifierSet() : Mask(0) {}
-
-  void removeConst() { removeCVR(QualType::Const); }
-  void removeVolatile() { removeCVR(QualType::Volatile); }
-  void removeRestrict() { removeCVR(QualType::Restrict); }
-  void removeCVR(unsigned mask) { Mask &= ~mask; }
-  void removeAddressSpace() { setAddressSpace(0); }
-  void removeObjCGCAttrType() { setGCAttrType(QualType::GCNone); }
-
-  void addConst() { addCVR(QualType::Const); }
-  void addVolatile() { addCVR(QualType::Volatile); }
-  void addRestrict() { addCVR(QualType::Restrict); }
-  void addCVR(unsigned mask) { Mask |= mask; }
-  void addAddressSpace(unsigned space) {
-    assert(space);
-    setAddressSpace(space);
-  }
-  void addObjCGCAttrType(QualType::GCAttrTypes type) {
-    assert(type);
-    setGCAttrType(type);
-  }
-
-  bool hasConst() const { return Mask & QualType::Const; }
-  bool hasVolatile() const { return Mask & QualType::Volatile; }
-  bool hasRestrict() const { return Mask & QualType::Restrict; }
-  unsigned getCVRMask() const { return Mask & CVRMask; }
-
-  bool hasObjCGCAttrType() const { return Mask & GCAttrMask; }
-  QualType::GCAttrTypes getObjCGCAttrType() const {
-    return QualType::GCAttrTypes((Mask & GCAttrMask) >> GCAttrShift);
-  }
-
-  bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
-  unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
-
-  /// empty() - Return true if there are no qualifiers collected
-  /// in this set.
-  bool empty() {
-    return (Mask == 0);
-  }
-
-  /// Collect any qualifiers on the given type and return an
-  /// unqualified type.
-  const Type *strip(QualType QT) {
-    Mask |= QT.getCVRQualifiers();
-    return strip(QT.getTypePtr());
-  }
-
-  /// Collect any qualifiers on the given type and return an
-  /// unqualified type.
-  const Type *strip(const Type* T);
-
-  /// Apply the collected qualifiers to the given type.
-  QualType apply(QualType QT, ASTContext& C);
-
-  /// Apply the collected qualifiers to the given type.
-  QualType apply(const Type* T, ASTContext& C) {
-    return apply(QualType(T, 0), C);
-  }
-
-  bool operator==(QualifierSet& Other) { return Mask == Other.Mask; }
-
-private:
-  void setAddressSpace(unsigned space) {
-    assert(space <= MaxAddressSpace);
-    Mask = (Mask & ~AddressSpaceMask)
-         | (((uint32_t) space) << AddressSpaceShift);
-  }
-
-  void setGCAttrType(QualType::GCAttrTypes type) {
-    Mask = (Mask & ~GCAttrMask) | (type << GCAttrShift);
-  }
-
-  // bits:     |0 1 2|3 .. 4|5  ..  31|
-  //           |C R V|GCAttr|AddrSpace|
-  uint32_t Mask;
-
-  static const uint32_t CVRMask = 0x07;
-  static const uint32_t GCAttrMask = 0x18;
-  static const uint32_t GCAttrShift = 3;
-  static const uint32_t AddressSpaceMask = ~(CVRMask | GCAttrMask);
-  static const uint32_t AddressSpaceShift = 5;
-  static const unsigned MaxAddressSpace = QualType::MaxAddressSpace;
-};
-
-
 /// BuiltinType - This class is used for builtin types like 'int'.  Builtin
 /// types are always canonical and have a literal name field.
 class BuiltinType : public Type {
@@ -967,7 +1192,10 @@
   ArraySizeModifier getSizeModifier() const {
     return ArraySizeModifier(SizeModifier);
   }
-  unsigned getIndexTypeQualifier() const { return IndexTypeQuals; }
+  Qualifiers getIndexTypeQualifiers() const {
+    return Qualifiers::fromCVRMask(IndexTypeQuals);
+  }
+  unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; }
 
   static bool classof(const Type *T) {
     return T->getTypeClass() == ConstantArray ||
@@ -1003,7 +1231,7 @@
 
   void Profile(llvm::FoldingSetNodeID &ID) {
     Profile(ID, getElementType(), getSize(),
-            getSizeModifier(), getIndexTypeQualifier());
+            getSizeModifier(), getIndexTypeCVRQualifiers());
   }
   static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
                       const llvm::APInt &ArraySize, ArraySizeModifier SizeMod,
@@ -1109,7 +1337,8 @@
   friend class StmtIteratorBase;
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getElementType(), getSizeModifier(), getIndexTypeQualifier());
+    Profile(ID, getElementType(), getSizeModifier(),
+            getIndexTypeCVRQualifiers());
   }
 
   static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
@@ -1226,7 +1455,7 @@
 
   void Profile(llvm::FoldingSetNodeID &ID) {
     Profile(ID, Context, getElementType(),
-            getSizeModifier(), getIndexTypeQualifier(), getSizeExpr());
+            getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr());
   }
 
   static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
@@ -1709,7 +1938,7 @@
   /// @brief Determines whether this type is in the process of being
   /// defined.
   bool isBeingDefined() const { return decl.getInt(); }
-  void setBeingDefined(bool Def) { decl.setInt(Def? 1 : 0); }
+  void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
 
   virtual void getAsStringInternal(std::string &InnerString,
                                    const PrintingPolicy &Policy) const;
@@ -2206,41 +2435,119 @@
   static bool classof(const ObjCObjectPointerType *) { return true; }
 };
 
+/// A qualifier set is used to build a set of qualifiers.
+class QualifierCollector : public Qualifiers {
+  ASTContext *Context;
+
+public:
+  QualifierCollector(Qualifiers Qs = Qualifiers())
+    : Qualifiers(Qs), Context(0) {}
+  QualifierCollector(ASTContext &Context, Qualifiers Qs = Qualifiers())
+    : Qualifiers(Qs), Context(&Context) {}
+
+  void setContext(ASTContext &C) { Context = &C; }
+
+  /// Collect any qualifiers on the given type and return an
+  /// unqualified type.
+  const Type *strip(QualType QT) {
+    addFastQualifiers(QT.getFastQualifiers());
+    if (QT.hasNonFastQualifiers()) {
+      const ExtQuals *EQ = QT.getExtQualsUnsafe();
+      Context = &EQ->getContext();
+      addQualifiers(EQ->getQualifiers());
+      return EQ->getBaseType();
+    }
+    return QT.getTypePtrUnsafe();
+  }
+
+  /// Apply the collected qualifiers to the given type.
+  QualType apply(QualType QT) const;
+
+  /// Apply the collected qualifiers to the given type.
+  QualType apply(const Type* T) const;
+
+};
+
+
 // Inline function definitions.
 
-/// getUnqualifiedType - Return the type without any qualifiers.
-inline QualType QualType::getUnqualifiedType() const {
-  Type *TP = getTypePtr();
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(TP))
-    TP = EXTQT->getBaseType();
-  return QualType(TP, 0);
+inline void QualType::removeConst() {
+  removeFastQualifiers(Qualifiers::Const);
+}
+
+inline void QualType::removeRestrict() {
+  removeFastQualifiers(Qualifiers::Restrict);
+}
+
+inline void QualType::removeVolatile() {
+  QualifierCollector Qc;
+  const Type *Ty = Qc.strip(*this);
+  if (Qc.hasVolatile()) {
+    Qc.removeVolatile();
+    *this = Qc.apply(Ty);
+  }
+}
+
+inline void QualType::removeCVRQualifiers(unsigned Mask) {
+  assert(!(Mask & ~Qualifiers::CVRMask) && "mask has non-fast qualifiers");
+
+  // Fast path: we don't need to touch the slow qualifiers.
+  if (!(Mask & ~Qualifiers::FastMask)) {
+    removeFastQualifiers(Mask);
+    return;
+  }
+
+  QualifierCollector Qc;
+  const Type *Ty = Qc.strip(*this);
+  Qc.removeCVRQualifiers(Mask);
+  *this = Qc.apply(Ty);
 }
 
 /// getAddressSpace - Return the address space of this type.
 inline unsigned QualType::getAddressSpace() const {
+  if (hasNonFastQualifiers()) {
+    const ExtQuals *EQ = getExtQualsUnsafe();
+    if (EQ->hasAddressSpace())
+      return EQ->getAddressSpace();
+  }
+
   QualType CT = getTypePtr()->getCanonicalTypeInternal();
+  if (CT.hasNonFastQualifiers()) {
+    const ExtQuals *EQ = CT.getExtQualsUnsafe();
+    if (EQ->hasAddressSpace())
+      return EQ->getAddressSpace();
+  }
+
   if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
     return AT->getElementType().getAddressSpace();
   if (const RecordType *RT = dyn_cast<RecordType>(CT))
     return RT->getAddressSpace();
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CT))
-    return EXTQT->getAddressSpace();
   return 0;
 }
 
 /// getObjCGCAttr - Return the gc attribute of this type.
-inline QualType::GCAttrTypes QualType::getObjCGCAttr() const {
+inline Qualifiers::GC QualType::getObjCGCAttr() const {
+  if (hasNonFastQualifiers()) {
+    const ExtQuals *EQ = getExtQualsUnsafe();
+    if (EQ->hasObjCGCAttr())
+      return EQ->getObjCGCAttr();
+  }
+
   QualType CT = getTypePtr()->getCanonicalTypeInternal();
+  if (CT.hasNonFastQualifiers()) {
+    const ExtQuals *EQ = CT.getExtQualsUnsafe();
+    if (EQ->hasObjCGCAttr())
+      return EQ->getObjCGCAttr();
+  }
+
   if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
       return AT->getElementType().getObjCGCAttr();
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CT))
-    return EXTQT->getObjCGCAttr();
   if (const ObjCObjectPointerType *PT = CT->getAs<ObjCObjectPointerType>())
     return PT->getPointeeType().getObjCGCAttr();
   // We most look at all pointer types, not just pointer to interface types.
   if (const PointerType *PT = CT->getAs<PointerType>())
     return PT->getPointeeType().getObjCGCAttr();
-  return GCNone;
+  return Qualifiers::GCNone;
 }
 
   /// getNoReturnAttr - Returns true if the type has the noreturn attribute,
@@ -2262,6 +2569,7 @@
 /// "int". However, it is not more qualified than "const volatile
 /// int".
 inline bool QualType::isMoreQualifiedThan(QualType Other) const {
+  // FIXME: work on arbitrary qualifiers
   unsigned MyQuals = this->getCVRQualifiers();
   unsigned OtherQuals = Other.getCVRQualifiers();
   if (getAddressSpace() != Other.getAddressSpace())
@@ -2274,6 +2582,7 @@
 /// int" is at least as qualified as "const int", "volatile int",
 /// "int", and "const volatile int".
 inline bool QualType::isAtLeastAsQualifiedAs(QualType Other) const {
+  // FIXME: work on arbitrary qualifiers
   unsigned MyQuals = this->getCVRQualifiers();
   unsigned OtherQuals = Other.getCVRQualifiers();
   if (getAddressSpace() != Other.getAddressSpace())
@@ -2441,14 +2750,10 @@
     return Ty;
 
   // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<T>(CanonicalType)) {
-    // Look through type qualifiers
-    if (isa<T>(CanonicalType.getUnqualifiedType()))
-      return CanonicalType.getUnqualifiedType()->getAs<T>();
+  if (!isa<T>(CanonicalType))
     return 0;
-  }
 
-  // If this is a typedef for a pointer type, strip the typedef off without
+  // If this is a typedef for the type, strip the typedef off without
   // losing all typedef information.
   return cast<T>(getDesugaredType());
 }

Modified: cfe/trunk/include/clang/AST/TypeNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeNodes.def?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/TypeNodes.def (original)
+++ cfe/trunk/include/clang/AST/TypeNodes.def Thu Sep 24 14:53:00 2009
@@ -51,7 +51,6 @@
 #  define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
 #endif
 
-TYPE(ExtQual, Type)
 TYPE(Builtin, Type)
 TYPE(FixedWidthInt, Type)
 TYPE(Complex, Type)

Modified: cfe/trunk/include/clang/Frontend/DocumentXML.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/DocumentXML.h?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/DocumentXML.h (original)
+++ cfe/trunk/include/clang/Frontend/DocumentXML.h Thu Sep 24 14:53:00 2009
@@ -132,6 +132,7 @@
   // for addAttributeOptional:
   static bool isDefault(unsigned value)           { return value == 0; }
   static bool isDefault(bool value)               { return !value; }
+  static bool isDefault(Qualifiers::GC value)     { return value == Qualifiers::GCNone; }
   static bool isDefault(const std::string& value) { return value.empty(); }
 };
 

Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Thu Sep 24 14:53:00 2009
@@ -206,7 +206,7 @@
   ///
   /// When the pointer at index I is non-NULL, the type with
   /// ID = (I + 1) << 3 has already been loaded from the PCH file.
-  std::vector<Type *> TypesLoaded;
+  std::vector<QualType> TypesLoaded;
 
   /// \brief Offset of each declaration within the bitstream, indexed
   /// by the declaration ID (-1).

Modified: cfe/trunk/include/clang/Frontend/PCHWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHWriter.h?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Thu Sep 24 14:53:00 2009
@@ -40,6 +40,24 @@
 class SwitchCase;
 class TargetInfo;
 
+/// A structure for putting "fast"-unqualified QualTypes into a
+/// DenseMap.  This uses the standard pointer hash function.
+struct UnsafeQualTypeDenseMapInfo {
+  static inline bool isEqual(QualType A, QualType B) { return A == B; }
+  static inline bool isPod() { return true; }
+  static inline QualType getEmptyKey() {
+    return QualType::getFromOpaquePtr((void*) 1);
+  }
+  static inline QualType getTombstoneKey() {
+    return QualType::getFromOpaquePtr((void*) 2);
+  }
+  static inline unsigned getHashValue(QualType T) {
+    assert(!T.getFastQualifiers() && "hash invalid for types with fast quals");
+    uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+    return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
+  }
+};
+
 /// \brief Writes a precompiled header containing the contents of a
 /// translation unit.
 ///
@@ -76,9 +94,11 @@
   ///
   /// The ID numbers of types are consecutive (in order of discovery)
   /// and start at 1. 0 is reserved for NULL. When types are actually
-  /// stored in the stream, the ID number is shifted by 3 bits to
-  /// allow for the const/volatile/restrict qualifiers.
-  llvm::DenseMap<const Type *, pch::TypeID> TypeIDs;
+  /// stored in the stream, the ID number is shifted by 2 bits to
+  /// allow for the const/volatile qualifiers.
+  ///
+  /// Keys in the map never have const/volatile qualifiers.
+  llvm::DenseMap<QualType, pch::TypeID, UnsafeQualTypeDenseMapInfo> TypeIDs;
 
   /// \brief Offset of each type in the bitstream, indexed by
   /// the type's ID.
@@ -89,7 +109,7 @@
 
   /// \brief Queue containing the types that we still need to
   /// emit.
-  std::queue<const Type *> TypesToEmit;
+  std::queue<QualType> TypesToEmit;
 
   /// \brief Map that provides the ID numbers of each identifier in
   /// the output stream.
@@ -168,7 +188,7 @@
                                const char* isysroot);
   void WritePreprocessor(const Preprocessor &PP);
   void WriteComments(ASTContext &Context);
-  void WriteType(const Type *T);
+  void WriteType(QualType T);
   void WriteTypesBlock(ASTContext &Context);
   uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
   uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);

Modified: cfe/trunk/include/clang/Frontend/TypeXML.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/TypeXML.def?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/TypeXML.def (original)
+++ cfe/trunk/include/clang/Frontend/TypeXML.def Thu Sep 24 14:53:00 2009
@@ -68,17 +68,8 @@
   ATTRIBUTE_OPT_XML(isConstQualified(), "const")        // boolean
   ATTRIBUTE_OPT_XML(isVolatileQualified(), "volatile")  // boolean
   ATTRIBUTE_OPT_XML(isRestrictQualified(), "restrict")  // boolean
-END_NODE_XML
-
-NODE_XML(ExtQualType, "ExtQualType")
-  ID_ATTRIBUTE_XML
-  TYPE_ATTRIBUTE_XML(getBaseType())
-  ATTRIBUTE_OPT_XML(getAddressSpace(), "adress_space")  // unsigned: Address Space ID - The address space ID this type is qualified with.
-  ATTRIBUTE_ENUM_OPT_XML(getObjCGCAttr(), "objc_gc")    // GC __weak/__strong attributes
-	  ENUM_XML(QualType::GCNone, "")
-	  ENUM_XML(QualType::Weak, "weak")
-	  ENUM_XML(QualType::Strong, "strong")
-  END_ENUM_XML
+  ATTRIBUTE_OPT_XML(getObjCGCAttr(), "objc_gc")         // Qualifiers::GC
+  ATTRIBUTE_OPT_XML(getAddressSpace(), "address_space") // unsigned
 END_NODE_XML
 
 NODE_XML(BuiltinType, "FundamentalType")
@@ -175,7 +166,7 @@
 	  ENUM_XML(ArrayType::Static, "static")
 	  ENUM_XML(ArrayType::Star, "star")
   END_ENUM_XML
-  ATTRIBUTE_OPT_XML(getIndexTypeQualifier(), "index_type_qualifier")   // unsigned
+  ATTRIBUTE_OPT_XML(getIndexTypeCVRQualifiers(), "index_type_qualifier")   // unsigned
 END_NODE_XML
 
 NODE_XML(IncompleteArrayType, "IncompleteArrayType")

Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Thu Sep 24 14:53:00 2009
@@ -90,7 +90,7 @@
   };
 
   // type-qualifiers
-  enum TQ {   // NOTE: These flags must be kept in sync with QualType::TQ.
+  enum TQ {   // NOTE: These flags must be kept in sync with Qualifiers::TQ.
     TQ_unspecified = 0,
     TQ_const       = 1,
     TQ_restrict    = 2,

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Sep 24 14:53:00 2009
@@ -59,6 +59,13 @@
   }
 
   {
+    llvm::FoldingSet<ExtQuals>::iterator
+      I = ExtQualNodes.begin(), E = ExtQualNodes.end();
+    while (I != E)
+      Deallocate(&*I++);
+  }
+
+  {
     llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
       I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end();
     while (I != E) {
@@ -525,6 +532,10 @@
 
 /// getTypeSize - Return the size of the specified type, in bits.  This method
 /// does not work on incomplete types.
+///
+/// FIXME: Pointers into different addr spaces could have different sizes and
+/// alignment requirements: getPointerInfo should take an AddrSpace, this
+/// should take a QualType, &c.
 std::pair<uint64_t, unsigned>
 ASTContext::getTypeInfo(const Type *T) {
   uint64_t Width=0;
@@ -656,10 +667,6 @@
     Width = std::max(llvm::NextPowerOf2(Width - 1), (uint64_t)8);
     Align = Width;
     break;
-  case Type::ExtQual:
-    // FIXME: Pointers into different addr spaces could have different sizes and
-    // alignment requirements: getPointerInfo should take an AddrSpace.
-    return getTypeInfo(QualType(cast<ExtQualType>(T)->getBaseType(), 0));
   case Type::ObjCObjectPointer:
     Width = Target.getPointerWidth(0);
     Align = Target.getPointerAlign(0);
@@ -1002,52 +1009,58 @@
 //                   Type creation/memoization methods
 //===----------------------------------------------------------------------===//
 
-QualType ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) {
-  QualType CanT = getCanonicalType(T);
-  if (CanT.getAddressSpace() == AddressSpace)
-    return T;
-
-  // If we are composing extended qualifiers together, merge together into one
-  // ExtQualType node.
-  unsigned CVRQuals = T.getCVRQualifiers();
-  QualType::GCAttrTypes GCAttr = QualType::GCNone;
-  Type *TypeNode = T.getTypePtr();
-
-  if (ExtQualType *EQT = dyn_cast<ExtQualType>(TypeNode)) {
-    // If this type already has an address space specified, it cannot get
-    // another one.
-    assert(EQT->getAddressSpace() == 0 &&
-           "Type cannot be in multiple addr spaces!");
-    GCAttr = EQT->getObjCGCAttr();
-    TypeNode = EQT->getBaseType();
-  }
+QualType ASTContext::getExtQualType(const Type *TypeNode, Qualifiers Quals) {
+  unsigned Fast = Quals.getFastQualifiers();
+  Quals.removeFastQualifiers();
 
   // Check if we've already instantiated this type.
   llvm::FoldingSetNodeID ID;
-  ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
+  ExtQuals::Profile(ID, TypeNode, Quals);
   void *InsertPos = 0;
-  if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
-    return QualType(EXTQy, CVRQuals);
+  if (ExtQuals *EQ = ExtQualNodes.FindNodeOrInsertPos(ID, InsertPos)) {
+    assert(EQ->getQualifiers() == Quals);
+    QualType T = QualType(EQ, Fast);
+    return T;
+  }
 
-  // If the base type isn't canonical, this won't be a canonical type either,
-  // so fill in the canonical type field.
-  QualType Canonical;
-  if (!TypeNode->isCanonical()) {
-    Canonical = getAddrSpaceQualType(CanT, AddressSpace);
+  ExtQuals *New = new (*this, 8) ExtQuals(*this, TypeNode, Quals);
+  ExtQualNodes.InsertNode(New, InsertPos);
+  QualType T = QualType(New, Fast);
+  return T;
+}
 
-    // Update InsertPos, the previous call could have invalidated it.
-    ExtQualType *NewIP = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos);
-    assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
-  }
-  ExtQualType *New =
-    new (*this, 8) ExtQualType(TypeNode, Canonical, AddressSpace, GCAttr);
-  ExtQualTypes.InsertNode(New, InsertPos);
-  Types.push_back(New);
-  return QualType(New, CVRQuals);
+QualType ASTContext::getVolatileType(QualType T) {
+  QualType CanT = getCanonicalType(T);
+  if (CanT.isVolatileQualified()) return T;
+
+  QualifierCollector Quals;
+  const Type *TypeNode = Quals.strip(T);
+  Quals.addVolatile();
+
+  return getExtQualType(TypeNode, Quals);
+}
+
+QualType ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) {
+  QualType CanT = getCanonicalType(T);
+  if (CanT.getAddressSpace() == AddressSpace)
+    return T;
+
+  // If we are composing extended qualifiers together, merge together
+  // into one ExtQuals node.
+  QualifierCollector Quals;
+  const Type *TypeNode = Quals.strip(T);
+
+  // If this type already has an address space specified, it cannot get
+  // another one.
+  assert(!Quals.hasAddressSpace() &&
+         "Type cannot be in multiple addr spaces!");
+  Quals.addAddressSpace(AddressSpace);
+
+  return getExtQualType(TypeNode, Quals);
 }
 
 QualType ASTContext::getObjCGCQualType(QualType T,
-                                       QualType::GCAttrTypes GCAttr) {
+                                       Qualifiers::GC GCAttr) {
   QualType CanT = getCanonicalType(T);
   if (CanT.getObjCGCAttr() == GCAttr)
     return T;
@@ -1059,75 +1072,48 @@
       return getPointerType(ResultType);
     }
   }
-  // If we are composing extended qualifiers together, merge together into one
-  // ExtQualType node.
-  unsigned CVRQuals = T.getCVRQualifiers();
-  Type *TypeNode = T.getTypePtr();
-  unsigned AddressSpace = 0;
-
-  if (ExtQualType *EQT = dyn_cast<ExtQualType>(TypeNode)) {
-    // If this type already has an ObjCGC specified, it cannot get
-    // another one.
-    assert(EQT->getObjCGCAttr() == QualType::GCNone &&
-           "Type cannot have multiple ObjCGCs!");
-    AddressSpace = EQT->getAddressSpace();
-    TypeNode = EQT->getBaseType();
-  }
 
-  // Check if we've already instantiated an gc qual'd type of this type.
-  llvm::FoldingSetNodeID ID;
-  ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
-  void *InsertPos = 0;
-  if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
-    return QualType(EXTQy, CVRQuals);
-
-  // If the base type isn't canonical, this won't be a canonical type either,
-  // so fill in the canonical type field.
-  // FIXME: Isn't this also not canonical if the base type is a array
-  // or pointer type?  I can't find any documentation for objc_gc, though...
-  QualType Canonical;
-  if (!T->isCanonical()) {
-    Canonical = getObjCGCQualType(CanT, GCAttr);
+  // If we are composing extended qualifiers together, merge together
+  // into one ExtQuals node.
+  QualifierCollector Quals;
+  const Type *TypeNode = Quals.strip(T);
+
+  // If this type already has an ObjCGC specified, it cannot get
+  // another one.
+  assert(!Quals.hasObjCGCAttr() &&
+         "Type cannot have multiple ObjCGCs!");
+  Quals.addObjCGCAttr(GCAttr);
 
-    // Update InsertPos, the previous call could have invalidated it.
-    ExtQualType *NewIP = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos);
-    assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
-  }
-  ExtQualType *New =
-    new (*this, 8) ExtQualType(TypeNode, Canonical, AddressSpace, GCAttr);
-  ExtQualTypes.InsertNode(New, InsertPos);
-  Types.push_back(New);
-  return QualType(New, CVRQuals);
+  return getExtQualType(TypeNode, Quals);
 }
 
 QualType ASTContext::getNoReturnType(QualType T) {
-  QualifierSet qs;
-  qs.strip(T);
+  QualType ResultType;
   if (T->isPointerType()) {
     QualType Pointee = T->getAs<PointerType>()->getPointeeType();
-    QualType ResultType = getNoReturnType(Pointee);
+    ResultType = getNoReturnType(Pointee);
     ResultType = getPointerType(ResultType);
-    ResultType.setCVRQualifiers(T.getCVRQualifiers());
-    return qs.apply(ResultType, *this);
-  }
-  if (T->isBlockPointerType()) {
+  } else if (T->isBlockPointerType()) {
     QualType Pointee = T->getAs<BlockPointerType>()->getPointeeType();
-    QualType ResultType = getNoReturnType(Pointee);
+    ResultType = getNoReturnType(Pointee);
     ResultType = getBlockPointerType(ResultType);
-    ResultType.setCVRQualifiers(T.getCVRQualifiers());
-    return qs.apply(ResultType, *this);
-  }
-  if (!T->isFunctionType())
-    assert(0 && "can't noreturn qualify non-pointer to function or block type");
+  } else {
+    assert (T->isFunctionType()
+            && "can't noreturn qualify non-pointer to function or block type");
 
-  if (const FunctionNoProtoType *F = T->getAs<FunctionNoProtoType>()) {
-    return getFunctionNoProtoType(F->getResultType(), true);
+    if (const FunctionNoProtoType *F = T->getAs<FunctionNoProtoType>()) {
+      ResultType = getFunctionNoProtoType(F->getResultType(), true);
+    } else {
+      const FunctionProtoType *F = T->getAs<FunctionProtoType>();
+      ResultType
+        = getFunctionType(F->getResultType(), F->arg_type_begin(),
+                          F->getNumArgs(), F->isVariadic(), F->getTypeQuals(),
+                          F->hasExceptionSpec(), F->hasAnyExceptionSpec(),
+                          F->getNumExceptions(), F->exception_begin(), true);
+    }
   }
-  const FunctionProtoType *F = T->getAs<FunctionProtoType>();
-  return getFunctionType(F->getResultType(), F->arg_type_begin(),
-                         F->getNumArgs(), F->isVariadic(), F->getTypeQuals(),
-                         F->hasExceptionSpec(), F->hasAnyExceptionSpec(),
-                         F->getNumExceptions(), F->exception_begin(), true);
+
+  return getQualifiedType(ResultType, T.getQualifiers());
 }
 
 /// getComplexType - Return the uniqued reference to the type for a complex
@@ -1645,8 +1631,8 @@
                                      const QualType *ExArray, bool NoReturn) {
   if (LangOpts.CPlusPlus) {
     for (unsigned i = 0; i != NumArgs; ++i)
-      assert(!ArgArray[i].getCVRQualifiers() && 
-             "C++ arguments can't have toplevel CVR qualifiers!");
+      assert(!ArgArray[i].hasQualifiers() && 
+             "C++ arguments can't have toplevel qualifiers!");
   }
   
   // Unique functions, to guarantee there is only one function of a particular
@@ -2157,33 +2143,38 @@
 /// to be free of any of these, allowing two canonical types to be compared
 /// for exact equality with a simple pointer comparison.
 CanQualType ASTContext::getCanonicalType(QualType T) {
-  QualType CanType = T.getTypePtr()->getCanonicalTypeInternal();
+  QualifierCollector Quals;
+  const Type *Ptr = Quals.strip(T);
+  QualType CanType = Ptr->getCanonicalTypeInternal();
+
+  // The canonical internal type will be the canonical type *except*
+  // that we push type qualifiers down through array types.
 
-  // If the result has type qualifiers, make sure to canonicalize them as well.
-  unsigned TypeQuals = T.getCVRQualifiers() | CanType.getCVRQualifiers();
-  if (TypeQuals == 0)
+  // If there are no new qualifiers to push down, stop here.
+  if (!Quals.hasQualifiers())
     return CanQualType::CreateUnsafe(CanType);
 
-  // If the type qualifiers are on an array type, get the canonical type of the
-  // array with the qualifiers applied to the element type.
+  // If the type qualifiers are on an array type, get the canonical
+  // type of the array with the qualifiers applied to the element
+  // type.
   ArrayType *AT = dyn_cast<ArrayType>(CanType);
   if (!AT)
-    return CanQualType::CreateUnsafe(CanType.getQualifiedType(TypeQuals));
+    return CanQualType::CreateUnsafe(getQualifiedType(CanType, Quals));
 
   // Get the canonical version of the element with the extra qualifiers on it.
   // This can recursively sink qualifiers through multiple levels of arrays.
-  QualType NewEltTy=AT->getElementType().getWithAdditionalQualifiers(TypeQuals);
+  QualType NewEltTy = getQualifiedType(AT->getElementType(), Quals);
   NewEltTy = getCanonicalType(NewEltTy);
 
   if (ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
     return CanQualType::CreateUnsafe(
              getConstantArrayType(NewEltTy, CAT->getSize(),
                                   CAT->getSizeModifier(),
-                                  CAT->getIndexTypeQualifier()));
+                                  CAT->getIndexTypeCVRQualifiers()));
   if (IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT))
     return CanQualType::CreateUnsafe(
              getIncompleteArrayType(NewEltTy, IAT->getSizeModifier(),
-                                    IAT->getIndexTypeQualifier()));
+                                    IAT->getIndexTypeCVRQualifiers()));
 
   if (DependentSizedArrayType *DSAT = dyn_cast<DependentSizedArrayType>(AT))
     return CanQualType::CreateUnsafe(
@@ -2191,7 +2182,7 @@
                                         DSAT->getSizeExpr() ?
                                           DSAT->getSizeExpr()->Retain() : 0,
                                         DSAT->getSizeModifier(),
-                                        DSAT->getIndexTypeQualifier(),
+                                        DSAT->getIndexTypeCVRQualifiers(),
                                         DSAT->getBracketsRange()));
 
   VariableArrayType *VAT = cast<VariableArrayType>(AT);
@@ -2199,7 +2190,7 @@
                                                         VAT->getSizeExpr() ?
                                               VAT->getSizeExpr()->Retain() : 0,
                                                         VAT->getSizeModifier(),
-                                                  VAT->getIndexTypeQualifier(),
+                                              VAT->getIndexTypeCVRQualifiers(),
                                                      VAT->getBracketsRange()));
 }
 
@@ -2316,68 +2307,47 @@
 
 const ArrayType *ASTContext::getAsArrayType(QualType T) {
   // Handle the non-qualified case efficiently.
-  if (T.getCVRQualifiers() == 0) {
+  if (!T.hasQualifiers()) {
     // Handle the common positive case fast.
     if (const ArrayType *AT = dyn_cast<ArrayType>(T))
       return AT;
   }
 
-  // Handle the common negative case fast, ignoring CVR qualifiers.
+  // Handle the common negative case fast.
   QualType CType = T->getCanonicalTypeInternal();
-
-  // Make sure to look through type qualifiers (like ExtQuals) for the negative
-  // test.
-  if (!isa<ArrayType>(CType) &&
-      !isa<ArrayType>(CType.getUnqualifiedType()))
+  if (!isa<ArrayType>(CType))
     return 0;
 
-  // Apply any CVR qualifiers from the array type to the element type.  This
+  // Apply any qualifiers from the array type to the element type.  This
   // implements C99 6.7.3p8: "If the specification of an array type includes
   // any type qualifiers, the element type is so qualified, not the array type."
 
   // If we get here, we either have type qualifiers on the type, or we have
   // sugar such as a typedef in the way.  If we have type qualifiers on the type
   // we must propagate them down into the element type.
-  unsigned CVRQuals = T.getCVRQualifiers();
-  unsigned AddrSpace = 0;
-  Type *Ty = T.getTypePtr();
-
-  // Rip through ExtQualType's and typedefs to get to a concrete type.
-  while (1) {
-    if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(Ty)) {
-      AddrSpace = EXTQT->getAddressSpace();
-      Ty = EXTQT->getBaseType();
-    } else {
-      T = Ty->getDesugaredType();
-      if (T.getTypePtr() == Ty && T.getCVRQualifiers() == 0)
-        break;
-      CVRQuals |= T.getCVRQualifiers();
-      Ty = T.getTypePtr();
-    }
-  }
+
+  QualifierCollector Qs;
+  const Type *Ty = Qs.strip(T.getDesugaredType());
 
   // If we have a simple case, just return now.
   const ArrayType *ATy = dyn_cast<ArrayType>(Ty);
-  if (ATy == 0 || (AddrSpace == 0 && CVRQuals == 0))
+  if (ATy == 0 || Qs.empty())
     return ATy;
 
   // Otherwise, we have an array and we have qualifiers on it.  Push the
   // qualifiers into the array element type and return a new array type.
   // Get the canonical version of the element with the extra qualifiers on it.
   // This can recursively sink qualifiers through multiple levels of arrays.
-  QualType NewEltTy = ATy->getElementType();
-  if (AddrSpace)
-    NewEltTy = getAddrSpaceQualType(NewEltTy, AddrSpace);
-  NewEltTy = NewEltTy.getWithAdditionalQualifiers(CVRQuals);
+  QualType NewEltTy = getQualifiedType(ATy->getElementType(), Qs);
 
   if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(ATy))
     return cast<ArrayType>(getConstantArrayType(NewEltTy, CAT->getSize(),
                                                 CAT->getSizeModifier(),
-                                                CAT->getIndexTypeQualifier()));
+                                           CAT->getIndexTypeCVRQualifiers()));
   if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(ATy))
     return cast<ArrayType>(getIncompleteArrayType(NewEltTy,
                                                   IAT->getSizeModifier(),
-                                                  IAT->getIndexTypeQualifier()));
+                                           IAT->getIndexTypeCVRQualifiers()));
 
   if (const DependentSizedArrayType *DSAT
         = dyn_cast<DependentSizedArrayType>(ATy))
@@ -2386,15 +2356,15 @@
                                                 DSAT->getSizeExpr() ?
                                               DSAT->getSizeExpr()->Retain() : 0,
                                                 DSAT->getSizeModifier(),
-                                                DSAT->getIndexTypeQualifier(),
+                                              DSAT->getIndexTypeCVRQualifiers(),
                                                 DSAT->getBracketsRange()));
 
   const VariableArrayType *VAT = cast<VariableArrayType>(ATy);
   return cast<ArrayType>(getVariableArrayType(NewEltTy,
                                               VAT->getSizeExpr() ?
-                                               VAT->getSizeExpr()->Retain() : 0,
+                                              VAT->getSizeExpr()->Retain() : 0,
                                               VAT->getSizeModifier(),
-                                              VAT->getIndexTypeQualifier(),
+                                              VAT->getIndexTypeCVRQualifiers(),
                                               VAT->getBracketsRange()));
 }
 
@@ -2416,17 +2386,17 @@
   QualType PtrTy = getPointerType(PrettyArrayType->getElementType());
 
   // int x[restrict 4] ->  int *restrict
-  return PtrTy.getQualifiedType(PrettyArrayType->getIndexTypeQualifier());
+  return getQualifiedType(PtrTy, PrettyArrayType->getIndexTypeQualifiers());
 }
 
 QualType ASTContext::getBaseElementType(QualType QT) {
-  QualifierSet qualifiers;
+  QualifierCollector Qs;
   while (true) {
-    const Type *UT = qualifiers.strip(QT);
+    const Type *UT = Qs.strip(QT);
     if (const ArrayType *AT = getAsArrayType(QualType(UT,0))) {
       QT = AT->getElementType();
     } else {
-      return qualifiers.apply(QT, *this);
+      return Qs.apply(QT);
     }
   }
 }
@@ -2651,11 +2621,11 @@
     QualType FieldTypes[4];
 
     // const int *isa;
-    FieldTypes[0] = getPointerType(IntTy.getQualifiedType(QualType::Const));
+    FieldTypes[0] = getPointerType(IntTy.withConst());
     // int flags;
     FieldTypes[1] = IntTy;
     // const char *str;
-    FieldTypes[2] = getPointerType(CharTy.getQualifiedType(QualType::Const));
+    FieldTypes[2] = getPointerType(CharTy.withConst());
     // long length;
     FieldTypes[3] = LongTy;
 
@@ -3139,9 +3109,9 @@
     return;
   }
 
-  if (T->isObjCInterfaceType()) {
+  if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
     // @encode(class_name)
-    ObjCInterfaceDecl *OI = T->getAs<ObjCInterfaceType>()->getDecl();
+    ObjCInterfaceDecl *OI = OIT->getDecl();
     S += '{';
     const IdentifierInfo *II = OI->getIdentifier();
     S += II->getName();
@@ -3388,24 +3358,24 @@
 /// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
 /// garbage collection attribute.
 ///
-QualType::GCAttrTypes ASTContext::getObjCGCAttrKind(const QualType &Ty) const {
-  QualType::GCAttrTypes GCAttrs = QualType::GCNone;
+Qualifiers::GC ASTContext::getObjCGCAttrKind(const QualType &Ty) const {
+  Qualifiers::GC GCAttrs = Qualifiers::GCNone;
   if (getLangOptions().ObjC1 &&
       getLangOptions().getGCMode() != LangOptions::NonGC) {
     GCAttrs = Ty.getObjCGCAttr();
     // Default behavious under objective-c's gc is for objective-c pointers
     // (or pointers to them) be treated as though they were declared
     // as __strong.
-    if (GCAttrs == QualType::GCNone) {
+    if (GCAttrs == Qualifiers::GCNone) {
       if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType())
-        GCAttrs = QualType::Strong;
+        GCAttrs = Qualifiers::Strong;
       else if (Ty->isPointerType())
         return getObjCGCAttrKind(Ty->getAs<PointerType>()->getPointeeType());
     }
     // Non-pointers have none gc'able attribute regardless of the attribute
     // set on them.
     else if (!Ty->isAnyPointerType() && !Ty->isBlockPointerType())
-      return QualType::GCNone;
+      return Qualifiers::GCNone;
   }
   return GCAttrs;
 }
@@ -3766,11 +3736,38 @@
   if (LHSCan == RHSCan)
     return LHS;
 
-  // If the qualifiers are different, the types aren't compatible
-  // Note that we handle extended qualifiers later, in the
-  // case for ExtQualType.
-  if (LHSCan.getCVRQualifiers() != RHSCan.getCVRQualifiers())
+  // If the qualifiers are different, the types aren't compatible... mostly.
+  Qualifiers LQuals = LHSCan.getQualifiers();
+  Qualifiers RQuals = RHSCan.getQualifiers();
+  if (LQuals != RQuals) {
+    // If any of these qualifiers are different, we have a type
+    // mismatch.
+    if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
+        LQuals.getAddressSpace() != RQuals.getAddressSpace())
+      return QualType();
+
+    // Exactly one GC qualifier difference is allowed: __strong is
+    // okay if the other type has no GC qualifier but is an Objective
+    // C object pointer (i.e. implicitly strong by default).  We fix
+    // this by pretending that the unqualified type was actually
+    // qualified __strong.
+    Qualifiers::GC GC_L = LQuals.getObjCGCAttr();
+    Qualifiers::GC GC_R = RQuals.getObjCGCAttr();
+    assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements");
+
+    if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak)
+      return QualType();
+
+    if (GC_L == Qualifiers::Strong && RHSCan->isObjCObjectPointerType()) {
+      return mergeTypes(LHS, getObjCGCQualType(RHS, Qualifiers::Strong));
+    }
+    if (GC_R == Qualifiers::Strong && LHSCan->isObjCObjectPointerType()) {
+      return mergeTypes(getObjCGCQualType(LHS, Qualifiers::Strong), RHS);
+    }
     return QualType();
+  }
+
+  // Okay, qualifiers are equal.
 
   Type::TypeClass LHSClass = LHSCan->getTypeClass();
   Type::TypeClass RHSClass = RHSCan->getTypeClass();
@@ -3780,59 +3777,6 @@
   if (LHSClass == Type::FunctionProto) LHSClass = Type::FunctionNoProto;
   if (RHSClass == Type::FunctionProto) RHSClass = Type::FunctionNoProto;
 
-  // Strip off objc_gc attributes off the top level so they can be merged.
-  // This is a complete mess, but the attribute itself doesn't make much sense.
-  if (RHSClass == Type::ExtQual) {
-    QualType::GCAttrTypes GCAttr = RHSCan.getObjCGCAttr();
-    if (GCAttr != QualType::GCNone) {
-      QualType::GCAttrTypes GCLHSAttr = LHSCan.getObjCGCAttr();
-      // __weak attribute must appear on both declarations.
-      // __strong attribue is redundant if other decl is an objective-c
-      // object pointer (or decorated with __strong attribute); otherwise
-      // issue error.
-      if ((GCAttr == QualType::Weak && GCLHSAttr != GCAttr) ||
-          (GCAttr == QualType::Strong && GCLHSAttr != GCAttr &&
-           !LHSCan->isObjCObjectPointerType()))
-        return QualType();
-
-      RHS = QualType(cast<ExtQualType>(RHS.getDesugaredType())->getBaseType(),
-                     RHS.getCVRQualifiers());
-      QualType Result = mergeTypes(LHS, RHS);
-      if (!Result.isNull()) {
-        if (Result.getObjCGCAttr() == QualType::GCNone)
-          Result = getObjCGCQualType(Result, GCAttr);
-        else if (Result.getObjCGCAttr() != GCAttr)
-          Result = QualType();
-      }
-      return Result;
-    }
-  }
-  if (LHSClass == Type::ExtQual) {
-    QualType::GCAttrTypes GCAttr = LHSCan.getObjCGCAttr();
-    if (GCAttr != QualType::GCNone) {
-      QualType::GCAttrTypes GCRHSAttr = RHSCan.getObjCGCAttr();
-      // __weak attribute must appear on both declarations. __strong
-      // __strong attribue is redundant if other decl is an objective-c
-      // object pointer (or decorated with __strong attribute); otherwise
-      // issue error.
-      if ((GCAttr == QualType::Weak && GCRHSAttr != GCAttr) ||
-          (GCAttr == QualType::Strong && GCRHSAttr != GCAttr &&
-           !RHSCan->isObjCObjectPointerType()))
-        return QualType();
-
-      LHS = QualType(cast<ExtQualType>(LHS.getDesugaredType())->getBaseType(),
-                     LHS.getCVRQualifiers());
-      QualType Result = mergeTypes(LHS, RHS);
-      if (!Result.isNull()) {
-        if (Result.getObjCGCAttr() == QualType::GCNone)
-          Result = getObjCGCQualType(Result, GCAttr);
-        else if (Result.getObjCGCAttr() != GCAttr)
-          Result = QualType();
-      }
-      return Result;
-    }
-  }
-
   // Same as above for arrays
   if (LHSClass == Type::VariableArray || LHSClass == Type::IncompleteArray)
     LHSClass = Type::ConstantArray;
@@ -3988,34 +3932,6 @@
   case Type::FixedWidthInt:
     // Distinct fixed-width integers are not compatible.
     return QualType();
-  case Type::ExtQual:
-    // FIXME: ExtQual types can be compatible even if they're not
-    // identical!
-    return QualType();
-    // First attempt at an implementation, but I'm not really sure it's
-    // right...
-#if 0
-    ExtQualType* LQual = cast<ExtQualType>(LHSCan);
-    ExtQualType* RQual = cast<ExtQualType>(RHSCan);
-    if (LQual->getAddressSpace() != RQual->getAddressSpace() ||
-        LQual->getObjCGCAttr() != RQual->getObjCGCAttr())
-      return QualType();
-    QualType LHSBase, RHSBase, ResultType, ResCanUnqual;
-    LHSBase = QualType(LQual->getBaseType(), 0);
-    RHSBase = QualType(RQual->getBaseType(), 0);
-    ResultType = mergeTypes(LHSBase, RHSBase);
-    if (ResultType.isNull()) return QualType();
-    ResCanUnqual = getCanonicalType(ResultType).getUnqualifiedType();
-    if (LHSCan.getUnqualifiedType() == ResCanUnqual)
-      return LHS;
-    if (RHSCan.getUnqualifiedType() == ResCanUnqual)
-      return RHS;
-    ResultType = getAddrSpaceQualType(ResultType, LQual->getAddressSpace());
-    ResultType = getObjCGCQualType(ResultType, LQual->getObjCGCAttr());
-    ResultType.setCVRQualifiers(LHSCan.getCVRQualifiers());
-    return ResultType;
-#endif
-
   case Type::TemplateSpecialization:
     assert(false && "Dependent types have no size");
     break;
@@ -4231,7 +4147,7 @@
         break;
       // FIXME: There's no way to have a built-in with an rvalue ref arg.
       case 'C':
-        Type = Type.getQualifiedType(QualType::Const);
+        Type = Type.withConst();
         break;
     }
   }

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Sep 24 14:53:00 2009
@@ -146,7 +146,7 @@
 }
 
 bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
-  return getCopyConstructor(Context, QualType::Const) != 0;
+  return getCopyConstructor(Context, Qualifiers::Const) != 0;
 }
 
 CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context,
@@ -167,8 +167,8 @@
 
     if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context,
                                                           FoundTQs)) {
-      if (((TypeQuals & QualType::Const) == (FoundTQs & QualType::Const)) ||
-          (!(TypeQuals & QualType::Const) && (FoundTQs & QualType::Const)))
+      if (((TypeQuals & Qualifiers::Const) == (FoundTQs & Qualifiers::Const)) ||
+          (!(TypeQuals & Qualifiers::Const) && (FoundTQs & Qualifiers::Const)))
         return cast<CXXConstructorDecl>(*Con);
 
     }
@@ -508,7 +508,8 @@
     ClassTy = TD->getInjectedClassNameType(C);
   else
     ClassTy = C.getTagDeclType(getParent());
-  ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
+  ClassTy = C.getQualifiedType(ClassTy,
+                               Qualifiers::fromCVRMask(getTypeQualifiers()));
   return C.getPointerType(ClassTy);
 }
 
@@ -600,6 +601,8 @@
   if (PointeeType.getUnqualifiedType() != ClassTy)
     return false;
 
+  // FIXME: other qualifiers?
+
   // We have a copy constructor.
   TypeQuals = PointeeType.getCVRQualifiers();
   return true;

Modified: cfe/trunk/lib/AST/DeclarationName.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclarationName.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclarationName.cpp (original)
+++ cfe/trunk/lib/AST/DeclarationName.cpp Thu Sep 24 14:53:00 2009
@@ -309,11 +309,11 @@
   switch (Kind) {
   case DeclarationName::CXXConstructorName:
     EKind = DeclarationNameExtra::CXXConstructor;
-    assert(Ty.getCVRQualifiers() == 0 &&"Constructor type must be unqualified");
+    assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
     break;
   case DeclarationName::CXXDestructorName:
     EKind = DeclarationNameExtra::CXXDestructor;
-    assert(Ty.getCVRQualifiers() == 0 && "Destructor type must be unqualified");
+    assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
     break;
   case DeclarationName::CXXConversionFunctionName:
     EKind = DeclarationNameExtra::CXXConversionFunction;

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Thu Sep 24 14:53:00 2009
@@ -825,7 +825,7 @@
     return LV_NotObjectType;
 
   // Allow qualified void which is an incomplete type other than void (yuck).
-  if (TR->isVoidType() && !Ctx.getCanonicalType(TR).getCVRQualifiers())
+  if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers())
     return LV_IncompleteVoidType;
 
   return LV_Valid;
@@ -1120,7 +1120,7 @@
       // dereferencing to a  pointer is always a gc'able candidate,
       // unless it is __weak.
       return T->isPointerType() &&
-             (Ctx.getObjCGCAttrKind(T) != QualType::Weak);
+             (Ctx.getObjCGCAttrKind(T) != Qualifiers::Weak);
     }
     return false;
   }
@@ -1397,7 +1397,7 @@
     if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
       return NoDiag();
     if (Ctx.getLangOptions().CPlusPlus &&
-        E->getType().getCVRQualifiers() == QualType::Const) {
+        E->getType().getCVRQualifiers() == Qualifiers::Const) {
       // C++ 7.1.5.1p2
       //   A variable of non-volatile const-qualified integral or enumeration
       //   type initialized by an ICE can be used in ICEs.
@@ -1635,7 +1635,7 @@
       // Check that it is a cast to void*.
       if (const PointerType *PT = CE->getType()->getAs<PointerType>()) {
         QualType Pointee = PT->getPointeeType();
-        if (Pointee.getCVRQualifiers() == 0 &&
+        if (!Pointee.hasQualifiers() &&
             Pointee->isVoidType() &&                              // to void*
             CE->getSubExpr()->getType()->isIntegerType())         // from int.
           return CE->getSubExpr()->isNullPointerConstant(Ctx);

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Sep 24 14:53:00 2009
@@ -783,7 +783,7 @@
 
   // In C++, const, non-volatile integers initialized with ICEs are ICEs.
   // In C, they can also be folded, although they are not ICEs.
-  if (E->getType().getCVRQualifiers() == QualType::Const) {
+  if (E->getType().getCVRQualifiers() == Qualifiers::Const) {
     if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) {
       if (APValue *V = D->getEvaluatedValue())
         return Success(V->getInt(), E);

Modified: cfe/trunk/lib/AST/StmtDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtDumper.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtDumper.cpp (original)
+++ cfe/trunk/lib/AST/StmtDumper.cpp Thu Sep 24 14:53:00 2009
@@ -87,13 +87,10 @@
       fprintf(F, "'%s'", T.getAsString().c_str());
 
       if (!T.isNull()) {
-        // If the type is directly a typedef, strip off typedefness to give at
-        // least one level of concreteness.
-        if (TypedefType *TDT = dyn_cast<TypedefType>(T)) {
-          QualType Simplified =
-            TDT->LookThroughTypedefs().getQualifiedType(T.getCVRQualifiers());
+        // If the type is sugared, also dump a (shallow) desugared type.
+        QualType Simplified = T.getDesugaredType();
+        if (Simplified != T)
           fprintf(F, ":'%s'", Simplified.getAsString().c_str());
-        }
       }
     }
     void DumpStmt(const Stmt *Node) {

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Thu Sep 24 14:53:00 2009
@@ -101,12 +101,8 @@
     return ATy->getElementType().getTypePtr();
 
   // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<ArrayType>(CanonicalType)) {
-    // Look through type qualifiers
-    if (ArrayType *AT = dyn_cast<ArrayType>(CanonicalType.getUnqualifiedType()))
-      return AT->getElementType().getTypePtr();
+  if (!isa<ArrayType>(CanonicalType))
     return 0;
-  }
 
   // If this is a typedef for an array type, strip the typedef off without
   // losing all typedef information.
@@ -125,8 +121,8 @@
 /// decide whether it is worth providing a desugared form of the type
 /// or not.
 QualType QualType::getDesugaredType(bool ForDisplay) const {
-  return getTypePtr()->getDesugaredType(ForDisplay)
-     .getWithAdditionalQualifiers(getCVRQualifiers());
+  QualifierCollector Qs;
+  return Qs.apply(Qs.strip(*this)->getDesugaredType(ForDisplay));
 }
 
 /// getDesugaredType - Return the specified type with any "sugar" removed from
@@ -181,8 +177,6 @@
 bool Type::isVoidType() const {
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() == BuiltinType::Void;
-  if (const ExtQualType *AS = dyn_cast<ExtQualType>(CanonicalType))
-    return AS->getBaseType()->isVoidType();
   return false;
 }
 
@@ -190,15 +184,11 @@
   if (isa<FunctionType>(CanonicalType) || isa<ReferenceType>(CanonicalType) ||
       isa<IncompleteArrayType>(CanonicalType) || isVoidType())
     return false;
-  if (const ExtQualType *AS = dyn_cast<ExtQualType>(CanonicalType))
-    return AS->getBaseType()->isObjectType();
   return true;
 }
 
 bool Type::isDerivedType() const {
   switch (CanonicalType->getTypeClass()) {
-  case ExtQual:
-    return cast<ExtQualType>(CanonicalType)->getBaseType()->isDerivedType();
   case Pointer:
   case VariableArray:
   case ConstantArray:
@@ -241,39 +231,19 @@
 bool Type::isComplexType() const {
   if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
     return CT->getElementType()->isFloatingType();
-  if (const ExtQualType *AS = dyn_cast<ExtQualType>(CanonicalType))
-    return AS->getBaseType()->isComplexType();
   return false;
 }
 
 bool Type::isComplexIntegerType() const {
   // Check for GCC complex integer extension.
-  if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
-    return CT->getElementType()->isIntegerType();
-  if (const ExtQualType *AS = dyn_cast<ExtQualType>(CanonicalType))
-    return AS->getBaseType()->isComplexIntegerType();
-  return false;
+  return getAsComplexIntegerType();
 }
 
 const ComplexType *Type::getAsComplexIntegerType() const {
-  // Are we directly a complex type?
-  if (const ComplexType *CTy = dyn_cast<ComplexType>(this)) {
-    if (CTy->getElementType()->isIntegerType())
-      return CTy;
-    return 0;
-  }
-
-  // If the canonical form of this type isn't what we want, reject it.
-  if (!isa<ComplexType>(CanonicalType)) {
-    // Look through type qualifiers (e.g. ExtQualType's).
-    if (isa<ComplexType>(CanonicalType.getUnqualifiedType()))
-      return CanonicalType.getUnqualifiedType()->getAsComplexIntegerType();
-    return 0;
-  }
-
-  // If this is a typedef for a complex type, strip the typedef off without
-  // losing all typedef information.
-  return cast<ComplexType>(getDesugaredType());
+  if (const ComplexType *Complex = getAs<ComplexType>())
+    if (Complex->getElementType()->isIntegerType())
+      return Complex;
+  return 0;
 }
 
 QualType Type::getPointeeType() const {
@@ -335,9 +305,6 @@
     // losing all typedef information.
     return cast<RecordType>(getDesugaredType());
   }
-  // Look through type qualifiers
-  if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
-    return CanonicalType.getUnqualifiedType()->getAsStructureType();
   return 0;
 }
 
@@ -358,9 +325,6 @@
     return cast<RecordType>(getDesugaredType());
   }
 
-  // Look through type qualifiers
-  if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
-    return CanonicalType.getUnqualifiedType()->getAsUnionType();
   return 0;
 }
 
@@ -416,8 +380,6 @@
     return true;
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isIntegerType();
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isIntegerType();
   return false;
 }
 
@@ -431,24 +393,18 @@
                     // FIXME: In C++, enum types are never integral.
   if (isa<FixedWidthIntType>(CanonicalType))
     return true;
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isIntegralType();
   return false;
 }
 
 bool Type::isEnumeralType() const {
   if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
     return TT->getDecl()->isEnum();
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isEnumeralType();
   return false;
 }
 
 bool Type::isBooleanType() const {
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() == BuiltinType::Bool;
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isBooleanType();
   return false;
 }
 
@@ -458,16 +414,12 @@
            BT->getKind() == BuiltinType::UChar ||
            BT->getKind() == BuiltinType::Char_S ||
            BT->getKind() == BuiltinType::SChar;
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isCharType();
   return false;
 }
 
 bool Type::isWideCharType() const {
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() == BuiltinType::WChar;
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isWideCharType();
   return false;
 }
 
@@ -490,8 +442,6 @@
 
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isSignedIntegerType();
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isSignedIntegerType();
   return false;
 }
 
@@ -514,8 +464,6 @@
 
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isUnsignedIntegerType();
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isUnsignedIntegerType();
   return false;
 }
 
@@ -527,8 +475,6 @@
     return CT->getElementType()->isFloatingType();
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isFloatingType();
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isFloatingType();
   return false;
 }
 
@@ -538,8 +484,6 @@
            BT->getKind() <= BuiltinType::LongDouble;
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isRealFloatingType();
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isRealFloatingType();
   return false;
 }
 
@@ -553,8 +497,6 @@
     return true;
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isRealType();
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isRealType();
   return false;
 }
 
@@ -568,8 +510,6 @@
     return ET->getDecl()->isDefinition();
   if (isa<FixedWidthIntType>(CanonicalType))
     return true;
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isArithmeticType();
   return isa<ComplexType>(CanonicalType) || isa<VectorType>(CanonicalType);
 }
 
@@ -583,8 +523,6 @@
       return true;
     return false;
   }
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isScalarType();
   if (isa<FixedWidthIntType>(CanonicalType))
     return true;
   return isa<PointerType>(CanonicalType) ||
@@ -611,8 +549,6 @@
     return true;
   }
 
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isAggregateType();
   return isa<ArrayType>(CanonicalType);
 }
 
@@ -620,8 +556,6 @@
 /// according to the rules of C99 6.7.5p3.  It is not legal to call this on
 /// incomplete types or dependent types.
 bool Type::isConstantSizeType() const {
-  if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
-    return EXTQT->getBaseType()->isConstantSizeType();
   assert(!isIncompleteType() && "This doesn't make sense for incomplete types");
   assert(!isDependentType() && "This doesn't make sense for dependent types");
   // The VAT must have a size, as it is known to be complete.
@@ -634,8 +568,6 @@
 bool Type::isIncompleteType() const {
   switch (CanonicalType->getTypeClass()) {
   default: return false;
-  case ExtQual:
-    return cast<ExtQualType>(CanonicalType)->getBaseType()->isIncompleteType();
   case Builtin:
     // Void is the only incomplete builtin type.  Per C99 6.2.5p19, it can never
     // be completed.
@@ -664,8 +596,6 @@
   switch (CanonicalType->getTypeClass()) {
     // Everything not explicitly mentioned is not POD.
   default: return false;
-  case ExtQual:
-    return cast<ExtQualType>(CanonicalType)->getBaseType()->isPODType();
   case VariableArray:
   case ConstantArray:
     // IncompleteArray is caught by isIncompleteType() above.
@@ -827,21 +757,16 @@
     return FirstType;
 
   // Otherwise, do the fully general loop.
-  unsigned TypeQuals = 0;
-  const TypedefType *TDT = this;
-  while (1) {
-    QualType CurType = TDT->getDecl()->getUnderlyingType();
+  QualifierCollector Qs;
 
+  QualType CurType;
+  const TypedefType *TDT = this;
+  do {
+    CurType = TDT->getDecl()->getUnderlyingType();
+    TDT = dyn_cast<TypedefType>(Qs.strip(CurType));
+  } while (TDT);
 
-    /// FIXME:
-    /// FIXME: This is incorrect for ExtQuals!
-    /// FIXME:
-    TypeQuals |= CurType.getCVRQualifiers();
-
-    TDT = dyn_cast<TypedefType>(CurType);
-    if (TDT == 0)
-      return QualType(CurType.getTypePtr(), TypeQuals);
-  }
+  return Qs.apply(CurType);
 }
 
 TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
@@ -961,27 +886,20 @@
     Args[Idx].Profile(ID, Context);
 }
 
-const Type *QualifierSet::strip(const Type* T) {
-  QualType DT = T->getDesugaredType();
-  addCVR(DT.getCVRQualifiers());
-
-  if (const ExtQualType* EQT = dyn_cast<ExtQualType>(DT)) {
-    if (EQT->getAddressSpace())
-      addAddressSpace(EQT->getAddressSpace());
-    if (EQT->getObjCGCAttr())
-      addObjCGCAttrType(EQT->getObjCGCAttr());
-    return EQT->getBaseType();
-  } else {
-    // Use the sugared type unless desugaring found extra qualifiers.
-    return (DT.getCVRQualifiers() ? DT.getTypePtr() : T);
-  }
+QualType QualifierCollector::apply(QualType QT) const {
+  if (!hasNonFastQualifiers())
+    return QT.withFastQualifiers(getFastQualifiers());
+
+  assert(Context && "extended qualifiers but no context!");
+  return Context->getQualifiedType(QT, *this);
 }
 
-QualType QualifierSet::apply(QualType QT, ASTContext& C) {
-  QT = QT.getWithAdditionalQualifiers(getCVRMask());
-  if (hasObjCGCAttrType()) QT = C.getObjCGCQualType(QT, getObjCGCAttrType());
-  if (hasAddressSpace()) QT = C.getAddrSpaceQualType(QT, getAddressSpace());
-  return QT;
+QualType QualifierCollector::apply(const Type *T) const {
+  if (!hasNonFastQualifiers())
+    return QualType(T, getFastQualifiers());
+
+  assert(Context && "extended qualifiers but no context!");
+  return Context->getQualifiedType(T, *this);
 }
 
 
@@ -1012,14 +930,46 @@
 
 
 static void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
-  // Note: funkiness to ensure we get a space only between quals.
-  bool NonePrinted = true;
-  if (TypeQuals & QualType::Const)
-    S += "const", NonePrinted = false;
-  if (TypeQuals & QualType::Volatile)
-    S += (NonePrinted+" volatile"), NonePrinted = false;
-  if (TypeQuals & QualType::Restrict)
-    S += (NonePrinted+" restrict"), NonePrinted = false;
+  if (TypeQuals & Qualifiers::Const) {
+    if (!S.empty()) S += ' ';
+    S += "const";
+  }
+  if (TypeQuals & Qualifiers::Volatile) {
+    if (!S.empty()) S += ' ';
+    S += "volatile";
+  }
+  if (TypeQuals & Qualifiers::Restrict) {
+    if (!S.empty()) S += ' ';
+    S += "restrict";
+  }
+}
+
+std::string Qualifiers::getAsString() const {
+  LangOptions LO;
+  return getAsString(PrintingPolicy(LO));
+}
+
+// Appends qualifiers to the given string, separated by spaces.  Will
+// prefix a space if the string is non-empty.  Will not append a final
+// space.
+void Qualifiers::getAsStringInternal(std::string &S,
+                                     const PrintingPolicy&) const {
+  AppendTypeQualList(S, getCVRQualifiers());
+  if (unsigned AddressSpace = getAddressSpace()) {
+    if (!S.empty()) S += ' ';
+    S += "__attribute__((address_space(";
+    S += llvm::utostr_32(AddressSpace);
+    S += ")))";
+  }
+  if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
+    if (!S.empty()) S += ' ';
+    S += "__attribute__((objc_gc(";
+    if (GCAttrType == Qualifiers::Weak)
+      S += "weak";
+    else
+      S += "strong";
+    S += ")))";
+  }
 }
 
 std::string QualType::getAsString() const {
@@ -1041,13 +991,16 @@
     return;
 
   // Print qualifiers as appropriate.
-  if (unsigned Tq = getCVRQualifiers()) {
+  Qualifiers Quals = getQualifiers();
+  if (!Quals.empty()) {
     std::string TQS;
-    AppendTypeQualList(TQS, Tq);
-    if (!S.empty())
-      S = TQS + ' ' + S;
-    else
-      S = TQS;
+    Quals.getAsStringInternal(TQS, Policy);
+
+    if (!S.empty()) {
+      TQS += ' ';
+      TQS += S;
+    }
+    std::swap(S, TQS);
   }
 
   getTypePtr()->getAsStringInternal(S, Policy);
@@ -1084,25 +1037,6 @@
   S = "_Complex " + S;
 }
 
-void ExtQualType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
-  bool NeedsSpace = false;
-  if (AddressSpace) {
-    S = "__attribute__((address_space("+llvm::utostr_32(AddressSpace)+")))" + S;
-    NeedsSpace = true;
-  }
-  if (GCAttrType != QualType::GCNone) {
-    if (NeedsSpace)
-      S += ' ';
-    S += "__attribute__((objc_gc(";
-    if (GCAttrType == QualType::Weak)
-      S += "weak";
-    else
-      S += "strong";
-    S += ")))";
-  }
-  BaseType->getAsStringInternal(S, Policy);
-}
-
 void PointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
   S = '*' + S;
 
@@ -1195,8 +1129,8 @@
 void VariableArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
   S += '[';
 
-  if (getIndexTypeQualifier()) {
-    AppendTypeQualList(S, getIndexTypeQualifier());
+  if (getIndexTypeQualifiers().hasQualifiers()) {
+    AppendTypeQualList(S, getIndexTypeCVRQualifiers());
     S += ' ';
   }
 
@@ -1219,8 +1153,8 @@
 void DependentSizedArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
   S += '[';
 
-  if (getIndexTypeQualifier()) {
-    AppendTypeQualList(S, getIndexTypeQualifier());
+  if (getIndexTypeQualifiers().hasQualifiers()) {
+    AppendTypeQualList(S, getIndexTypeCVRQualifiers());
     S += ' ';
   }
 
@@ -1536,6 +1470,9 @@
     }
     ObjCQIString += '>';
   }
+
+  PointeeType.getQualifiers().getAsStringInternal(ObjCQIString, Policy);
+
   if (!isObjCIdType() && !isObjCQualifiedIdType())
     ObjCQIString += " *"; // Don't forget the implicit pointer.
   else if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Thu Sep 24 14:53:00 2009
@@ -1686,8 +1686,8 @@
         // FIXME: This is really ugly; should be refactored somehow
         unsigned idx = CGM.getTypes().getLLVMFieldNo(Field);
         llvm::Value *V = Builder.CreateStructGEP(LoadOfThis, idx, "tmp");
-        LHS = LValue::MakeAddr(V, FieldType.getCVRQualifiers(),
-                               QualType::GCNone, FieldType.getAddressSpace());
+        assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs");
+        LHS = LValue::MakeAddr(V, MakeQualifiers(FieldType));
       } else {
         LHS = EmitLValueForField(LoadOfThis, Field, false, 0);
       }

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Thu Sep 24 14:53:00 2009
@@ -629,7 +629,7 @@
                                            (Name + ".addr").c_str());
       // FIXME: What are the right qualifiers here?
       llvm::Function::arg_iterator End =
-        ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp,0), AI);
+        ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI);
       EmitParmDecl(*Arg, Temp);
 
       // Name the arguments used in expansion and increment AI.

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Thu Sep 24 14:53:00 2009
@@ -788,7 +788,6 @@
   case Type::RValueReference:
   case Type::Vector:
   case Type::ExtVector:
-  case Type::ExtQual:
   case Type::FixedWidthInt:
   case Type::MemberPointer:
   case Type::TemplateSpecialization:

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Sep 24 14:53:00 2009
@@ -166,9 +166,7 @@
   ErrorUnsupported(E, Name);
   llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType()));
   return LValue::MakeAddr(llvm::UndefValue::get(Ty),
-                          E->getType().getCVRQualifiers(),
-                          getContext().getObjCGCAttrKind(E->getType()),
-                          E->getType().getAddressSpace());
+                          MakeQualifiers(E->getType()));
 }
 
 /// EmitLValue - Emit code to compute a designator that specifies the location
@@ -746,17 +744,16 @@
       llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
       if (VD->getType()->isReferenceType())
         V = Builder.CreateLoad(V, "tmp");
-      LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
-                            getContext().getObjCGCAttrKind(E->getType()),
-                            E->getType().getAddressSpace());
+      LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
     } else {
       llvm::Value *V = LocalDeclMap[VD];
       assert(V && "DeclRefExpr not entered in LocalDeclMap?");
+
+      Qualifiers Quals = MakeQualifiers(E->getType());
       // local variables do not get their gc attribute set.
-      QualType::GCAttrTypes attr = QualType::GCNone;
       // local static?
-      if (!NonGCable)
-        attr = getContext().getObjCGCAttrKind(E->getType());
+      if (NonGCable) Quals.removeObjCGCAttr();
+
       if (VD->hasAttr<BlocksAttr>()) {
         V = Builder.CreateStructGEP(V, 1, "forwarding");
         V = Builder.CreateLoad(V, false);
@@ -765,8 +762,7 @@
       }
       if (VD->getType()->isReferenceType())
         V = Builder.CreateLoad(V, "tmp");
-      LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(), attr,
-                            E->getType().getAddressSpace());
+      LV = LValue::MakeAddr(V, Quals);
     }
     LValue::SetObjCNonGC(LV, NonGCable);
     setObjCGCLValueClass(getContext(), E, LV);
@@ -775,9 +771,7 @@
     llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
     if (VD->getType()->isReferenceType())
       V = Builder.CreateLoad(V, "tmp");
-    LValue LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
-                                 getContext().getObjCGCAttrKind(E->getType()),
-                                 E->getType().getAddressSpace());
+    LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
     setObjCGCLValueClass(getContext(), E, LV);
     return LV;
   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
@@ -794,16 +788,12 @@
         V = Builder.CreateBitCast(V, ConvertType(NoProtoType), "tmp");
       }
     }
-    return LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
-                            getContext().getObjCGCAttrKind(E->getType()),
-                            E->getType().getAddressSpace());
+    return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
   } else if (const ImplicitParamDecl *IPD =
       dyn_cast<ImplicitParamDecl>(E->getDecl())) {
     llvm::Value *V = LocalDeclMap[IPD];
     assert(V && "BlockVarDecl not entered in LocalDeclMap?");
-    return LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
-                            getContext().getObjCGCAttrKind(E->getType()),
-                            E->getType().getAddressSpace());
+    return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
   }
   assert(0 && "Unimp declref");
   //an invalid LValue, but the assert will
@@ -812,10 +802,7 @@
 }
 
 LValue CodeGenFunction::EmitBlockDeclRefLValue(const BlockDeclRefExpr *E) {
-  return LValue::MakeAddr(GetAddrOfBlockDecl(E),
-                          E->getType().getCVRQualifiers(),
-                          getContext().getObjCGCAttrKind(E->getType()),
-                          E->getType().getAddressSpace());
+  return LValue::MakeAddr(GetAddrOfBlockDecl(E), MakeQualifiers(E->getType()));
 }
 
 LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
@@ -831,10 +818,10 @@
       QualType T = E->getSubExpr()->getType()->getPointeeType();
       assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
 
-      LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()),
-                                   T.getCVRQualifiers(),
-                                   getContext().getObjCGCAttrKind(T),
-                                   ExprTy.getAddressSpace());
+      Qualifiers Quals = MakeQualifiers(T);
+      Quals.setAddressSpace(ExprTy.getAddressSpace());
+
+      LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()), Quals);
      // We should not generate __weak write barrier on indirect reference
      // of a pointer to object; as in void foo (__weak id *param); *param = 0;
      // But, we continue to generate __strong write barrier on indirect write
@@ -851,18 +838,18 @@
     unsigned Idx = E->getOpcode() == UnaryOperator::Imag;
     return LValue::MakeAddr(Builder.CreateStructGEP(LV.getAddress(),
                                                     Idx, "idx"),
-                            ExprTy.getCVRQualifiers(),
-                            QualType::GCNone,
-                            ExprTy.getAddressSpace());
+                            MakeQualifiers(ExprTy));
   }
 }
 
 LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
-  return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromLiteral(E), 0);
+  return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromLiteral(E),
+                          Qualifiers());
 }
 
 LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) {
-  return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromObjCEncode(E), 0);
+  return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromObjCEncode(E),
+                          Qualifiers());
 }
 
 
@@ -894,7 +881,7 @@
 
   llvm::Constant *C =
     CGM.GetAddrOfConstantCString(FunctionName, GlobalVarName.c_str());
-  return LValue::MakeAddr(C, 0);
+  return LValue::MakeAddr(C, Qualifiers());
 }
 
 LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
@@ -923,7 +910,7 @@
     Idx = Builder.CreateIntCast(Idx,
                           llvm::Type::getInt32Ty(VMContext), IdxSigned, "vidx");
     return LValue::MakeVectorElt(LHS.getAddress(), Idx,
-      E->getBase()->getType().getCVRQualifiers());
+                                 E->getBase()->getType().getCVRQualifiers());
   }
 
   // The base must be a pointer, which is not an aggregate.  Emit it.
@@ -973,10 +960,10 @@
   assert(!T.isNull() &&
          "CodeGenFunction::EmitArraySubscriptExpr(): Illegal base type");
 
-  LValue LV = LValue::MakeAddr(Address,
-                               T.getCVRQualifiers(),
-                               getContext().getObjCGCAttrKind(T),
-                               E->getBase()->getType().getAddressSpace());
+  Qualifiers Quals = MakeQualifiers(T);
+  Quals.setAddressSpace(E->getBase()->getType().getAddressSpace());
+
+  LValue LV = LValue::MakeAddr(Address, Quals);
   if (getContext().getLangOptions().ObjC1 &&
       getContext().getLangOptions().getGCMode() != LangOptions::NonGC) {
     LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext()));
@@ -1009,9 +996,9 @@
   } else {
     const PointerType *PT = E->getBase()->getType()->getAs<PointerType>();
     llvm::Value *Ptr = EmitScalarExpr(E->getBase());
-    Base = LValue::MakeAddr(Ptr, PT->getPointeeType().getCVRQualifiers(),
-                            QualType::GCNone,
-                            PT->getPointeeType().getAddressSpace());
+    Qualifiers Quals = MakeQualifiers(PT->getPointeeType());
+    Quals.removeObjCGCAttr();
+    Base = LValue::MakeAddr(Ptr, Quals);
   }
 
   // Encode the element access list into a vector of unsigned indices.
@@ -1021,7 +1008,7 @@
   if (Base.isSimple()) {
     llvm::Constant *CV = GenerateConstantVector(VMContext, Indices);
     return LValue::MakeExtVectorElt(Base.getAddress(), CV,
-                                    Base.getQualifiers());
+                                    Base.getVRQualifiers());
   }
   assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!");
 
@@ -1037,7 +1024,7 @@
   }
   llvm::Constant *CV = llvm::ConstantVector::get(&CElts[0], CElts.size());
   return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), CV,
-                                  Base.getQualifiers());
+                                  Base.getVRQualifiers());
 }
 
 LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
@@ -1045,7 +1032,7 @@
   bool isNonGC = false;
   Expr *BaseExpr = E->getBase();
   llvm::Value *BaseValue = NULL;
-  unsigned CVRQualifiers=0;
+  Qualifiers BaseQuals;
 
   // If this is s.x, emit s as an lvalue.  If it is s->x, emit s as a scalar.
   if (E->isArrow()) {
@@ -1054,7 +1041,7 @@
       BaseExpr->getType()->getAs<PointerType>();
     if (PTy->getPointeeType()->isUnionType())
       isUnion = true;
-    CVRQualifiers = PTy->getPointeeType().getCVRQualifiers();
+    BaseQuals = PTy->getPointeeType().getQualifiers();
   } else if (isa<ObjCPropertyRefExpr>(BaseExpr->IgnoreParens()) ||
              isa<ObjCImplicitSetterGetterRefExpr>(
                BaseExpr->IgnoreParens())) {
@@ -1062,7 +1049,7 @@
     BaseValue = RV.getAggregateAddr();
     if (BaseExpr->getType()->isUnionType())
       isUnion = true;
-    CVRQualifiers = BaseExpr->getType().getCVRQualifiers();
+    BaseQuals = BaseExpr->getType().getQualifiers();
   } else {
     LValue BaseLV = EmitLValue(BaseExpr);
     if (BaseLV.isNonGC())
@@ -1072,14 +1059,14 @@
     QualType BaseTy = BaseExpr->getType();
     if (BaseTy->isUnionType())
       isUnion = true;
-    CVRQualifiers = BaseTy.getCVRQualifiers();
+    BaseQuals = BaseTy.getQualifiers();
   }
 
   FieldDecl *Field = dyn_cast<FieldDecl>(E->getMemberDecl());
   // FIXME: Handle non-field member expressions
   assert(Field && "No code generation for non-field member references");
   LValue MemExpLV = EmitLValueForField(BaseValue, Field, isUnion,
-                                       CVRQualifiers);
+                                       BaseQuals.getCVRQualifiers());
   LValue::SetObjCNonGC(MemExpLV, isNonGC);
   setObjCGCLValueClass(getContext(), E, MemExpLV);
   return MemExpLV;
@@ -1133,17 +1120,14 @@
   }
   if (Field->getType()->isReferenceType())
     V = Builder.CreateLoad(V, "tmp");
-  QualType::GCAttrTypes attr = getContext().getObjCGCAttrKind(Field->getType());
+
+  Qualifiers Quals = MakeQualifiers(Field->getType());
+  Quals.addCVRQualifiers(CVRQualifiers);
   // __weak attribute on a field is ignored.
-  if (attr == QualType::Weak)
-    attr = QualType::GCNone;
+  if (Quals.getObjCGCAttr() == Qualifiers::Weak)
+    Quals.removeObjCGCAttr();
   
-  LValue LV =
-    LValue::MakeAddr(V,
-                     Field->getType().getCVRQualifiers()|CVRQualifiers,
-                     attr,
-                     Field->getType().getAddressSpace());
-  return LV;
+  return LValue::MakeAddr(V, Quals);
 }
 
 LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){
@@ -1151,9 +1135,7 @@
   llvm::Value *DeclPtr = CreateTempAlloca(LTy, ".compoundliteral");
 
   const Expr* InitExpr = E->getInitializer();
-  LValue Result = LValue::MakeAddr(DeclPtr, E->getType().getCVRQualifiers(),
-                                   QualType::GCNone,
-                                   E->getType().getAddressSpace());
+  LValue Result = LValue::MakeAddr(DeclPtr, MakeQualifiers(E->getType()));
 
   if (E->getType()->isComplexType()) {
     EmitComplexExprIntoAddr(InitExpr, DeclPtr, false);
@@ -1199,9 +1181,7 @@
     EmitBlock(ContBlock);
     
     Temp = Builder.CreateLoad(Temp, "lv");
-    return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
-                            getContext().getObjCGCAttrKind(E->getType()),
-                            E->getType().getAddressSpace());
+    return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
   }
   
   // ?: here should be an aggregate.
@@ -1212,9 +1192,7 @@
   llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
   EmitAggExpr(E, Temp, false);
 
-  return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
-                          getContext().getObjCGCAttrKind(E->getType()),
-                          E->getType().getAddressSpace());
+  return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
 }
 
 /// EmitCastLValue - Casts are never lvalues.  If a cast is needed by the code
@@ -1254,18 +1232,14 @@
       GetAddressCXXOfBaseClass(LV.getAddress(), DerivedClassDecl, 
                                BaseClassDecl, /*NullCheckValue=*/false);
     
-    return LValue::MakeAddr(Base, E->getType().getCVRQualifiers(),
-                            getContext().getObjCGCAttrKind(E->getType()),
-                            E->getType().getAddressSpace());
+    return LValue::MakeAddr(Base, MakeQualifiers(E->getType()));
   }
 
   case CastExpr::CK_ToUnion: {
     llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
     EmitAnyExpr(E->getSubExpr(), Temp, false);
 
-    return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
-                            getContext().getObjCGCAttrKind(E->getType()),
-                            E->getType().getAddressSpace());
+    return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
     }
   }
 }
@@ -1327,9 +1301,7 @@
   llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
   EmitAggExpr(E, Temp, false);
   // FIXME: Are these qualifiers correct?
-  return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
-                          getContext().getObjCGCAttrKind(E->getType()),
-                          E->getType().getAddressSpace());
+  return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
 }
 
 LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
@@ -1340,23 +1312,17 @@
            "Can't have a scalar return unless the return type is a "
            "reference type!");
 
-    return LValue::MakeAddr(RV.getScalarVal(), E->getType().getCVRQualifiers(),
-                            getContext().getObjCGCAttrKind(E->getType()),
-                            E->getType().getAddressSpace());
+    return LValue::MakeAddr(RV.getScalarVal(), MakeQualifiers(E->getType()));
   }
 
-  return LValue::MakeAddr(RV.getAggregateAddr(),
-                          E->getType().getCVRQualifiers(),
-                          getContext().getObjCGCAttrKind(E->getType()),
-                          E->getType().getAddressSpace());
+  return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType()));
 }
 
 LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) {
   // FIXME: This shouldn't require another copy.
   llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
   EmitAggExpr(E, Temp, false);
-  return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
-                          QualType::GCNone, E->getType().getAddressSpace());
+  return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
 }
 
 LValue
@@ -1368,8 +1334,7 @@
 LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
   llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(E->getType()), "tmp");
   EmitCXXConstructExpr(Temp, E);
-  return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
-                          QualType::GCNone, E->getType().getAddressSpace());
+  return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
 }
 
 LValue
@@ -1385,10 +1350,7 @@
   // Can only get l-value for message expression returning aggregate type
   RValue RV = EmitObjCMessageExpr(E);
   // FIXME: can this be volatile?
-  return LValue::MakeAddr(RV.getAggregateAddr(),
-                          E->getType().getCVRQualifiers(),
-                          getContext().getObjCGCAttrKind(E->getType()),
-                          E->getType().getAddressSpace());
+  return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType()));
 }
 
 llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface,
@@ -1408,22 +1370,23 @@
   // FIXME: A lot of the code below could be shared with EmitMemberExpr.
   llvm::Value *BaseValue = 0;
   const Expr *BaseExpr = E->getBase();
-  unsigned CVRQualifiers = 0;
+  Qualifiers BaseQuals;
   QualType ObjectTy;
   if (E->isArrow()) {
     BaseValue = EmitScalarExpr(BaseExpr);
     ObjectTy = BaseExpr->getType()->getPointeeType();
-    CVRQualifiers = ObjectTy.getCVRQualifiers();
+    BaseQuals = ObjectTy.getQualifiers();
   } else {
     LValue BaseLV = EmitLValue(BaseExpr);
     // FIXME: this isn't right for bitfields.
     BaseValue = BaseLV.getAddress();
     ObjectTy = BaseExpr->getType();
-    CVRQualifiers = ObjectTy.getCVRQualifiers();
+    BaseQuals = ObjectTy.getQualifiers();
   }
 
   LValue LV = 
-    EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(), CVRQualifiers);
+    EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(),
+                      BaseQuals.getCVRQualifiers());
   setObjCGCLValueClass(getContext(), E, LV);
   return LV;
 }
@@ -1453,10 +1416,7 @@
   // Can only get l-value for message expression returning aggregate type
   RValue RV = EmitAnyExprToTemp(E);
   // FIXME: can this be volatile?
-  return LValue::MakeAddr(RV.getAggregateAddr(),
-                          E->getType().getCVRQualifiers(),
-                          getContext().getObjCGCAttrKind(E->getType()),
-                          E->getType().getAddressSpace());
+  return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType()));
 }
 
 

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu Sep 24 14:53:00 2009
@@ -181,7 +181,7 @@
     llvm::Value *CastPtr = Builder.CreateBitCast(DestPtr,
                                                  CGF.ConvertType(PtrTy));
     EmitInitializationToLValue(E->getSubExpr(),
-                               LValue::MakeAddr(CastPtr, 0));
+                               LValue::MakeAddr(CastPtr, Qualifiers()));
     return;
   }
 
@@ -316,7 +316,7 @@
     return;
   }
 
-  EmitFinalDestCopy(VE, LValue::MakeAddr(ArgPtr, 0));
+  EmitFinalDestCopy(VE, LValue::MakeAddr(ArgPtr, Qualifiers()));
 }
 
 void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
@@ -429,15 +429,16 @@
     QualType ElementType = CGF.getContext().getCanonicalType(E->getType());
     ElementType = CGF.getContext().getAsArrayType(ElementType)->getElementType();
 
-    unsigned CVRqualifier = ElementType.getCVRQualifiers();
+    // FIXME: were we intentionally ignoring address spaces and GC attributes?
+    Qualifiers Quals = CGF.MakeQualifiers(ElementType);
 
     for (uint64_t i = 0; i != NumArrayElements; ++i) {
       llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array");
       if (i < NumInitElements)
         EmitInitializationToLValue(E->getInit(i),
-                                   LValue::MakeAddr(NextVal, CVRqualifier));
+                                   LValue::MakeAddr(NextVal, Quals));
       else
-        EmitNullInitializationToLValue(LValue::MakeAddr(NextVal, CVRqualifier),
+        EmitNullInitializationToLValue(LValue::MakeAddr(NextVal, Quals),
                                        ElementType);
     }
     return;

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Thu Sep 24 14:53:00 2009
@@ -791,8 +791,7 @@
         NextVal = Builder.CreateGEP(InVal, Inc, "add.ptr");
         llvm::Value *lhs = LV.getAddress();
         lhs = Builder.CreateBitCast(lhs, llvm::PointerType::getUnqual(i8Ty));
-        LV = LValue::MakeAddr(lhs, ValTy.getCVRQualifiers(),
-                              CGF.getContext().getObjCGCAttrKind(ValTy));
+        LV = LValue::MakeAddr(lhs, CGF.MakeQualifiers(ValTy));
       } else
         NextVal = Builder.CreateInBoundsGEP(InVal, Inc, "ptrincdec");
     } else {

Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Thu Sep 24 14:53:00 2009
@@ -112,6 +112,9 @@
   V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
   V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
 
+  Qualifiers Quals = CGF.MakeQualifiers(IvarTy);
+  Quals.addCVRQualifiers(CVRQualifiers);
+
   if (Ivar->isBitField()) {
     // We need to compute the bit offset for the bit-field, the offset
     // is to the byte. Note, there is a subtle invariant here: we can
@@ -124,11 +127,11 @@
       Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue();
     return LValue::MakeBitfield(V, BitOffset, BitFieldSize,
                                 IvarTy->isSignedIntegerType(),
-                                IvarTy.getCVRQualifiers()|CVRQualifiers);
+                                Quals.getCVRQualifiers());
   }
 
-  LValue LV = LValue::MakeAddr(V, IvarTy.getCVRQualifiers()|CVRQualifiers,
-                               CGF.CGM.getContext().getObjCGCAttrKind(IvarTy));
+  
+  LValue LV = LValue::MakeAddr(V, Quals);
   return LV;
 }
 
@@ -2992,21 +2995,20 @@
   return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
 }
 
-static QualType::GCAttrTypes GetGCAttrTypeForType(ASTContext &Ctx,
-                                                  QualType FQT) {
+static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
   if (FQT.isObjCGCStrong())
-    return QualType::Strong;
+    return Qualifiers::Strong;
 
   if (FQT.isObjCGCWeak())
-    return QualType::Weak;
+    return Qualifiers::Weak;
 
   if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
-    return QualType::Strong;
+    return Qualifiers::Strong;
 
   if (const PointerType *PT = FQT->getAs<PointerType>())
     return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
 
-  return QualType::GCNone;
+  return Qualifiers::GCNone;
 }
 
 void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
@@ -3123,11 +3125,11 @@
     }
     // At this point, we are done with Record/Union and array there of.
     // For other arrays we are down to its element type.
-    QualType::GCAttrTypes GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
+    Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
 
     unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
-    if ((ForStrongLayout && GCAttr == QualType::Strong)
-        || (!ForStrongLayout && GCAttr == QualType::Weak)) {
+    if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
+        || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
       if (IsUnion) {
         uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
         if (UnionIvarSize > MaxUnionIvarSize) {
@@ -3140,8 +3142,8 @@
                                     FieldSize / WordSizeInBits));
       }
     } else if ((ForStrongLayout &&
-                (GCAttr == QualType::GCNone || GCAttr == QualType::Weak))
-               || (!ForStrongLayout && GCAttr != QualType::Weak)) {
+                (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
+               || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
       if (IsUnion) {
         // FIXME: Why the asymmetry? We divide by word size in bits on other
         // side.

Modified: cfe/trunk/lib/CodeGen/CGValue.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGValue.h?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGValue.h (original)
+++ cfe/trunk/lib/CodeGen/CGValue.h Thu Sep 24 14:53:00 2009
@@ -118,12 +118,6 @@
                   // use getKVCRefExpr
   } LVType;
 
-  enum ObjCType {
-    None = 0,     // object with no gc attribute.
-    Weak,         // __weak object expression
-    Strong        // __strong object expression
-  };
-
   llvm::Value *V;
 
   union {
@@ -146,9 +140,8 @@
     const ObjCImplicitSetterGetterRefExpr *KVCRefExpr;
   };
 
-  bool Volatile:1;
-  // FIXME: set but never used, what effect should it have?
-  bool Restrict:1;
+  // 'const' is unused here
+  Qualifiers Quals;
 
   // objective-c's ivar
   bool Ivar:1;
@@ -163,20 +156,13 @@
   // Lvalue is a global reference of an objective-c object
   bool GlobalObjCRef : 1;
 
-  // objective-c's gc attributes
-  unsigned ObjCType : 2;
-
-  // address space
-  unsigned AddressSpace;
-
 private:
-  static void SetQualifiers(unsigned Qualifiers, LValue& R) {
-    R.Volatile = (Qualifiers&QualType::Volatile)!=0;
-    R.Restrict = (Qualifiers&QualType::Restrict)!=0;
+  void SetQualifiers(Qualifiers Quals) {
+    this->Quals = Quals;
+    
     // FIXME: Convenient place to set objc flags to 0. This should really be
     // done in a user-defined constructor instead.
-    R.ObjCType = None;
-    R.Ivar = R.ObjIsArray = R.NonGC = R.GlobalObjCRef = false;
+    this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
   }
 
 public:
@@ -187,21 +173,20 @@
   bool isPropertyRef() const { return LVType == PropertyRef; }
   bool isKVCRef() const { return LVType == KVCRef; }
 
-  bool isVolatileQualified() const { return Volatile; }
-  bool isRestrictQualified() const { return Restrict; }
-  unsigned getQualifiers() const {
-    return (Volatile ? QualType::Volatile : 0) |
-           (Restrict ? QualType::Restrict : 0);
+  bool isVolatileQualified() const { return Quals.hasVolatile(); }
+  bool isRestrictQualified() const { return Quals.hasRestrict(); }
+  unsigned getVRQualifiers() const {
+    return Quals.getCVRQualifiers() & ~Qualifiers::Const;
   }
 
   bool isObjCIvar() const { return Ivar; }
   bool isObjCArray() const { return ObjIsArray; }
   bool isNonGC () const { return NonGC; }
   bool isGlobalObjCRef() const { return GlobalObjCRef; }
-  bool isObjCWeak() const { return ObjCType == Weak; }
-  bool isObjCStrong() const { return ObjCType == Strong; }
+  bool isObjCWeak() const { return Quals.getObjCGCAttr() == Qualifiers::Weak; }
+  bool isObjCStrong() const { return Quals.getObjCGCAttr() == Qualifiers::Strong; }
 
-  unsigned getAddressSpace() const { return AddressSpace; }
+  unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
 
   static void SetObjCIvar(LValue& R, bool iValue) {
     R.Ivar = iValue;
@@ -216,14 +201,6 @@
   static void SetObjCNonGC(LValue& R, bool iValue) {
     R.NonGC = iValue;
   }
-  static void SetObjCType(QualType::GCAttrTypes GCAttrs, LValue& R) {
-    if (GCAttrs == QualType::Weak)
-      R.ObjCType = Weak;
-    else if (GCAttrs == QualType::Strong)
-      R.ObjCType = Strong;
-    else
-     R.ObjCType = None;
-  }
 
   // simple lvalue
   llvm::Value *getAddress() const { assert(isSimple()); return V; }
@@ -262,48 +239,44 @@
     return KVCRefExpr;
   }
 
-  static LValue MakeAddr(llvm::Value *V, unsigned Qualifiers,
-                         QualType::GCAttrTypes GCAttrs = QualType::GCNone,
-                         unsigned AddressSpace = 0) {
+  static LValue MakeAddr(llvm::Value *V, Qualifiers Quals) {
     LValue R;
     R.LVType = Simple;
     R.V = V;
-    SetQualifiers(Qualifiers,R);
-    R.AddressSpace = AddressSpace;
-    SetObjCType(GCAttrs, R);
+    R.SetQualifiers(Quals);
     return R;
   }
 
   static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx,
-                              unsigned Qualifiers) {
+                              unsigned CVR) {
     LValue R;
     R.LVType = VectorElt;
     R.V = Vec;
     R.VectorIdx = Idx;
-    SetQualifiers(Qualifiers,R);
+    R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
     return R;
   }
 
   static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts,
-                                 unsigned Qualifiers) {
+                                 unsigned CVR) {
     LValue R;
     R.LVType = ExtVectorElt;
     R.V = Vec;
     R.VectorElts = Elts;
-    SetQualifiers(Qualifiers,R);
+    R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
     return R;
   }
 
   static LValue MakeBitfield(llvm::Value *V, unsigned short StartBit,
                              unsigned short Size, bool IsSigned,
-                             unsigned Qualifiers) {
+                             unsigned CVR) {
     LValue R;
     R.LVType = BitField;
     R.V = V;
     R.BitfieldData.StartBit = StartBit;
     R.BitfieldData.Size = Size;
     R.BitfieldData.IsSigned = IsSigned;
-    SetQualifiers(Qualifiers,R);
+    R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
     return R;
   }
 
@@ -311,20 +284,20 @@
   // the lvalue. However, this complicates the code a bit, and I haven't figured
   // out how to make it go wrong yet.
   static LValue MakePropertyRef(const ObjCPropertyRefExpr *E,
-                                unsigned Qualifiers) {
+                                unsigned CVR) {
     LValue R;
     R.LVType = PropertyRef;
     R.PropertyRefExpr = E;
-    SetQualifiers(Qualifiers,R);
+    R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
     return R;
   }
 
   static LValue MakeKVCRef(const ObjCImplicitSetterGetterRefExpr *E,
-                           unsigned Qualifiers) {
+                           unsigned CVR) {
     LValue R;
     R.LVType = KVCRef;
     R.KVCRefExpr = E;
-    SetQualifiers(Qualifiers,R);
+    R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
     return R;
   }
 };

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Sep 24 14:53:00 2009
@@ -496,6 +496,12 @@
   //                                  Helpers
   //===--------------------------------------------------------------------===//
 
+  Qualifiers MakeQualifiers(QualType T) {
+    Qualifiers Quals = T.getQualifiers();
+    Quals.setObjCGCAttr(getContext().getObjCGCAttrKind(T));
+    return Quals;
+  }
+
   /// CreateTempAlloca - This creates a alloca and inserts it into the entry
   /// block.
   llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty,

Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Thu Sep 24 14:53:00 2009
@@ -267,7 +267,7 @@
 
   case Type::VariableArray: {
     const VariableArrayType &A = cast<VariableArrayType>(Ty);
-    assert(A.getIndexTypeQualifier() == 0 &&
+    assert(A.getIndexTypeCVRQualifiers() == 0 &&
            "FIXME: We only handle trivial array types so far!");
     // VLAs resolve to the innermost element type; this matches
     // the return of alloca, and there isn't any obviously better choice.
@@ -275,7 +275,7 @@
   }
   case Type::IncompleteArray: {
     const IncompleteArrayType &A = cast<IncompleteArrayType>(Ty);
-    assert(A.getIndexTypeQualifier() == 0 &&
+    assert(A.getIndexTypeCVRQualifiers() == 0 &&
            "FIXME: We only handle trivial array types so far!");
     // int X[] -> [0 x int]
     return llvm::ArrayType::get(ConvertTypeForMemRecursive(A.getElementType()), 0);
@@ -312,10 +312,6 @@
     return GetFunctionType(getFunctionInfo(FNPT), true);
   }
 
-  case Type::ExtQual:
-    return
-      ConvertTypeRecursive(QualType(cast<ExtQualType>(Ty).getBaseType(), 0));
-
   case Type::ObjCInterface: {
     // Objective-C interfaces are always opaque (outside of the
     // runtime, which can do whatever it likes); we never refine

Modified: cfe/trunk/lib/CodeGen/Mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.cpp (original)
+++ cfe/trunk/lib/CodeGen/Mangle.cpp Thu Sep 24 14:53:00 2009
@@ -84,7 +84,7 @@
     void manglePrefix(const DeclContext *DC);
     void mangleTemplatePrefix(const NamedDecl *ND);
     void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
-    void mangleCVQualifiers(unsigned Quals);
+    void mangleQualifiers(Qualifiers Quals);
     void mangleType(QualType T);
 
     // Declare manglers for every type class.
@@ -459,7 +459,7 @@
   // FIXME: no class template support
   Out << 'N';
   if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND))
-    mangleCVQualifiers(Method->getTypeQualifiers());
+    mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
   
   // Check if we have a template.
   const TemplateArgumentList *TemplateArgs = 0;
@@ -637,14 +637,16 @@
   }
 }
 
-void CXXNameMangler::mangleCVQualifiers(unsigned Quals) {
+void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
   // <CV-qualifiers> ::= [r] [V] [K]    # restrict (C99), volatile, const
-  if (Quals & QualType::Restrict)
+  if (Quals.hasRestrict())
     Out << 'r';
-  if (Quals & QualType::Volatile)
+  if (Quals.hasVolatile())
     Out << 'V';
-  if (Quals & QualType::Const)
+  if (Quals.hasConst())
     Out << 'K';
+
+  // FIXME: For now, just drop all extension qualifiers on the floor.
 }
 
 void CXXNameMangler::mangleType(QualType T) {
@@ -655,10 +657,10 @@
   if (IsSubstitutable && mangleSubstitution(T))
     return;
 
-  if (unsigned CVRQualifiers = T.getCVRQualifiers()) {
-    //  <type> ::= <CV-qualifiers> <type>
-    mangleCVQualifiers(CVRQualifiers);
-
+  if (Qualifiers Quals = T.getQualifiers()) {
+    mangleQualifiers(Quals);
+    // Recurse:  even if the qualified type isn't yet substitutable,
+    // the unqualified type might be.
     mangleType(T.getUnqualifiedType());
   } else {
     switch (T->getTypeClass()) {
@@ -669,7 +671,7 @@
       return;
 #define TYPE(CLASS, PARENT) \
     case Type::CLASS: \
-      mangleType(static_cast<CLASS##Type*>(T.getTypePtr())); \
+      mangleType(static_cast<const CLASS##Type*>(T.getTypePtr())); \
       break;
 #include "clang/AST/TypeNodes.def"
     }
@@ -830,7 +832,7 @@
   mangleType(QualType(T->getClass(), 0));
   QualType PointeeType = T->getPointeeType();
   if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
-    mangleCVQualifiers(FPT->getTypeQuals());
+    mangleQualifiers(Qualifiers::fromCVRMask(FPT->getTypeQuals()));
     mangleType(FPT);
   } else
     mangleType(PointeeType);
@@ -912,11 +914,6 @@
   assert(false && "can't mangle dependent typenames yet");
 }
 
-// FIXME: For now, just drop all extension qualifiers on the floor.
-void CXXNameMangler::mangleType(const ExtQualType *T) {
-  mangleType(QualType(T->getBaseType(), 0));
-}
-
 void CXXNameMangler::mangleExpression(const Expr *E) {
   // <expression> ::= <unary operator-name> <expression>
 	//              ::= <binary operator-name> <expression> <expression>

Modified: cfe/trunk/lib/Frontend/DocumentXML.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/DocumentXML.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/DocumentXML.cpp (original)
+++ cfe/trunk/lib/Frontend/DocumentXML.cpp Thu Sep 24 14:53:00 2009
@@ -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()];
     }

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Thu Sep 24 14:53:00 2009
@@ -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);

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Thu Sep 24 14:53:00 2009
@@ -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) {

Modified: cfe/trunk/lib/Frontend/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/RewriteObjC.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Frontend/RewriteObjC.cpp Thu Sep 24 14:53:00 2009
@@ -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);

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Thu Sep 24 14:53:00 2009
@@ -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,

Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Thu Sep 24 14:53:00 2009
@@ -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.

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Sep 24 14:53:00 2009
@@ -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>()) &&

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Sep 24 14:53:00 2009
@@ -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")

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Sep 24 14:53:00 2009
@@ -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*

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Sep 24 14:53:00 2009
@@ -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));
     }
   }
 

Modified: cfe/trunk/lib/Sema/SemaInherit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInherit.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaInherit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInherit.cpp Thu Sep 24 14:53:00 2009
@@ -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;
 }

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Sep 24 14:53:00 2009
@@ -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!");
+
+  QualType PointeeTy = PointerTy->getPointeeType();
+  const Type *ClassTy = PointerTy->getClass();
 
-    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));
+  // 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);
       }

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Thu Sep 24 14:53:00 2009
@@ -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; }

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Thu Sep 24 14:53:00 2009
@@ -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(),

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Sep 24 14:53:00 2009
@@ -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 =

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Thu Sep 24 14:53:00 2009
@@ -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();

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Sep 24 14:53:00 2009
@@ -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());
   }

Modified: cfe/trunk/test/Sema/address_spaces.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/address_spaces.c?rev=82705&r1=82704&r2=82705&view=diff

==============================================================================
--- cfe/trunk/test/Sema/address_spaces.c (original)
+++ cfe/trunk/test/Sema/address_spaces.c Thu Sep 24 14:53:00 2009
@@ -33,6 +33,6 @@
 __attribute__((address_space(256))) void * * const base = 0;
 void * get_0(void) {
   return base[0];  // expected-error {{illegal implicit cast between two pointers with different address spaces}} \
-                      expected-warning {{returning 'void __attribute__((address_space(256)))*' discards qualifiers, expected 'void *'}}
+                      expected-warning {{returning 'void __attribute__((address_space(256))) *' discards qualifiers, expected 'void *'}}
 }
 





More information about the cfe-commits mailing list