]> granicus.if.org Git - clang/commitdiff
Revise the SplitQualType interface to make it its own thing instead of
authorJohn McCall <rjmccall@apple.com>
Wed, 8 Feb 2012 00:46:36 +0000 (00:46 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 8 Feb 2012 00:46:36 +0000 (00:46 +0000)
a typedef of std::pair.  This slightly improves type-safety, but mostly
makes code using it clearer to read as well as making it possible to add
methods to the type.

Add such a method for efficiently single-step desugaring a split type.
Add a method to single-step desugaring a locally-unqualified type.
Implement both the SplitQualType and QualType methods in terms of that.

Also, fix a typo ("ObjCGLifetime").

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150028 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
include/clang/AST/Type.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/ASTContext.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/Type.cpp
lib/AST/TypePrinter.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaOverload.cpp
lib/Sema/SemaType.cpp

index c0d191e565d29e185c027a6947a117c962770a50..3236977030e82d064e11f2c04088193e99b91c89 100644 (file)
@@ -1134,6 +1134,11 @@ public:
     return getQualifiedType(T, Qualifiers::fromCVRMask(CVR));
   }
 
+  /// getQualifiedType - Un-split a SplitQualType.
+  QualType getQualifiedType(SplitQualType split) const {
+    return getQualifiedType(split.Ty, split.Quals);
+  }
+
   /// getQualifiedType - Returns a type with additional qualifiers.
   QualType getQualifiedType(QualType T, Qualifiers Qs) const {
     if (!Qs.hasNonFastQualifiers())
index 641f732c599ade521f10e2a8afa0adf2959eb10f..ef4dbdd241cd151894d6fdbad342702aec7af2b7 100644 (file)
@@ -236,7 +236,7 @@ public:
     qs.removeObjCGCAttr();
     return qs;
   }
-  Qualifiers withoutObjCGLifetime() const {
+  Qualifiers withoutObjCLifetime() const {
     Qualifiers qs = *this;
     qs.removeObjCLifetime();
     return qs;
@@ -252,7 +252,8 @@ public:
   void removeObjCLifetime() { setObjCLifetime(OCL_None); }
   void addObjCLifetime(ObjCLifetime type) {
     assert(type);
-    setObjCLifetime(type);
+    assert(!hasObjCLifetime());
+    Mask |= (type << LifetimeShift);
   }
 
   /// True if the lifetime is neither None or ExplicitNone.
@@ -447,7 +448,32 @@ enum CallingConv {
   CC_AAPCS_VFP    // __attribute__((pcs("aapcs-vfp")))
 };
 
-typedef std::pair<const Type*, Qualifiers> SplitQualType;
+/// A std::pair-like structure for storing a qualified type split
+/// into its local qualifiers and its locally-unqualified type.
+struct SplitQualType {
+  /// The locally-unqualified type.
+  const Type *Ty;
+
+  /// The local qualifiers.
+  Qualifiers Quals;
+
+  SplitQualType() : Ty(0), Quals() {}
+  SplitQualType(const Type *ty, Qualifiers qs) : Ty(ty), Quals(qs) {}
+
+  SplitQualType getSingleStepDesugaredType() const; // end of this file
+
+  // Make llvm::tie work.
+  operator std::pair<const Type *,Qualifiers>() const {
+    return std::pair<const Type *,Qualifiers>(Ty, Quals);
+  }
+
+  friend bool operator==(SplitQualType a, SplitQualType b) {
+    return a.Ty == b.Ty && a.Quals == b.Quals;
+  }
+  friend bool operator!=(SplitQualType a, SplitQualType b) {
+    return a.Ty != b.Ty || a.Quals != b.Quals;
+  }
+};
 
 /// 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
@@ -769,7 +795,9 @@ public:
   ///
   /// This routine takes off the first typedef, typeof, etc. If the outer level
   /// of the type is already concrete, it returns it unmodified.
-  QualType getSingleStepDesugaredType(const ASTContext &Context) const;
+  QualType getSingleStepDesugaredType(const ASTContext &Context) const {
+    return getSingleStepDesugaredTypeImpl(*this, Context);
+  }
 
   /// IgnoreParens - Returns the specified type after dropping any
   /// outer-level parentheses.
@@ -791,7 +819,7 @@ public:
     return getAsString(split());
   }
   static std::string getAsString(SplitQualType split) {
-    return getAsString(split.first, split.second);
+    return getAsString(split.Ty, split.Quals);
   }
   static std::string getAsString(const Type *ty, Qualifiers qs);
 
@@ -806,7 +834,7 @@ public:
   }
   static void getAsStringInternal(SplitQualType split, std::string &out,
                                   const PrintingPolicy &policy) {
-    return getAsStringInternal(split.first, split.second, out, policy);
+    return getAsStringInternal(split.Ty, split.Quals, out, policy);
   }
   static void getAsStringInternal(const Type *ty, Qualifiers qs,
                                   std::string &out,
@@ -887,6 +915,8 @@ private:
   static QualType getDesugaredType(QualType T, const ASTContext &Context);
   static SplitQualType getSplitDesugaredType(QualType T);
   static SplitQualType getSplitUnqualifiedTypeImpl(QualType type);
+  static QualType getSingleStepDesugaredTypeImpl(QualType type,
+                                                 const ASTContext &C);
   static QualType IgnoreParens(QualType T);
   static DestructionKind isDestructedTypeImpl(QualType type);
 };
