diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index b957708e3ec3..c2cddb95f71c 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1039,8 +1039,17 @@ public: UndeducedAuto, // In C++0x, this represents the type of an auto variable // that has not been deduced yet. - ObjCId, // This represents the ObjC 'id' type. - ObjCClass, // This represents the ObjC 'Class' type. + + /// The primitive Objective C 'id' type. The type pointed to by the + /// user-visible 'id' type. Only ever shows up in an AST as the base + /// type of an ObjCObjectType. + ObjCId, + + /// The primitive Objective C 'Class' type. The type pointed to by the + /// user-visible 'Class' type. Only ever shows up in an AST as the + /// base type of an ObjCObjectType. + ObjCClass, + ObjCSel // This represents the ObjC 'SEL' type. }; private: @@ -2762,12 +2771,13 @@ public: /// /// 'C
' is an ObjCObjectType with base C and protocol list [P]. /// -/// 'id' is a TypedefType which is sugar for an ObjCPointerType with -/// base BuiltinType::ObjCIdType and no protocols. +/// 'id' is a TypedefType which is sugar for an ObjCPointerType whose +/// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType +/// and no protocols. /// -/// 'id
' is an ObjCPointerType with base BuiltinType::ObjCIdType -/// and protocol list [P]. Eventually this should get its own sugar -/// class to better represent the source. +/// 'id
' is an ObjCPointerType whose pointee is an ObjCObjecType
+/// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually
+/// this should get its own sugar class to better represent the source.
class ObjCObjectType : public Type {
// Pad the bit count up so that NumProtocols is 2-byte aligned
unsigned : BitsRemainingInType - 16;
@@ -2775,6 +2785,10 @@ class ObjCObjectType : public Type {
/// \brief The number of protocols stored after the
/// ObjCObjectPointerType node.
///
+ /// These protocols are those written directly on the type. If
+ /// protocol qualifiers ever become additive, the iterators will
+ /// get kindof complicated.
+ ///
/// In the canonical object type, these are sorted alphabetically
/// and uniqued.
unsigned NumProtocols : 16;
@@ -2799,6 +2813,12 @@ protected:
BaseType(QualType(this_(), 0)) {}
public:
+ /// getBaseType - Gets the base type of this object type. This is
+ /// always (possibly sugar for) one of:
+ /// - the 'id' builtin type (as opposed to the 'id' type visible to the
+ /// user, which is a typedef for an ObjCPointerType)
+ /// - the 'Class' builtin type (same caveat)
+ /// - an ObjCObjectType (currently always an ObjCInterfaceType)
QualType getBaseType() const { return BaseType; }
bool isObjCId() const {
@@ -2887,6 +2907,14 @@ inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() {
/// are two kinds of interface types, normal interfaces like "NSString" and
/// qualified interfaces, which are qualified with a protocol list like
/// "NSString ',
-/// and 'Interface *'.
+/// ObjCObjectPointerType - Used to represent a pointer to an
+/// Objective C object. These are constructed from pointer
+/// declarators when the pointee type is an ObjCObjectType (or sugar
+/// for one). In addition, the 'id' and 'Class' types are typedefs
+/// for these, and the protocol-qualified types 'id ' and 'Class '
+/// are translated into these.
///
-/// Duplicate protocols are removed and protocol list is canonicalized to be in
-/// alphabetical order.
+/// Pointers to pointers to Objective C objects are still PointerTypes;
+/// only the first level of pointer gets it own type implementation.
class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
- QualType PointeeType; // A builtin or interface type.
+ QualType PointeeType;
ObjCObjectPointerType(QualType Canonical, QualType Pointee)
: Type(ObjCObjectPointer, Canonical, false),
@@ -2943,43 +2976,80 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
public:
void Destroy(ASTContext& C);
- // Get the pointee type. Pointee will either be:
- // - a built-in type (for 'id' and 'Class').
- // - an interface type (for user-defined types).
- // - a TypedefType whose canonical type is an interface (as in 'T' below).
- // For example: typedef NSObject T; T *var;
+ /// getPointeeType - Gets the type pointed to by this ObjC pointer.
+ /// The result will always be an ObjCObjectType or sugar thereof.
QualType getPointeeType() const { return PointeeType; }
+ /// getObjCObjectType - Gets the type pointed to by this ObjC
+ /// pointer. This method always returns non-null.
+ ///
+ /// This method is equivalent to getPointeeType() except that
+ /// it discards any typedefs (or other sugar) between this
+ /// type and the "outermost" object type. So for:
+ /// @class A; @protocol P; @protocol Q;
+ /// typedef A AP;
+ /// typedef A A1;
+ /// typedef A1 A1P;
+ /// typedef A1P *', getObjectType() will return 'A '.
+ /// For 'AP*', getObjectType() will return 'A '.
+ /// For 'A1*', getObjectType() will return 'A'.
+ /// For 'A1 *', getObjectType() will return 'A1 '.
+ /// For 'A1P*', getObjectType() will return 'A1 '.
+ /// For 'A1PQ*', getObjectType() will return 'A1 ".
+ /// isObjCQualifiedIdType - True if this is equivalent to 'id ' for some
+ /// non-empty set of protocols.
bool isObjCQualifiedIdType() const {
return getObjectType()->isObjCQualifiedId();
}
- /// isObjCQualifiedClassType - true for "Class ".
+
+ /// isObjCQualifiedClassType - True if this is equivalent to 'Class ' for
+ /// some non-empty set of protocols.
bool isObjCQualifiedClassType() const {
return getObjectType()->isObjCQualifiedClass();
}
- /// qual_iterator and friends: this provides access to the (potentially empty)
- /// list of protocols qualifying this interface.
+
+ /// An iterator over the qualifiers on the object type. Provided
+ /// for convenience. This will always iterate over the full set of
+ /// protocols on a type, not just those provided directly.
typedef ObjCObjectType::qual_iterator qual_iterator;
qual_iterator qual_begin() const {
@@ -2990,13 +3060,14 @@ public:
}
bool qual_empty() const { return getObjectType()->qual_empty(); }
- /// getNumProtocols - Return the number of qualifying protocols in this
- /// interface type, or 0 if there are none.
+ /// getNumProtocols - Return the number of qualifying protocols on
+ /// the object type.
unsigned getNumProtocols() const {
return getObjectType()->getNumProtocols();
}
- /// \brief Retrieve the Ith protocol.
+ /// \brief Retrieve a qualifying protocol by index on the object
+ /// type.
ObjCProtocolDecl *getProtocol(unsigned I) const {
return getObjectType()->getProtocol(I);
}
@@ -3006,7 +3077,9 @@ public:
virtual Linkage getLinkage() const;
- void Profile(llvm::FoldingSetNodeID &ID);
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPointeeType());
+ }
static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
ID.AddPointer(T.getAsOpaquePtr());
}
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 5b484054b56a..ebaad9a0a8c8 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -952,10 +952,6 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) {
getExtInfo());
}
-void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getPointeeType());
-}
-
/// 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:
A1PQ;
+ /// For 'A*', getObjectType() will return 'A'.
+ /// For 'A
', because
+ /// adding protocols to a protocol-qualified base discards the
+ /// old qualifiers (for now). But if it didn't, getObjectType()
+ /// would return 'A1P
' (and we'd have to make iterating over
+ /// qualifiers more complicated).
const ObjCObjectType *getObjectType() const {
return PointeeType->getAs