Implement the ObjC pseudo built-in types as clang "BuiltinType's". I say pseudo built-in types, since Sema still injects a typedef for recognition (i.e. they aren't truly built-ins from a parser perspective).
This removes the static data/methods on ObjCObjectPointerType while preserving the nice API (no need to fiddle with ASTContext:-).
This patch also adds Type::isObjCBuiltinType().
This should be the last fairly large patch related to recrafting the ObjC type system. The follow-on patches should be fairly small.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75808 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 13f35dc..fb28188 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -201,8 +201,13 @@
BuiltinVaListType = QualType();
- ObjCIdType = QualType();
- ObjCClassType = QualType();
+ // "Builtin" typedefs set by Sema::ActOnTranslationUnitScope().
+ ObjCIdTypedefType = QualType();
+ ObjCClassTypedefType = QualType();
+
+ // Builtin types for 'id' and 'Class'.
+ InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
+ InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
ObjCConstantStringType = QualType();
@@ -1868,7 +1873,7 @@
ObjCProtocolDecl **Protocols,
unsigned NumProtocols) {
if (InterfaceT.isNull())
- InterfaceT = QualType(ObjCObjectPointerType::getIdInterface(), 0);
+ InterfaceT = ObjCBuiltinIdTy;
// Sort the protocol list alphabetically to canonicalize it.
if (NumProtocols)
@@ -2471,7 +2476,7 @@
QualType FieldTypes[] = {
UnsignedLongTy,
- getPointerType(ObjCIdType),
+ getPointerType(ObjCIdTypedefType),
getPointerType(UnsignedLongTy),
getConstantArrayType(UnsignedLongTy,
llvm::APInt(32, 5), ArrayType::Normal, 0)
@@ -3018,13 +3023,7 @@
}
void ASTContext::setObjCIdType(QualType T) {
- ObjCIdType = T;
- const TypedefType *TT = T->getAsTypedefType();
- assert(TT && "missing 'id' typedef");
- const ObjCObjectPointerType *OPT =
- TT->getDecl()->getUnderlyingType()->getAsObjCObjectPointerType();
- assert(OPT && "missing 'id' type");
- ObjCObjectPointerType::setIdInterface(OPT->getPointeeType());
+ ObjCIdTypedefType = T;
}
void ASTContext::setObjCSelType(QualType T) {
@@ -3050,13 +3049,7 @@
}
void ASTContext::setObjCClassType(QualType T) {
- ObjCClassType = T;
- const TypedefType *TT = T->getAsTypedefType();
- assert(TT && "missing 'Class' typedef");
- const ObjCObjectPointerType *OPT =
- TT->getDecl()->getUnderlyingType()->getAsObjCObjectPointerType();
- assert(OPT && "missing 'Class' type");
- ObjCObjectPointerType::setClassInterface(OPT->getPointeeType());
+ ObjCClassTypedefType = T;
}
void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
@@ -3235,27 +3228,38 @@
/// FIXME: Move the following to ObjCObjectPointerType/ObjCInterfaceType.
bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT) {
- // If either interface represents the built-in 'id' or 'Class' types,
- // then return true (no need to call canAssignObjCInterfaces()).
- if (LHSOPT->isObjCIdType() || RHSOPT->isObjCIdType() ||
- LHSOPT->isObjCClassType() || RHSOPT->isObjCClassType())
+ // If either type represents the built-in 'id' or 'Class' types, return true.
+ if (LHSOPT->isObjCBuiltinType() || RHSOPT->isObjCBuiltinType())
return true;
const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
- if (!LHS || !RHS)
- return false;
+ if (!LHS || !RHS) {
+ // We have qualified builtin types.
+ // Both the right and left sides have qualifiers.
+ for (ObjCObjectPointerType::qual_iterator I = LHSOPT->qual_begin(),
+ E = LHSOPT->qual_end(); I != E; ++I) {
+ bool RHSImplementsProtocol = false;
+
+ // when comparing an id<P> on lhs with a static type on rhs,
+ // see if static class implements all of id's protocols, directly or
+ // through its super class and categories.
+ for (ObjCObjectPointerType::qual_iterator J = RHSOPT->qual_begin(),
+ E = RHSOPT->qual_end(); J != E; ++J) {
+ if ((*J)->lookupProtocolNamed((*I)->getIdentifier()))
+ RHSImplementsProtocol = true;
+ }
+ if (!RHSImplementsProtocol)
+ return false;
+ }
+ // The RHS implements all protocols listed on the LHS.
+ return true;
+ }
return canAssignObjCInterfaces(LHS, RHS);
}
bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
const ObjCInterfaceType *RHS) {
- // If either interface represents the built-in 'id' or 'Class' types,
- // then return true.
- if (LHS->isObjCIdInterface() || RHS->isObjCIdInterface() ||
- LHS->isObjCClassInterface() || RHS->isObjCClassInterface())
- return true;
-
// Verify that the base decls are compatible: the RHS must be a subclass of
// the LHS.
if (!LHS->getDecl()->isSuperClassOf(RHS->getDecl()))