@@ -1333,6 +1363,11 @@ public:
     return CanonicalType == QualType(this, 0);
   }
 
+  /// Pull a single level of sugar off of this locally-unqualified type.
+  /// Users should generally prefer SplitQualType::getSingleStepDesugaredType()
+  /// or QualType::getSingleStepDesugaredType(const ASTContext&).
+  QualType getLocallyUnqualifiedSingleStepDesugaredType() const;
+
   /// Types are partitioned into 3 broad categories (C99 6.2.5p1):
   /// object types, function types, and incomplete types.
 
@@ -4406,6 +4441,13 @@ public:
 
 // Inline function definitions.
 
+inline SplitQualType SplitQualType::getSingleStepDesugaredType() const {
+  SplitQualType desugar =
+    Ty->getLocallyUnqualifiedSingleStepDesugaredType().split();
+  desugar.Quals.addConsistentQualifiers(Quals);
+  return desugar;
+}
+
 inline const Type *QualType::getTypePtr() const {
   return getCommonPtr()->BaseType;
 }
@@ -4490,7 +4532,7 @@ inline QualType QualType::getUnqualifiedType() const {
   if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers())
     return QualType(getTypePtr(), 0);
 
-  return QualType(getSplitUnqualifiedTypeImpl(*this).first, 0);
+  return QualType(getSplitUnqualifiedTypeImpl(*this).Ty, 0);
 }
 
 inline SplitQualType QualType::getSplitUnqualifiedType() const {
index e52b35e1cdc8f344beded1e6821aa16495376e45..4366cd4dee80b0d46d64c38d355b56bfbe7d5a35 100644 (file)
@@ -1526,7 +1526,7 @@ def err_arg_with_address_space : Error<
 def err_attr_objc_ownership_bad_type : Error<
   "the type %0 cannot be retained">;
 def err_attr_objc_ownership_redundant : Error<
-  "the type %0 already has retainment attributes set on it">;
+  "the type %0 is already explicitly ownership-qualified">;
 def err_attribute_not_string : Error<
   "argument to %0 attribute was not a string literal">;
 def err_only_annotate_after_access_spec : Error<
index 069f1068da387c36f4c089957aabfbe6ee54922a..fb7d7473776fc6eb2f658865ab2baa3fef98ebe7 100644 (file)
@@ -1387,8 +1387,8 @@ ASTContext::getExtQualType(const Type *baseType, Qualifiers quals) const {
   QualType canon;
   if (!baseType->isCanonicalUnqualified()) {
     SplitQualType canonSplit = baseType->getCanonicalTypeInternal().split();
-    canonSplit.second.addConsistentQualifiers(quals);
-    canon = getExtQualType(canonSplit.first, canonSplit.second);
+    canonSplit.Quals.addConsistentQualifiers(quals);
+    canon = getExtQualType(canonSplit.Ty, canonSplit.Quals);
 
     // Re-find the insert position.
     (void) ExtQualNodes.FindNodeOrInsertPos(ID, insertPos);
@@ -1690,9 +1690,9 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
   QualType Canon;
   if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers()) {
     SplitQualType canonSplit = getCanonicalType(EltTy).split();
-    Canon = getConstantArrayType(QualType(canonSplit.first, 0), ArySize,
+    Canon = getConstantArrayType(QualType(canonSplit.Ty, 0), ArySize,
                                  ASM, IndexTypeQuals);
-    Canon = getQualifiedType(Canon, canonSplit.second);
+    Canon = getQualifiedType(Canon, canonSplit.Quals);
 
     // Get the new insert position for the node we care about.
     ConstantArrayType *NewIP =
@@ -1717,7 +1717,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
   QualType result;
 
   SplitQualType split = type.getSplitDesugaredType();
-  const Type *ty = split.first;
+  const Type *ty = split.Ty;
   switch (ty->getTypeClass()) {
 #define TYPE(Class, Base)
 #define ABSTRACT_TYPE(Class, Base)
@@ -1836,7 +1836,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
   }
 
   // Apply the top-level qualifiers from the original.
-  return getQualifiedType(result, split.second);
+  return getQualifiedType(result, split.Quals);
 }
 
 /// getVariableArrayType - Returns a non-unique reference to the type for a
@@ -1853,9 +1853,9 @@ QualType ASTContext::getVariableArrayType(QualType EltTy,
   // Be sure to pull qualifiers off the element type.
   if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers()) {
     SplitQualType canonSplit = getCanonicalType(EltTy).split();
-    Canon = getVariableArrayType(QualType(canonSplit.first, 0), NumElts, ASM,
+    Canon = getVariableArrayType(QualType(canonSplit.Ty, 0), NumElts, ASM,
                                  IndexTypeQuals, Brackets);
-    Canon = getQualifiedType(Canon, canonSplit.second);
+    Canon = getQualifiedType(Canon, canonSplit.Quals);
   }
   
   VariableArrayType *New = new(*this, TypeAlignment)
@@ -1900,7 +1900,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType,
   void *insertPos = 0;
   llvm::FoldingSetNodeID ID;
   DependentSizedArrayType::Profile(ID, *this,
-                                   QualType(canonElementType.first, 0),
+                                   QualType(canonElementType.Ty, 0),
                                    ASM, elementTypeQuals, numElements);
 
   // Look for an existing type with these properties.
@@ -1910,7 +1910,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType,
   // If we don't have one, build one.
   if (!canonTy) {
     canonTy = new (*this, TypeAlignment)
-      DependentSizedArrayType(*this, QualType(canonElementType.first, 0),
+      DependentSizedArrayType(*this, QualType(canonElementType.Ty, 0),
                               QualType(), numElements, ASM, elementTypeQuals,
                               brackets);
     DependentSizedArrayTypes.InsertNode(canonTy, insertPos);
@@ -1919,11 +1919,11 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType,
 
   // Apply qualifiers from the element type to the array.
   QualType canon = getQualifiedType(QualType(canonTy,0),
-                                    canonElementType.second);
+                                    canonElementType.Quals);
 
   // If we didn't need extra canonicalization for the element type,
   // then just use that as our result.
-  if (QualType(canonElementType.first, 0) == elementType)
+  if (QualType(canonElementType.Ty, 0) == elementType)
     return canon;
 
   // Otherwise, we need to build a type which follows the spelling
@@ -1954,9 +1954,9 @@ QualType ASTContext::getIncompleteArrayType(QualType elementType,
 
   if (!elementType.isCanonical() || elementType.hasLocalQualifiers()) {
     SplitQualType canonSplit = getCanonicalType(elementType).split();
-    canon = getIncompleteArrayType(QualType(canonSplit.first, 0),
+    canon = getIncompleteArrayType(QualType(canonSplit.Ty, 0),
                                    ASM, elementTypeQuals);
-    canon = getQualifiedType(canon, canonSplit.second);
+    canon = getQualifiedType(canon, canonSplit.Quals);
 
     // Get the new insert position for the node we care about.
     IncompleteArrayType *existing =
@@ -3134,12 +3134,12 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type,
   // We then have to strip that sugar back off with
   // getUnqualifiedDesugaredType(), which is silly.
   const ArrayType *AT =
-    dyn_cast<ArrayType>(splitType.first->getUnqualifiedDesugaredType());
+    dyn_cast<ArrayType>(splitType.Ty->getUnqualifiedDesugaredType());
 
   // If we don't have an array, just use the results in splitType.
   if (!AT) {
-    quals = splitType.second;
-    return QualType(splitType.first, 0);
+    quals = splitType.Quals;
+    return QualType(splitType.Ty, 0);
   }
 
   // Otherwise, recurse on the array's element type.
@@ -3150,13 +3150,13 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type,
   // can just use the results in splitType.
   if (elementType == unqualElementType) {
     assert(quals.empty()); // from the recursive call
-    quals = splitType.second;
-    return QualType(splitType.first, 0);
+    quals = splitType.Quals;
+    return QualType(splitType.Ty, 0);
   }
 
   // Otherwise, add in the qualifiers from the outermost type, then
   // build the type back up.
-  quals.addConsistentQualifiers(splitType.second);
+  quals.addConsistentQualifiers(splitType.Quals);
 
   if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
     return getConstantArrayType(unqualElementType, CAT->getSize(),
@@ -3458,10 +3458,10 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
   // we must propagate them down into the element type.
 
   SplitQualType split = T.getSplitDesugaredType();
-  Qualifiers qs = split.second;
+  Qualifiers qs = split.Quals;
 
   // If we have a simple case, just return now.
-  const ArrayType *ATy = dyn_cast<ArrayType>(split.first);
+  const ArrayType *ATy = dyn_cast<ArrayType>(split.Ty);
   if (ATy == 0 || qs.empty())
     return ATy;
 
@@ -3548,11 +3548,11 @@ QualType ASTContext::getBaseElementType(QualType type) const {
   Qualifiers qs;
   while (true) {
     SplitQualType split = type.getSplitDesugaredType();
-    const ArrayType *array = split.first->getAsArrayTypeUnsafe();
+    const ArrayType *array = split.Ty->getAsArrayTypeUnsafe();
     if (!array) break;
 
     type = array->getElementType();
-    qs.addConsistentQualifiers(split.second);
+    qs.addConsistentQualifiers(split.Quals);
   }
 
   return getQualifiedType(type, qs);
index 59192428b88e0101188a11806b3430dde07394b0..7df8f6fc6b85f6c4aeee6c88822f386a44d6cadd 100644 (file)
@@ -1655,8 +1655,8 @@ void CXXNameMangler::mangleType(QualType T) {
     } while (true);
   }
   SplitQualType split = T.split();
-  Qualifiers quals = split.second;
-  const Type *ty = split.first;
+  Qualifiers quals = split.Quals;
+  const Type *ty = split.Ty;
 
   bool isSubstitutable = quals || !isa<BuiltinType>(T);
   if (isSubstitutable && mangleSubstitution(T))
index ebf5706ed038dd37fc824a9c734f9a48cece0d90..b52e61b5284980f5bad422e73b18989f24364958 100644 (file)
@@ -197,27 +197,28 @@ const Type *Type::getArrayElementTypeNoTypeQual() const {
 /// concrete.
 QualType QualType::getDesugaredType(QualType T, const ASTContext &Context) {
   SplitQualType split = getSplitDesugaredType(T);
-  return Context.getQualifiedType(split.first, split.second);
+  return Context.getQualifiedType(split.Ty, split.Quals);
 }
 
-QualType QualType::getSingleStepDesugaredType(const ASTContext &Context) const {
-  QualifierCollector Qs;
-  
-  const Type *CurTy = Qs.strip(*this);
-  switch (CurTy->getTypeClass()) {
+QualType QualType::getSingleStepDesugaredTypeImpl(QualType type,
+                                                  const ASTContext &Context) {
+  SplitQualType split = type.split();
+  QualType desugar = split.Ty->getLocallyUnqualifiedSingleStepDesugaredType();
+  return Context.getQualifiedType(desugar, split.Quals);
+}
+
+QualType Type::getLocallyUnqualifiedSingleStepDesugaredType() const {
+  switch (getTypeClass()) {
 #define ABSTRACT_TYPE(Class, Parent)
 #define TYPE(Class, Parent) \
   case Type::Class: { \
-    const Class##Type *Ty = cast<Class##Type>(CurTy); \
-    if (!Ty->isSugared()) \
-      return *this; \
-    return Context.getQualifiedType(Ty->desugar(), Qs); \
-    break; \
+    const Class##Type *ty = cast<Class##Type>(this); \
+    if (!ty->isSugared()) return QualType(ty, 0); \
+    return ty->desugar(); \
   }
 #include "clang/AST/TypeNodes.def"
   }
-
-  return *this;
+  llvm_unreachable("bad type kind!");
 }
 
 SplitQualType QualType::getSplitDesugaredType(QualType T) {
@@ -245,21 +246,21 @@ SplitQualType QualType::getSplitUnqualifiedTypeImpl(QualType type) {
   SplitQualType split = type.split();
 
   // All the qualifiers we've seen so far.
-  Qualifiers quals = split.second;
+  Qualifiers quals = split.Quals;
 
   // The last type node we saw with any nodes inside it.
-  const Type *lastTypeWithQuals = split.first;
+  const Type *lastTypeWithQuals = split.Ty;
 
   while (true) {
     QualType next;
 
     // Do a single-step desugar, aborting the loop if the type isn't
     // sugared.
-    switch (split.first->getTypeClass()) {
+    switch (split.Ty->getTypeClass()) {
 #define ABSTRACT_TYPE(Class, Parent)
 #define TYPE(Class, Parent) \
     case Type::Class: { \
-      const Class##Type *ty = cast<Class##Type>(split.first); \
+      const Class##Type *ty = cast<Class##Type>(split.Ty); \
       if (!ty->isSugared()) goto done; \
       next = ty->desugar(); \
       break; \
@@ -270,9 +271,9 @@ SplitQualType QualType::getSplitUnqualifiedTypeImpl(QualType type) {
     // Otherwise, split the underlying type.  If that yields qualifiers,
     // update the information.
     split = next.split();
-    if (!split.second.empty()) {
-      lastTypeWithQuals = split.first;
-      quals.addConsistentQualifiers(split.second);
+    if (!split.Quals.empty()) {
+      lastTypeWithQuals = split.Ty;
+      quals.addConsistentQualifiers(split.Quals);
     }
   }
 
index 7e9e7c59b1b568a24b6db2b9045dce3587b4a981..abe68ef07b2707b6790e96cdfda4bbe71c340cde 100644 (file)
@@ -75,7 +75,7 @@ static void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
 
 void TypePrinter::print(QualType t, std::string &buffer) {
   SplitQualType split = t.split();
-  print(split.first, split.second, buffer);
+  print(split.Ty, split.Quals, buffer);
 }
 
 void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
index f656f90ea567600b71998a667ee6aeaddf46ac23..182956523821e3c2ea5d423cfe6f3d51e5a567a1 100644 (file)
@@ -4982,9 +4982,9 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) {
 
     // It's okay to add or remove GC or lifetime qualifiers when converting to
     // and from void*.
-    else if (lhq.withoutObjCGCAttr().withoutObjCGLifetime()
+    else if (lhq.withoutObjCGCAttr().withoutObjCLifetime()
                         .compatiblyIncludes(
-                                rhq.withoutObjCGCAttr().withoutObjCGLifetime())
+                                rhq.withoutObjCGCAttr().withoutObjCLifetime())
              && (lhptee->isVoidType() || rhptee->isVoidType()))
       ; // keep old
 
index fa103819bd29825067788f88f13288252c83191a..b0b2a783209b1fa55fe046c70110747d781aa829 100644 (file)
@@ -2211,7 +2211,7 @@ bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType,
   Qualifiers ToQuals = ToPointee.getQualifiers();
   if (!ToPointee->isObjCLifetimeType() || 
       ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing ||
-      !ToQuals.withoutObjCGLifetime().empty())
+      !ToQuals.withoutObjCLifetime().empty())
     return false;
   
   // Argument must be a pointer to __strong to __weak.
index 29cede91302355b4c2dfa9a2288723feec60eb54..67ee9376e8b23577d964895ac880d0f864c0d161 100644 (file)
@@ -3497,9 +3497,9 @@ namespace {
       SplitQualType SplitOld = Old.split();
 
       // As a special case, tail-recurse if there are no qualifiers.
-      if (SplitOld.second.empty())
-        return wrap(C, SplitOld.first, I);
-      return C.getQualifiedType(wrap(C, SplitOld.first, I), SplitOld.second);
+      if (SplitOld.Quals.empty())
+        return wrap(C, SplitOld.Ty, I);
+      return C.getQualifiedType(wrap(C, SplitOld.Ty, I), SplitOld.Quals);
     }
 
     QualType wrap(ASTContext &C, const Type *Old, unsigned I) {