Substantially alter the design of the Objective C type AST by introducing
ObjCObjectType, which is basically just a pair of
one of {primitive-id, primitive-Class, user-defined @class}
with
a list of protocols.
An ObjCObjectPointerType is therefore just a pointer which always points to
one of these types (possibly sugared). ObjCInterfaceType is now just a kind
of ObjCObjectType which happens to not carry any protocols.
Alter a rather large number of use sites to use ObjCObjectType instead of
ObjCInterfaceType. Store an ObjCInterfaceType as a pointer on the decl rather
than hashing them in a FoldingSet. Remove some number of methods that are no
longer used, at least after this patch.
By simplifying ObjCObjectPointerType, we are now able to easily remove and apply
pointers to Objective-C types, which is crucial for a certain kind of ObjC++
metaprogramming common in WebKit.
llvm-svn: 103870
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 81b56ad..d0e4c02 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -595,6 +595,8 @@
Align = EltInfo.second;
break;
}
+ case Type::ObjCObject:
+ return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr());
case Type::ObjCInterface: {
const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T);
const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
@@ -1692,10 +1694,6 @@
if (const TypedefDecl *Typedef = dyn_cast<TypedefDecl>(Decl))
return getTypedefType(Typedef);
- if (const ObjCInterfaceDecl *ObjCInterface
- = dyn_cast<ObjCInterfaceDecl>(Decl))
- return getObjCInterfaceType(ObjCInterface);
-
assert(!isa<TemplateTypeParmDecl>(Decl) &&
"Template type parameter types are always available.");
@@ -1991,7 +1989,7 @@
return LHS->getDeclName() < RHS->getDeclName();
}
-static bool areSortedAndUniqued(ObjCProtocolDecl **Protocols,
+static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols) {
if (NumProtocols == 0) return true;
@@ -2013,94 +2011,96 @@
NumProtocols = ProtocolsEnd-Protocols;
}
-/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for
-/// the given interface decl and the conforming protocol list.
-QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
- ObjCProtocolDecl **Protocols,
- unsigned NumProtocols,
- unsigned Quals) {
+QualType ASTContext::getObjCObjectType(QualType BaseType,
+ ObjCProtocolDecl * const *Protocols,
+ unsigned NumProtocols) {
+ // If the base type is an interface and there aren't any protocols
+ // to add, then the interface type will do just fine.
+ if (!NumProtocols && isa<ObjCInterfaceType>(BaseType))
+ return BaseType;
+
+ // Look in the folding set for an existing type.
llvm::FoldingSetNodeID ID;
- ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols);
- Qualifiers Qs = Qualifiers::fromCVRMask(Quals);
-
+ ObjCObjectTypeImpl::Profile(ID, BaseType, Protocols, NumProtocols);
void *InsertPos = 0;
- if (ObjCObjectPointerType *QT =
- ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
- return getQualifiedType(QualType(QT, 0), Qs);
+ if (ObjCObjectType *QT = ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(QT, 0);
- // Sort the protocol list alphabetically to canonicalize it.
+ // Build the canonical type, which has the canonical base type and
+ // a sorted-and-uniqued list of protocols.
QualType Canonical;
- if (!InterfaceT.isCanonical() ||
- !areSortedAndUniqued(Protocols, NumProtocols)) {
- if (!areSortedAndUniqued(Protocols, NumProtocols)) {
+ bool ProtocolsSorted = areSortedAndUniqued(Protocols, NumProtocols);
+ if (!ProtocolsSorted || !BaseType.isCanonical()) {
+ if (!ProtocolsSorted) {
llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols,
Protocols + NumProtocols);
unsigned UniqueCount = NumProtocols;
SortAndUniqueProtocols(&Sorted[0], UniqueCount);
-
- Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT),
- &Sorted[0], UniqueCount);
+ Canonical = getObjCObjectType(getCanonicalType(BaseType),
+ &Sorted[0], UniqueCount);
} else {
- Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT),
- Protocols, NumProtocols);
+ Canonical = getObjCObjectType(getCanonicalType(BaseType),
+ Protocols, NumProtocols);
}
// Regenerate InsertPos.
+ ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos);
+ }
+
+ unsigned Size = sizeof(ObjCObjectTypeImpl);
+ Size += NumProtocols * sizeof(ObjCProtocolDecl *);
+ void *Mem = Allocate(Size, TypeAlignment);
+ ObjCObjectTypeImpl *T =
+ new (Mem) ObjCObjectTypeImpl(Canonical, BaseType, Protocols, NumProtocols);
+
+ Types.push_back(T);
+ ObjCObjectTypes.InsertNode(T, InsertPos);
+ return QualType(T, 0);
+}
+
+/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for
+/// the given object type.
+QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) {
+ llvm::FoldingSetNodeID ID;
+ ObjCObjectPointerType::Profile(ID, ObjectT);
+
+ void *InsertPos = 0;
+ if (ObjCObjectPointerType *QT =
+ ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(QT, 0);
+
+ // Find the canonical object type.
+ QualType Canonical;
+ if (!ObjectT.isCanonical()) {
+ Canonical = getObjCObjectPointerType(getCanonicalType(ObjectT));
+
+ // Regenerate InsertPos.
ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
}
// No match.
- unsigned Size = sizeof(ObjCObjectPointerType)
- + NumProtocols * sizeof(ObjCProtocolDecl *);
- void *Mem = Allocate(Size, TypeAlignment);
- ObjCObjectPointerType *QType = new (Mem) ObjCObjectPointerType(Canonical,
- InterfaceT,
- Protocols,
- NumProtocols);
+ void *Mem = Allocate(sizeof(ObjCObjectPointerType), TypeAlignment);
+ ObjCObjectPointerType *QType =
+ new (Mem) ObjCObjectPointerType(Canonical, ObjectT);
Types.push_back(QType);
ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
- return getQualifiedType(QualType(QType, 0), Qs);
+ return QualType(QType, 0);
}
/// getObjCInterfaceType - Return the unique reference to the type for the
/// specified ObjC interface decl. The list of protocols is optional.
-QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
- ObjCProtocolDecl **Protocols, unsigned NumProtocols) {
- llvm::FoldingSetNodeID ID;
- ObjCInterfaceType::Profile(ID, Decl, Protocols, NumProtocols);
+QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) {
+ if (Decl->TypeForDecl)
+ return QualType(Decl->TypeForDecl, 0);
- void *InsertPos = 0;
- if (ObjCInterfaceType *QT =
- ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(QT, 0);
-
- // Sort the protocol list alphabetically to canonicalize it.
- QualType Canonical;
- if (NumProtocols && !areSortedAndUniqued(Protocols, NumProtocols)) {
- llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols,
- Protocols + NumProtocols);
-
- unsigned UniqueCount = NumProtocols;
- SortAndUniqueProtocols(&Sorted[0], UniqueCount);
-
- Canonical = getObjCInterfaceType(Decl, &Sorted[0], UniqueCount);
-
- ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos);
- }
-
- unsigned Size = sizeof(ObjCInterfaceType)
- + NumProtocols * sizeof(ObjCProtocolDecl *);
- void *Mem = Allocate(Size, TypeAlignment);
- ObjCInterfaceType *QType = new (Mem) ObjCInterfaceType(Canonical,
- const_cast<ObjCInterfaceDecl*>(Decl),
- Protocols,
- NumProtocols);
-
- Types.push_back(QType);
- ObjCInterfaceTypes.InsertNode(QType, InsertPos);
- return QualType(QType, 0);
+ // FIXME: redeclarations?
+ void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment);
+ ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl);
+ Decl->TypeForDecl = T;
+ Types.push_back(T);
+ return QualType(T, 0);
}
/// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique
@@ -3620,6 +3620,10 @@
return;
}
+ // Ignore protocol qualifiers when mangling at this level.
+ if (const ObjCObjectType *OT = T->getAs<ObjCObjectType>())
+ T = OT->getBaseType();
+
if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
// @encode(class_name)
ObjCInterfaceDecl *OI = OIT->getDecl();
@@ -4090,18 +4094,21 @@
///
bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT) {
+ const ObjCObjectType* LHS = LHSOPT->getObjectType();
+ const ObjCObjectType* RHS = RHSOPT->getObjectType();
+
// If either type represents the built-in 'id' or 'Class' types, return true.
- if (LHSOPT->isObjCBuiltinType() || RHSOPT->isObjCBuiltinType())
+ if (LHS->isObjCUnqualifiedIdOrClass() ||
+ RHS->isObjCUnqualifiedIdOrClass())
return true;
- if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType())
+ if (LHS->isObjCQualifiedId() || RHS->isObjCQualifiedId())
return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0),
false);
- const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
- const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
- if (LHS && RHS) // We have 2 user-defined types.
+ // If we have 2 user-defined types, fall into that path.
+ if (LHS->getInterface() && RHS->getInterface())
return canAssignObjCInterfaces(LHS, RHS);
return false;
@@ -4152,8 +4159,10 @@
const ObjCObjectPointerType *RHSOPT,
llvm::SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) {
- const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
- const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
+ const ObjCObjectType* LHS = LHSOPT->getObjectType();
+ const ObjCObjectType* RHS = RHSOPT->getObjectType();
+ assert(LHS->getInterface() && "LHS must have an interface base");
+ assert(RHS->getInterface() && "RHS must have an interface base");
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocolSet;
unsigned LHSNumProtocols = LHS->getNumProtocols();
@@ -4161,7 +4170,8 @@
InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end());
else {
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> LHSInheritedProtocols;
- Context.CollectInheritedProtocols(LHS->getDecl(), LHSInheritedProtocols);
+ Context.CollectInheritedProtocols(LHS->getInterface(),
+ LHSInheritedProtocols);
InheritedProtocolSet.insert(LHSInheritedProtocols.begin(),
LHSInheritedProtocols.end());
}
@@ -4176,7 +4186,8 @@
}
else {
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSInheritedProtocols;
- Context.CollectInheritedProtocols(RHS->getDecl(), RHSInheritedProtocols);
+ Context.CollectInheritedProtocols(RHS->getInterface(),
+ RHSInheritedProtocols);
for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I =
RHSInheritedProtocols.begin(),
E = RHSInheritedProtocols.end(); I != E; ++I)
@@ -4190,37 +4201,40 @@
/// last type comparison in a ?-exp of ObjC pointer types before a
/// warning is issued. So, its invokation is extremely rare.
QualType ASTContext::areCommonBaseCompatible(
- const ObjCObjectPointerType *LHSOPT,
- const ObjCObjectPointerType *RHSOPT) {
- const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
- const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
- if (!LHS || !RHS)
+ const ObjCObjectPointerType *Lptr,
+ const ObjCObjectPointerType *Rptr) {
+ const ObjCObjectType *LHS = Lptr->getObjectType();
+ const ObjCObjectType *RHS = Rptr->getObjectType();
+ const ObjCInterfaceDecl* LDecl = LHS->getInterface();
+ const ObjCInterfaceDecl* RDecl = RHS->getInterface();
+ if (!LDecl || !RDecl)
return QualType();
- while (const ObjCInterfaceDecl *LHSIDecl = LHS->getDecl()->getSuperClass()) {
- QualType LHSTy = getObjCInterfaceType(LHSIDecl);
- LHS = LHSTy->getAs<ObjCInterfaceType>();
+ while ((LDecl = LDecl->getSuperClass())) {
+ LHS = cast<ObjCInterfaceType>(getObjCInterfaceType(LDecl));
if (canAssignObjCInterfaces(LHS, RHS)) {
- llvm::SmallVector<ObjCProtocolDecl *, 8> IntersectionOfProtocols;
- getIntersectionOfProtocols(*this,
- LHSOPT, RHSOPT, IntersectionOfProtocols);
- if (IntersectionOfProtocols.empty())
- LHSTy = getObjCObjectPointerType(LHSTy);
- else
- LHSTy = getObjCObjectPointerType(LHSTy, &IntersectionOfProtocols[0],
- IntersectionOfProtocols.size());
- return LHSTy;
+ llvm::SmallVector<ObjCProtocolDecl *, 8> Protocols;
+ getIntersectionOfProtocols(*this, Lptr, Rptr, Protocols);
+
+ QualType Result = QualType(LHS, 0);
+ if (!Protocols.empty())
+ Result = getObjCObjectType(Result, Protocols.data(), Protocols.size());
+ Result = getObjCObjectPointerType(Result);
+ return Result;
}
}
return QualType();
}
-bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
- const ObjCInterfaceType *RHS) {
+bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
+ const ObjCObjectType *RHS) {
+ assert(LHS->getInterface() && "LHS is not an interface type");
+ assert(RHS->getInterface() && "RHS is not an interface type");
+
// Verify that the base decls are compatible: the RHS must be a subclass of
// the LHS.
- if (!LHS->getDecl()->isSuperClassOf(RHS->getDecl()))
+ if (!LHS->getInterface()->isSuperClassOf(RHS->getInterface()))
return false;
// RHS must have a superset of the protocols in the LHS. If the LHS is not
@@ -4233,15 +4247,15 @@
if (RHS->getNumProtocols() == 0)
return true; // FIXME: should return false!
- for (ObjCInterfaceType::qual_iterator LHSPI = LHS->qual_begin(),
- LHSPE = LHS->qual_end();
+ for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(),
+ LHSPE = LHS->qual_end();
LHSPI != LHSPE; LHSPI++) {
bool RHSImplementsProtocol = false;
// If the RHS doesn't implement the protocol on the left, the types
// are incompatible.
- for (ObjCInterfaceType::qual_iterator RHSPI = RHS->qual_begin(),
- RHSPE = RHS->qual_end();
+ for (ObjCObjectType::qual_iterator RHSPI = RHS->qual_begin(),
+ RHSPE = RHS->qual_end();
RHSPI != RHSPE; RHSPI++) {
if ((*RHSPI)->lookupProtocolNamed((*LHSPI)->getIdentifier())) {
RHSImplementsProtocol = true;
@@ -4467,6 +4481,10 @@
if (RHSClass == Type::VariableArray || RHSClass == Type::IncompleteArray)
RHSClass = Type::ConstantArray;
+ // ObjCInterfaces are just specialized ObjCObjects.
+ if (LHSClass == Type::ObjCInterface) LHSClass = Type::ObjCObject;
+ if (RHSClass == Type::ObjCInterface) RHSClass = Type::ObjCObject;
+
// Canonicalize ExtVector -> Vector.
if (LHSClass == Type::ExtVector) LHSClass = Type::Vector;
if (RHSClass == Type::ExtVector) RHSClass = Type::Vector;
@@ -4506,6 +4524,7 @@
assert(false && "C++ should never be in mergeTypes");
return QualType();
+ case Type::ObjCInterface:
case Type::IncompleteArray:
case Type::VariableArray:
case Type::FunctionProto:
@@ -4598,14 +4617,13 @@
RHSCan->getAs<VectorType>()))
return LHS;
return QualType();
- case Type::ObjCInterface: {
- // Check if the interfaces are assignment compatible.
+ case Type::ObjCObject: {
+ // Check if the types are assignment compatible.
// FIXME: This should be type compatibility, e.g. whether
// "LHS x; RHS x;" at global scope is legal.
- const ObjCInterfaceType* LHSIface = LHS->getAs<ObjCInterfaceType>();
- const ObjCInterfaceType* RHSIface = RHS->getAs<ObjCInterfaceType>();
- if (LHSIface && RHSIface &&
- canAssignObjCInterfaces(LHSIface, RHSIface))
+ const ObjCObjectType* LHSIface = LHS->getAs<ObjCObjectType>();
+ const ObjCObjectType* RHSIface = RHS->getAs<ObjCObjectType>();
+ if (canAssignObjCInterfaces(LHSIface, RHSIface))
return LHS;
return QualType();