This patch includes a conceptually simple, but very intrusive/pervasive change.
The idea is to segregate Objective-C "object" pointers from general C pointers (utilizing the recently added ObjCObjectPointerType). The fun starts in Sema::GetTypeForDeclarator(), where "SomeInterface *" is now represented by a single AST node (rather than a PointerType whose Pointee is an ObjCInterfaceType). Since a significant amount of code assumed ObjC object pointers where based on C pointers/structs, this patch is very tedious. It should also explain why it is hard to accomplish this in smaller, self-contained patches.
This patch does most of the "heavy lifting" related to moving from PointerType->ObjCObjectPointerType. It doesn't include all potential "cleanups". The good news is additional cleanups can be done later (some are noted in the code). This patch is so large that I didn't want to include any changes that are purely aesthetic.
By making the ObjC types truly built-in, they are much easier to work with (and require fewer "hacks"). For example, there is no need for ASTContext::isObjCIdStructType() or ASTContext::isObjCClassStructType()! We believe this change (and the follow-up cleanups) will pay dividends over time.
Given the amount of code change, I do expect some fallout from this change (though it does pass all of the clang tests). If you notice any problems, please let us know asap! Thanks.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75314 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 78c3b78..fd368c4 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -22,6 +22,9 @@
#include "llvm/Support/raw_ostream.h"
using namespace clang;
+ObjCInterfaceType *ObjCObjectPointerType::IdInterfaceT;
+ObjCInterfaceType *ObjCObjectPointerType::ClassInterfaceT;
+
bool QualType::isConstant(ASTContext &Ctx) const {
if (isConstQualified())
return true;
@@ -295,6 +298,15 @@
return dyn_cast_or_null<FunctionProtoType>(getAsFunctionType());
}
+QualType Type::getPointeeType() const {
+ if (const PointerType *PT = getAsPointerType())
+ return PT->getPointeeType();
+ if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType())
+ return OPT->getPointeeType();
+ if (const BlockPointerType *BPT = getAsBlockPointerType())
+ return BPT->getPointeeType();
+ return QualType();
+}
const PointerType *Type::getAsPointerType() const {
// If this is directly a pointer type, return it.
@@ -609,6 +621,14 @@
return 0;
}
+const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const {
+ if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+ if (OPT->getInterfaceType())
+ return OPT;
+ }
+ return 0;
+}
+
const TemplateTypeParmType *Type::getAsTemplateTypeParmType() const {
// There is no sugar for template type parameters, so just return
// the canonical type pointer if it is the right class.
@@ -1016,16 +1036,18 @@
}
void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID,
- const ObjCInterfaceDecl *Decl,
- ObjCProtocolDecl **protocols,
+ QualType OIT, ObjCProtocolDecl **protocols,
unsigned NumProtocols) {
- ID.AddPointer(Decl);
+ ID.AddPointer(OIT.getAsOpaquePtr());
for (unsigned i = 0; i != NumProtocols; i++)
ID.AddPointer(protocols[i]);
}
void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getDecl(), &Protocols[0], getNumProtocols());
+ if (getNumProtocols())
+ Profile(ID, getPointeeType(), &Protocols[0], getNumProtocols());
+ else
+ Profile(ID, getPointeeType(), 0, 0);
}
void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
@@ -1663,6 +1685,14 @@
InnerString = MyString + ' ' + InnerString;
}
+bool ObjCInterfaceType::isObjCIdInterface() const {
+ return this == ObjCObjectPointerType::getIdInterface();
+}
+
+bool ObjCInterfaceType::isObjCClassInterface() const {
+ return this == ObjCObjectPointerType::getClassInterface();
+}
+
void ObjCInterfaceType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
InnerString = ' ' + InnerString;
@@ -1671,15 +1701,7 @@
void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const {
- if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
- InnerString = ' ' + InnerString;
-
- std::string ObjCQIString;
-
- if (getDecl())
- ObjCQIString = getDecl()->getNameAsString();
- else
- ObjCQIString = "id";
+ std::string ObjCQIString = getInterfaceType()->getDecl()->getNameAsString();
if (!qual_empty()) {
ObjCQIString += '<';
@@ -1690,6 +1712,11 @@
}
ObjCQIString += '>';
}
+ if (!isObjCIdType() && !isObjCQualifiedIdType())
+ ObjCQIString += " *"; // Don't forget the implicit pointer.
+ else if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
+ InnerString = ' ' + InnerString;
+
InnerString = ObjCQIString + InnerString;
}