Patch to implemented objective-c's dynamic object pointer qualified with
the protocol list (id<P,...> types).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45121 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp
index 4351b89..92b691e 100644
--- a/AST/ASTContext.cpp
+++ b/AST/ASTContext.cpp
@@ -49,6 +49,7 @@
unsigned NumTagStruct = 0, NumTagUnion = 0, NumTagEnum = 0, NumTagClass = 0;
unsigned NumObjcInterfaces = 0, NumObjcQualifiedInterfaces = 0;
+ unsigned NumObjcQualifiedIds = 0;
for (unsigned i = 0, e = Types.size(); i != e; ++i) {
Type *T = Types[i];
@@ -83,6 +84,8 @@
++NumObjcInterfaces;
else if (isa<ObjcQualifiedInterfaceType>(T))
++NumObjcQualifiedInterfaces;
+ else if (isa<ObjcQualifiedIdType>(T))
+ ++NumObjcQualifiedIds;
else {
QualType(T, 0).dump();
assert(0 && "Unknown type!");
@@ -106,6 +109,8 @@
fprintf(stderr, " %d interface types\n", NumObjcInterfaces);
fprintf(stderr, " %d protocol qualified interface types\n",
NumObjcQualifiedInterfaces);
+ fprintf(stderr, " %d protocol qualified id types\n",
+ NumObjcQualifiedIds);
fprintf(stderr, "Total bytes = %d\n", int(NumBuiltin*sizeof(BuiltinType)+
NumPointer*sizeof(PointerType)+NumArray*sizeof(ArrayType)+
NumComplex*sizeof(ComplexType)+NumVector*sizeof(VectorType)+
@@ -677,7 +682,7 @@
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
QualType Canonical = Decl->getUnderlyingType().getCanonicalType();
- Decl->TypeForDecl = new TypedefType(Decl, Canonical);
+ Decl->TypeForDecl = new TypedefType(Type::TypeName, Decl, Canonical);
Types.push_back(Decl->TypeForDecl);
return QualType(Decl->TypeForDecl, 0);
}
@@ -713,6 +718,29 @@
return QualType(QType, 0);
}
+/// getObjcQualifiedIdType - Return a
+/// getObjcQualifiedIdType type for the given interface decl and
+/// the conforming protocol list.
+QualType ASTContext::getObjcQualifiedIdType(TypedefDecl *Decl,
+ ObjcProtocolDecl **Protocols,
+ unsigned NumProtocols) {
+ llvm::FoldingSetNodeID ID;
+ ObjcQualifiedIdType::Profile(ID, Protocols, NumProtocols);
+
+ void *InsertPos = 0;
+ if (ObjcQualifiedIdType *QT =
+ ObjcQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(QT, 0);
+
+ // No Match;
+ QualType Canonical = Decl->getUnderlyingType().getCanonicalType();
+ ObjcQualifiedIdType *QType =
+ new ObjcQualifiedIdType(Decl, Canonical, Protocols, NumProtocols);
+ Types.push_back(QType);
+ ObjcQualifiedIdTypes.InsertNode(QType, InsertPos);
+ return QualType(QType, 0);
+}
+
/// getTypeOfExpr - Unlike many "get<Type>" functions, we can't unique
/// TypeOfExpr AST's (since expression's are never shared). For example,
/// multiple declarations that refer to "typeof(x)" all contain different
@@ -1043,7 +1071,13 @@
}
S += encoding;
- } else if (const PointerType *PT = T->getAsPointerType()) {
+ }
+ else if (const ObjcQualifiedIdType *QIT = dyn_cast<ObjcQualifiedIdType>(T)) {
+ // Treat id<P...> same as 'id' for encoding purposes.
+ return getObjcEncodingForType(QIT->getDecl()->getUnderlyingType(), S);
+
+ }
+ else if (const PointerType *PT = T->getAsPointerType()) {
QualType PointeeTy = PT->getPointeeType();
if (isObjcIdType(PointeeTy) || PointeeTy->isObjcInterfaceType()) {
S += '@';
@@ -1221,6 +1255,13 @@
return true;
}
+// TODO: id<P1,...> vs. id<P,...>
+#if 0
+bool ASTContext::QualifiedIdTypesAreCompatible(QualType lhs,
+ QualType rhs) {
+}
+#endif
+
bool ASTContext::vectorTypesAreCompatible(QualType lhs, QualType rhs) {
const VectorType *lVector = lhs->getAsVectorType();
const VectorType *rVector = rhs->getAsVectorType();
diff --git a/AST/Type.cpp b/AST/Type.cpp
index b1da04b..63f3589 100644
--- a/AST/Type.cpp
+++ b/AST/Type.cpp
@@ -539,6 +539,17 @@
Profile(ID, &Protocols[0], getNumProtocols());
}
+void ObjcQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID,
+ ObjcProtocolDecl **protocols,
+ unsigned NumProtocols) {
+ for (unsigned i = 0; i != NumProtocols; i++)
+ ID.AddPointer(protocols[i]);
+}
+
+void ObjcQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, &Protocols[0], getNumProtocols());
+}
+
/// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
/// potentially looking through *all* consequtive typedefs. This returns the
/// sum of the type qualifiers, so if you have:
@@ -780,6 +791,22 @@
InnerString = ObjcQIString + InnerString;
}
+void ObjcQualifiedIdType::getAsStringInternal(
+ std::string &InnerString) const {
+ if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
+ InnerString = ' ' + InnerString;
+ std::string ObjcQIString = "id";
+ ObjcQIString += '<';
+ int num = getNumProtocols();
+ for (int i = 0; i < num; i++) {
+ ObjcQIString += getProtocols(i)->getName();
+ if (i < num-1)
+ ObjcQIString += ',';
+ }
+ ObjcQIString += '>';
+ InnerString = ObjcQIString + InnerString;
+}
+
void TagType::getAsStringInternal(std::string &InnerString) const {
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
InnerString = ' ' + InnerString;
diff --git a/AST/TypeSerialization.cpp b/AST/TypeSerialization.cpp
index 10965c2..a3b99ed 100644
--- a/AST/TypeSerialization.cpp
+++ b/AST/TypeSerialization.cpp
@@ -224,7 +224,7 @@
std::vector<Type*>& Types =
const_cast<std::vector<Type*>&>(Context.getTypes());
- TypedefType* T = new TypedefType(NULL,QualType::ReadVal(D));
+ TypedefType* T = new TypedefType(Type::TypeName, NULL,QualType::ReadVal(D));
Types.push_back(T);
D.ReadPtr(T->Decl); // May be backpatched.