From: John McCall Date: Sat, 15 May 2010 11:32:37 +0000 (+0000) Subject: Substantially alter the design of the Objective C type AST by introducing X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44e;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103870 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index a53d803ecd..d1646e00d6 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -98,7 +98,7 @@ class ASTContext { llvm::FoldingSet TemplateSpecializationTypes; llvm::FoldingSet ElaboratedTypes; llvm::FoldingSet DependentNameTypes; - llvm::FoldingSet ObjCInterfaceTypes; + llvm::FoldingSet ObjCObjectTypes; llvm::FoldingSet ObjCObjectPointerTypes; llvm::FoldingSet QualifiedTemplateNames; @@ -624,16 +624,15 @@ public: const TemplateSpecializationType *TemplateId, QualType Canon = QualType()); - QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, - ObjCProtocolDecl **Protocols = 0, - unsigned NumProtocols = 0); + QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl); - /// getObjCObjectPointerType - Return a ObjCObjectPointerType type for the - /// given interface decl and the conforming protocol list. - QualType getObjCObjectPointerType(QualType OIT, - ObjCProtocolDecl **ProtocolList = 0, - unsigned NumProtocols = 0, - unsigned Quals = 0); + QualType getObjCObjectType(QualType Base, + ObjCProtocolDecl * const *Protocols, + unsigned NumProtocols); + + /// getObjCObjectPointerType - Return a ObjCObjectPointerType type + /// for the given ObjCObjectType. + QualType getObjCObjectPointerType(QualType OIT); /// getTypeOfType - GCC extension. QualType getTypeOfExprType(Expr *e); @@ -1182,8 +1181,8 @@ public: // Check the safety of assignment from LHS to RHS bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); - bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS, - const ObjCInterfaceType *RHS); + bool canAssignObjCInterfaces(const ObjCObjectType *LHS, + const ObjCObjectType *RHS); bool canAssignObjCInterfacesInBlockPointer( const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 93dcad7512..4afb81dd05 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -642,6 +642,24 @@ struct CanProxyAdaptor LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getName) }; +template<> +struct CanProxyAdaptor + : public CanProxyBase { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *, + getInterface) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass) + + typedef ObjCObjectPointerType::qual_iterator qual_iterator; + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) +}; + template<> struct CanProxyAdaptor : public CanProxyBase { diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index a7a13409eb..36b151ddf3 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -623,6 +623,17 @@ case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS, S); template bool RecursiveASTVisitor::VisitObjCInterfaceType( ObjCInterfaceType *T) { + return getDerived().VisitObjCObjectType(T); + } + + template + bool RecursiveASTVisitor::VisitObjCObjectType(ObjCObjectType *T) { + // We have to watch out here because an ObjCInterfaceType's base + // type is itself. + if (T->getBaseType().getTypePtr() != T) + if (Visit(T->getBaseType())) + return true; + return getDerived().VisitType(T); } diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 49022a8a61..b957708e3e 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -755,6 +755,9 @@ public: }; private: + Type(const Type&); // DO NOT IMPLEMENT. + void operator=(const Type&); // DO NOT IMPLEMENT. + QualType CanonicalType; /// TypeClass bitfield - Enum that specifies what subclass this belongs to. @@ -765,9 +768,9 @@ private: /// subclasses can pack their bitfields into the same word. bool Dependent : 1; - Type(const Type&); // DO NOT IMPLEMENT. - void operator=(const Type&); // DO NOT IMPLEMENT. protected: + enum { BitsRemainingInType = 23 }; + // silence VC++ warning C4355: 'this' : used in base member initializer list Type *this_() { return this; } Type(TypeClass tc, QualType Canonical, bool dependent) @@ -879,7 +882,7 @@ public: bool isObjCObjectPointerType() const; // Pointer to *any* ObjC object. // FIXME: change this to 'raw' interface type, so we can used 'interface' type // for the common case. - bool isObjCInterfaceType() const; // NSString or NSString + bool isObjCObjectType() const; // NSString or typeof(*(id)0) bool isObjCQualifiedInterfaceType() const; // NSString bool isObjCQualifiedIdType() const; // id bool isObjCQualifiedClassType() const; // Class @@ -920,7 +923,7 @@ public: // for object declared using an interface. const ObjCObjectPointerType *getAsObjCInterfacePointerType() const; const ObjCObjectPointerType *getAsObjCQualifiedIdType() const; - const ObjCInterfaceType *getAsObjCQualifiedInterfaceType() const; + const ObjCObjectType *getAsObjCQualifiedInterfaceType() const; const CXXRecordDecl *getCXXRecordDeclForPointerType() const; /// \brief Retrieves the CXXRecordDecl that this type refers to, either @@ -935,10 +938,6 @@ public: // immediately following this class. template const T *getAs() const; - /// getAsPointerToObjCInterfaceType - If this is a pointer to an ObjC - /// interface, return the interface type, otherwise return null. - const ObjCInterfaceType *getAsPointerToObjCInterfaceType() const; - /// getArrayElementTypeNoTypeQual - If this is an array type, return the /// element type of the array, potentially with type qualifiers missing. /// This method should never be used when type qualifiers are meaningful. @@ -2750,65 +2749,184 @@ public: static bool classof(const DependentNameType *T) { return true; } }; -/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for -/// object oriented design. They basically correspond to C++ classes. There -/// are two kinds of interface types, normal interfaces like "NSString" and -/// qualified interfaces, which are qualified with a protocol list like -/// "NSString". -class ObjCInterfaceType : public Type, public llvm::FoldingSetNode { - ObjCInterfaceDecl *Decl; +/// ObjCObjectType - Represents a class type in Objective C. +/// Every Objective C type is a combination of a base type and a +/// list of protocols. +/// +/// Given the following declarations: +/// @class C; +/// @protocol P; +/// +/// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType +/// with base C and no protocols. +/// +/// '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 an ObjCPointerType 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; + + /// \brief The number of protocols stored after the + /// ObjCObjectPointerType node. + /// + /// In the canonical object type, these are sorted alphabetically + /// and uniqued. + unsigned NumProtocols : 16; - /// \brief The number of protocols stored after the ObjCInterfaceType node. - /// The list of protocols is sorted on protocol name. No protocol is enterred - /// more than once. - unsigned NumProtocols; + /// Either a BuiltinType or an InterfaceType or sugar for either. + QualType BaseType; + + ObjCProtocolDecl * const *getProtocolStorage() const { + return const_cast(this)->getProtocolStorage(); + } + + ObjCProtocolDecl **getProtocolStorage(); + +protected: + ObjCObjectType(QualType Canonical, QualType Base, + ObjCProtocolDecl * const *Protocols, unsigned NumProtocols); + + enum Nonce_ObjCInterface { Nonce_ObjCInterface }; + ObjCObjectType(enum Nonce_ObjCInterface) + : Type(ObjCInterface, QualType(), false), + NumProtocols(0), + BaseType(QualType(this_(), 0)) {} - ObjCInterfaceType(QualType Canonical, ObjCInterfaceDecl *D, - ObjCProtocolDecl **Protos, unsigned NumP); - friend class ASTContext; // ASTContext creates these. public: - void Destroy(ASTContext& C); + QualType getBaseType() const { return BaseType; } - ObjCInterfaceDecl *getDecl() const { return Decl; } + bool isObjCId() const { + return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCId); + } + bool isObjCClass() const { + return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCClass); + } + bool isObjCUnqualifiedId() const { return qual_empty() && isObjCId(); } + bool isObjCUnqualifiedClass() const { return qual_empty() && isObjCClass(); } + bool isObjCUnqualifiedIdOrClass() const { + if (!qual_empty()) return false; + if (const BuiltinType *T = getBaseType()->getAs()) + return T->getKind() == BuiltinType::ObjCId || + T->getKind() == BuiltinType::ObjCClass; + return false; + } + bool isObjCQualifiedId() const { return !qual_empty() && isObjCId(); } + bool isObjCQualifiedClass() const { return !qual_empty() && isObjCClass(); } + + /// Gets the interface declaration for this object type, if the base type + /// really is an interface. + ObjCInterfaceDecl *getInterface() const; + + typedef ObjCProtocolDecl * const *qual_iterator; + + qual_iterator qual_begin() const { return getProtocolStorage(); } + qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); } + + bool qual_empty() const { return getNumProtocols() == 0; } /// getNumProtocols - Return the number of qualifying protocols in this /// interface type, or 0 if there are none. unsigned getNumProtocols() const { return NumProtocols; } - /// \brief Retrieve the Ith protocol. + /// \brief Fetch a protocol by index. ObjCProtocolDecl *getProtocol(unsigned I) const { assert(I < getNumProtocols() && "Out-of-range protocol access"); return qual_begin()[I]; } - /// qual_iterator and friends: this provides access to the (potentially empty) - /// list of protocols qualifying this interface. - typedef ObjCProtocolDecl* const * qual_iterator; - qual_iterator qual_begin() const { - return reinterpret_cast(this + 1); - } - qual_iterator qual_end() const { - return qual_begin() + NumProtocols; - } - bool qual_empty() const { return NumProtocols == 0; } - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + Linkage getLinkage() const; // key function + + static bool classof(const Type *T) { + return T->getTypeClass() == ObjCObject || + T->getTypeClass() == ObjCInterface; + } + static bool classof(const ObjCObjectType *) { return true; } +}; + +/// ObjCObjectTypeImpl - A class providing a concrete implementation +/// of ObjCObjectType, so as to not increase the footprint of +/// ObjCInterfaceType. Code outside of ASTContext and the core type +/// system should not reference this type. +class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode { + friend class ASTContext; + + // If anyone adds fields here, ObjCObjectType::getProtocolStorage() + // will need to be modified. + + ObjCObjectTypeImpl(QualType Canonical, QualType Base, + ObjCProtocolDecl * const *Protocols, + unsigned NumProtocols) + : ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {} + +public: + void Destroy(ASTContext& C); // key function + void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, - const ObjCInterfaceDecl *Decl, - ObjCProtocolDecl * const *protocols, - unsigned NumProtocols); + QualType Base, + ObjCProtocolDecl *const *protocols, + unsigned NumProtocols); +}; - virtual Linkage getLinkage() const; +inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() { + return reinterpret_cast( + static_cast(this) + 1); +} + +/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for +/// object oriented design. They basically correspond to C++ classes. There +/// are two kinds of interface types, normal interfaces like "NSString" and +/// qualified interfaces, which are qualified with a protocol list like +/// "NSString". +class ObjCInterfaceType : public ObjCObjectType { + ObjCInterfaceDecl *Decl; + + ObjCInterfaceType(const ObjCInterfaceDecl *D) + : ObjCObjectType(Nonce_ObjCInterface), + Decl(const_cast(D)) {} + friend class ASTContext; // ASTContext creates these. +public: + void Destroy(ASTContext& C); // key function + + ObjCInterfaceDecl *getDecl() const { return Decl; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } static bool classof(const Type *T) { return T->getTypeClass() == ObjCInterface; } static bool classof(const ObjCInterfaceType *) { return true; } + + // Nonsense to "hide" certain members of ObjCObjectType within this + // class. People asking for protocols on an ObjCInterfaceType are + // not going to get what they want: ObjCInterfaceTypes are + // guaranteed to have no protocols. + enum { + qual_iterator, + qual_begin, + qual_end, + getNumProtocols, + getProtocol + }; }; +inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { + if (const ObjCInterfaceType *T = + getBaseType()->getAs()) + return T->getDecl(); + return 0; +} + /// ObjCObjectPointerType - Used to represent 'id', 'Interface *', 'id

', /// and 'Interface

*'. /// @@ -2817,15 +2935,9 @@ public: class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { QualType PointeeType; // A builtin or interface type. - /// \brief The number of protocols stored after the ObjCObjectPointerType - /// node. - /// - /// The list of protocols is sorted on protocol name. No protocol is enterred - /// more than once. - unsigned NumProtocols; - - ObjCObjectPointerType(QualType Canonical, QualType T, - ObjCProtocolDecl **Protos, unsigned NumP); + ObjCObjectPointerType(QualType Canonical, QualType Pointee) + : Type(ObjCObjectPointer, Canonical, false), + PointeeType(Pointee) {} friend class ASTContext; // ASTContext creates these. public: @@ -2838,8 +2950,12 @@ public: // For example: typedef NSObject T; T *var; QualType getPointeeType() const { return PointeeType; } + const ObjCObjectType *getObjectType() const { + return PointeeType->getAs(); + } + const ObjCInterfaceType *getInterfaceType() const { - return PointeeType->getAs(); + return getObjectType()->getBaseType()->getAs(); } /// getInterfaceDecl - returns an interface decl for user-defined types. ObjCInterfaceDecl *getInterfaceDecl() const { @@ -2847,45 +2963,42 @@ public: } /// isObjCIdType - true for "id". bool isObjCIdType() const { - return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && - !NumProtocols; + return getObjectType()->isObjCUnqualifiedId(); } /// isObjCClassType - true for "Class". bool isObjCClassType() const { - return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) && - !NumProtocols; + return getObjectType()->isObjCUnqualifiedClass(); } /// isObjCQualifiedIdType - true for "id

". bool isObjCQualifiedIdType() const { - return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && - NumProtocols; + return getObjectType()->isObjCQualifiedId(); } /// isObjCQualifiedClassType - true for "Class

". bool isObjCQualifiedClassType() const { - return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) && - NumProtocols; + return getObjectType()->isObjCQualifiedClass(); } /// qual_iterator and friends: this provides access to the (potentially empty) /// list of protocols qualifying this interface. - typedef ObjCProtocolDecl* const * qual_iterator; + typedef ObjCObjectType::qual_iterator qual_iterator; qual_iterator qual_begin() const { - return reinterpret_cast (this + 1); + return getObjectType()->qual_begin(); } - qual_iterator qual_end() const { - return qual_begin() + NumProtocols; + qual_iterator qual_end() const { + return getObjectType()->qual_end(); } - bool qual_empty() const { return NumProtocols == 0; } + 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. - unsigned getNumProtocols() const { return NumProtocols; } + unsigned getNumProtocols() const { + return getObjectType()->getNumProtocols(); + } /// \brief Retrieve the Ith protocol. ObjCProtocolDecl *getProtocol(unsigned I) const { - assert(I < getNumProtocols() && "Out-of-range protocol access"); - return qual_begin()[I]; + return getObjectType()->getProtocol(I); } bool isSugared() const { return false; } @@ -2894,9 +3007,9 @@ public: virtual Linkage getLinkage() const; void Profile(llvm::FoldingSetNodeID &ID); - static void Profile(llvm::FoldingSetNodeID &ID, QualType T, - ObjCProtocolDecl *const *protocols, - unsigned NumProtocols); + static void Profile(llvm::FoldingSetNodeID &ID, QualType T) { + ID.AddPointer(T.getAsOpaquePtr()); + } static bool classof(const Type *T) { return T->getTypeClass() == ObjCObjectPointer; } @@ -3135,12 +3248,6 @@ inline QualType QualType::getNonReferenceType() const { return *this; } -inline const ObjCInterfaceType *Type::getAsPointerToObjCInterfaceType() const { - if (const PointerType *PT = getAs()) - return PT->getPointeeType()->getAs(); - return 0; -} - inline bool Type::isFunctionType() const { return isa(CanonicalType); } @@ -3207,8 +3314,8 @@ inline bool Type::isExtVectorType() const { inline bool Type::isObjCObjectPointerType() const { return isa(CanonicalType); } -inline bool Type::isObjCInterfaceType() const { - return isa(CanonicalType); +inline bool Type::isObjCObjectType() const { + return isa(CanonicalType); } inline bool Type::isObjCQualifiedIdType() const { if (const ObjCObjectPointerType *OPT = getAs()) @@ -3257,13 +3364,11 @@ inline bool Type::isOverloadableType() const { inline bool Type::hasPointerRepresentation() const { return (isPointerType() || isReferenceType() || isBlockPointerType() || - isObjCInterfaceType() || isObjCObjectPointerType() || - isObjCQualifiedInterfaceType() || isNullPtrType()); + isObjCObjectPointerType() || isNullPtrType()); } inline bool Type::hasObjCPointerRepresentation() const { - return (isObjCInterfaceType() || isObjCObjectPointerType() || - isObjCQualifiedInterfaceType()); + return isObjCObjectPointerType(); } /// Insertion operator for diagnostics. This allows sending QualType's into a diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 9927ae7edb..4896fe948b 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -559,6 +559,7 @@ class SubstTemplateTypeParmTypeLoc : struct ObjCProtocolListLocInfo { SourceLocation LAngleLoc; SourceLocation RAngleLoc; + bool HasBaseType; }; // A helper class for defining ObjC TypeLocs that can qualified with @@ -566,24 +567,15 @@ struct ObjCProtocolListLocInfo { // // TypeClass basically has to be either ObjCInterfaceType or // ObjCObjectPointerType. -template -class ObjCProtocolListTypeLoc : public ConcreteTypeLoc { +class ObjCObjectTypeLoc : public ConcreteTypeLoc { // SourceLocations are stored after Info, one for each Protocol. SourceLocation *getProtocolLocArray() const { return (SourceLocation*) this->getExtraLocalData(); } -protected: - void initializeLocalBase(SourceLocation Loc) { - setLAngleLoc(Loc); - setRAngleLoc(Loc); - for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) - setProtocolLoc(i, Loc); - } - public: SourceLocation getLAngleLoc() const { return this->getLocalData()->LAngleLoc; @@ -617,29 +609,48 @@ public: return *(this->getTypePtr()->qual_begin() + i); } + bool hasBaseTypeAsWritten() const { + return getLocalData()->HasBaseType; + } + + void setHasBaseTypeAsWritten(bool HasBaseType) { + getLocalData()->HasBaseType = HasBaseType; + } + + TypeLoc getBaseLoc() const { + return getInnerTypeLoc(); + } + SourceRange getSourceRange() const { return SourceRange(getLAngleLoc(), getRAngleLoc()); } void initializeLocal(SourceLocation Loc) { - initializeLocalBase(Loc); + setLAngleLoc(Loc); + setRAngleLoc(Loc); + for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) + setProtocolLoc(i, Loc); } unsigned getExtraLocalDataSize() const { return this->getNumProtocols() * sizeof(SourceLocation); } + + QualType getInnerType() const { + return getTypePtr()->getBaseType(); + } }; -struct ObjCInterfaceLocInfo : ObjCProtocolListLocInfo { +struct ObjCInterfaceLocInfo { SourceLocation NameLoc; }; /// \brief Wrapper for source info for ObjC interfaces. -class ObjCInterfaceTypeLoc : - public ObjCProtocolListTypeLoc { +class ObjCInterfaceTypeLoc : public ConcreteTypeLoc { public: ObjCInterfaceDecl *getIFaceDecl() const { return getTypePtr()->getDecl(); @@ -654,84 +665,15 @@ public: } SourceRange getSourceRange() const { - if (getNumProtocols()) - return SourceRange(getNameLoc(), getRAngleLoc()); - else - return SourceRange(getNameLoc(), getNameLoc()); + return SourceRange(getNameLoc()); } void initializeLocal(SourceLocation Loc) { - initializeLocalBase(Loc); setNameLoc(Loc); } }; -struct ObjCObjectPointerLocInfo : ObjCProtocolListLocInfo { - SourceLocation StarLoc; - bool HasProtocols; - bool HasBaseType; -}; - -/// Wraps an ObjCPointerType with source location information. Note -/// that not all ObjCPointerTypes actually have a star location; nor -/// are protocol locations necessarily written in the source just -/// because they're present on the type. -class ObjCObjectPointerTypeLoc : - public ObjCProtocolListTypeLoc { -public: - bool hasProtocolsAsWritten() const { - return getLocalData()->HasProtocols; - } - - void setHasProtocolsAsWritten(bool HasProtocols) { - getLocalData()->HasProtocols = HasProtocols; - } - - bool hasBaseTypeAsWritten() const { - return getLocalData()->HasBaseType; - } - - void setHasBaseTypeAsWritten(bool HasBaseType) { - getLocalData()->HasBaseType = HasBaseType; - } - - SourceLocation getStarLoc() const { - return getLocalData()->StarLoc; - } - - void setStarLoc(SourceLocation Loc) { - getLocalData()->StarLoc = Loc; - } - - SourceRange getSourceRange() const { - // Being written with protocols is incompatible with being written - // with a star. - if (hasProtocolsAsWritten()) - return SourceRange(getLAngleLoc(), getRAngleLoc()); - else - return SourceRange(getStarLoc(), getStarLoc()); - } - - void initializeLocal(SourceLocation Loc) { - initializeLocalBase(Loc); - setHasProtocolsAsWritten(false); - setHasBaseTypeAsWritten(false); - setStarLoc(Loc); - } - - TypeLoc getBaseTypeLoc() const { - return getInnerTypeLoc(); - } - - QualType getInnerType() const { - return getTypePtr()->getPointeeType(); - } -}; - - struct PointerLikeLocInfo { SourceLocation StarLoc; }; @@ -804,6 +746,20 @@ public: } }; +/// Wraps an ObjCPointerType with source location information. +class ObjCObjectPointerTypeLoc : + public PointerLikeTypeLoc { +public: + SourceLocation getStarLoc() const { + return getSigilLoc(); + } + + void setStarLoc(SourceLocation Loc) { + setSigilLoc(Loc); + } +}; + class ReferenceTypeLoc : public PointerLikeTypeLoc { diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h index c3b1c68b1f..e729488e43 100644 --- a/include/clang/AST/TypeLocBuilder.h +++ b/include/clang/AST/TypeLocBuilder.h @@ -59,6 +59,20 @@ class TypeLocBuilder { grow(Requested); } + /// Pushes a copy of the given TypeLoc onto this builder. The builder + /// must be empty for this to work. + void pushFullCopy(TypeLoc L) { +#ifndef NDEBUG + assert(LastTy.isNull() && "pushing copy on non-empty TypeLocBuilder"); + LastTy = L.getNextTypeLoc().getType(); +#endif + assert(Index == Capacity && "pushing copy on non-empty TypeLocBuilder"); + + unsigned Size = L.getFullDataSize(); + TypeLoc Copy = pushImpl(L.getType(), Size); + memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size); + } + /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs /// previously retrieved from this builder. TypeSpecTypeLoc pushTypeSpec(QualType T) { diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index ca27a2b949..02508af67d 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -92,7 +92,8 @@ NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) DEPENDENT_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(DependentName, Type) -TYPE(ObjCInterface, Type) +TYPE(ObjCObject, Type) +TYPE(ObjCInterface, ObjCObjectType) TYPE(ObjCObjectPointer, Type) #ifdef LAST_TYPE diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 4fed2e26cf..2493cfd47d 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -415,7 +415,9 @@ namespace clang { /// \brief An UnresolvedUsingType record. TYPE_UNRESOLVED_USING = 26, /// \brief An InjectedClassNameType record. - TYPE_INJECTED_CLASS_NAME = 27 + TYPE_INJECTED_CLASS_NAME = 27, + /// \brief An ObjCObjectType record. + TYPE_OBJC_OBJECT = 28 }; /// \brief The type IDs for special types constructed by semantic diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 81b56add8e..d0e4c02b91 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -595,6 +595,8 @@ ASTContext::getTypeInfo(const Type *T) { Align = EltInfo.second; break; } + case Type::ObjCObject: + return getTypeInfo(cast(T)->getBaseType().getTypePtr()); case Type::ObjCInterface: { const ObjCInterfaceType *ObjCI = cast(T); const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl()); @@ -1692,10 +1694,6 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) { if (const TypedefDecl *Typedef = dyn_cast(Decl)) return getTypedefType(Typedef); - if (const ObjCInterfaceDecl *ObjCInterface - = dyn_cast(Decl)) - return getObjCInterfaceType(ObjCInterface); - assert(!isa(Decl) && "Template type parameter types are always available."); @@ -1991,7 +1989,7 @@ static bool CmpProtocolNames(const ObjCProtocolDecl *LHS, return LHS->getDeclName() < RHS->getDeclName(); } -static bool areSortedAndUniqued(ObjCProtocolDecl **Protocols, +static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols, unsigned NumProtocols) { if (NumProtocols == 0) return true; @@ -2013,96 +2011,98 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols, 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) { - llvm::FoldingSetNodeID ID; - ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols); - Qualifiers Qs = Qualifiers::fromCVRMask(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(BaseType)) + return BaseType; + // Look in the folding set for an existing type. + llvm::FoldingSetNodeID ID; + 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 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. - ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos); + ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos); } - // No match. - unsigned Size = sizeof(ObjCObjectPointerType) - + NumProtocols * sizeof(ObjCProtocolDecl *); + unsigned Size = sizeof(ObjCObjectTypeImpl); + Size += NumProtocols * sizeof(ObjCProtocolDecl *); void *Mem = Allocate(Size, TypeAlignment); - ObjCObjectPointerType *QType = new (Mem) ObjCObjectPointerType(Canonical, - InterfaceT, - Protocols, - NumProtocols); + ObjCObjectTypeImpl *T = + new (Mem) ObjCObjectTypeImpl(Canonical, BaseType, Protocols, NumProtocols); - Types.push_back(QType); - ObjCObjectPointerTypes.InsertNode(QType, InsertPos); - return getQualifiedType(QualType(QType, 0), Qs); + Types.push_back(T); + ObjCObjectTypes.InsertNode(T, InsertPos); + return QualType(T, 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) { +/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for +/// the given object type. +QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) { llvm::FoldingSetNodeID ID; - ObjCInterfaceType::Profile(ID, Decl, Protocols, NumProtocols); + ObjCObjectPointerType::Profile(ID, ObjectT); void *InsertPos = 0; - if (ObjCInterfaceType *QT = - ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos)) + if (ObjCObjectPointerType *QT = + ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(QT, 0); - // Sort the protocol list alphabetically to canonicalize it. + // Find the canonical object type. QualType Canonical; - if (NumProtocols && !areSortedAndUniqued(Protocols, NumProtocols)) { - llvm::SmallVector Sorted(Protocols, - Protocols + NumProtocols); - - unsigned UniqueCount = NumProtocols; - SortAndUniqueProtocols(&Sorted[0], UniqueCount); - - Canonical = getObjCInterfaceType(Decl, &Sorted[0], UniqueCount); + if (!ObjectT.isCanonical()) { + Canonical = getObjCObjectPointerType(getCanonicalType(ObjectT)); - ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos); + // Regenerate InsertPos. + ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos); } - unsigned Size = sizeof(ObjCInterfaceType) - + NumProtocols * sizeof(ObjCProtocolDecl *); - void *Mem = Allocate(Size, TypeAlignment); - ObjCInterfaceType *QType = new (Mem) ObjCInterfaceType(Canonical, - const_cast(Decl), - Protocols, - NumProtocols); + // No match. + void *Mem = Allocate(sizeof(ObjCObjectPointerType), TypeAlignment); + ObjCObjectPointerType *QType = + new (Mem) ObjCObjectPointerType(Canonical, ObjectT); Types.push_back(QType); - ObjCInterfaceTypes.InsertNode(QType, InsertPos); + ObjCObjectPointerTypes.InsertNode(QType, InsertPos); 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) { + if (Decl->TypeForDecl) + return QualType(Decl->TypeForDecl, 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" functions, we can't unique /// TypeOfExprType AST's (since expression's are never shared). For example, /// multiple declarations that refer to "typeof(x)" all contain different @@ -3620,6 +3620,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } + // Ignore protocol qualifiers when mangling at this level. + if (const ObjCObjectType *OT = T->getAs()) + T = OT->getBaseType(); + if (const ObjCInterfaceType *OIT = T->getAs()) { // @encode(class_name) ObjCInterfaceDecl *OI = OIT->getDecl(); @@ -4090,18 +4094,21 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, /// 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 @@ void getIntersectionOfProtocols(ASTContext &Context, const ObjCObjectPointerType *RHSOPT, llvm::SmallVectorImpl &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 InheritedProtocolSet; unsigned LHSNumProtocols = LHS->getNumProtocols(); @@ -4161,7 +4170,8 @@ void getIntersectionOfProtocols(ASTContext &Context, InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end()); else { llvm::SmallPtrSet LHSInheritedProtocols; - Context.CollectInheritedProtocols(LHS->getDecl(), LHSInheritedProtocols); + Context.CollectInheritedProtocols(LHS->getInterface(), + LHSInheritedProtocols); InheritedProtocolSet.insert(LHSInheritedProtocols.begin(), LHSInheritedProtocols.end()); } @@ -4176,7 +4186,8 @@ void getIntersectionOfProtocols(ASTContext &Context, } else { llvm::SmallPtrSet RHSInheritedProtocols; - Context.CollectInheritedProtocols(RHS->getDecl(), RHSInheritedProtocols); + Context.CollectInheritedProtocols(RHS->getInterface(), + RHSInheritedProtocols); for (llvm::SmallPtrSet::iterator I = RHSInheritedProtocols.begin(), E = RHSInheritedProtocols.end(); I != E; ++I) @@ -4190,37 +4201,40 @@ void getIntersectionOfProtocols(ASTContext &Context, /// 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(); + while ((LDecl = LDecl->getSuperClass())) { + LHS = cast(getObjCInterfaceType(LDecl)); if (canAssignObjCInterfaces(LHS, RHS)) { - llvm::SmallVector IntersectionOfProtocols; - getIntersectionOfProtocols(*this, - LHSOPT, RHSOPT, IntersectionOfProtocols); - if (IntersectionOfProtocols.empty()) - LHSTy = getObjCObjectPointerType(LHSTy); - else - LHSTy = getObjCObjectPointerType(LHSTy, &IntersectionOfProtocols[0], - IntersectionOfProtocols.size()); - return LHSTy; + llvm::SmallVector 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 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS, 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 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, 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 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, 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 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, RHSCan->getAs())) 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(); - const ObjCInterfaceType* RHSIface = RHS->getAs(); - if (LHSIface && RHSIface && - canAssignObjCInterfaces(LHSIface, RHSIface)) + const ObjCObjectType* LHSIface = LHS->getAs(); + const ObjCObjectType* RHSIface = RHS->getAs(); + if (canAssignObjCInterfaces(LHSIface, RHSIface)) return LHS; return QualType(); diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index aae02a48cd..9d756950fa 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -74,6 +74,7 @@ namespace { QualType VisitElaboratedType(ElaboratedType *T); // FIXME: DependentNameType QualType VisitObjCInterfaceType(ObjCInterfaceType *T); + QualType VisitObjCObjectType(ObjCObjectType *T); QualType VisitObjCObjectPointerType(ObjCObjectPointerType *T); // Importing declarations @@ -632,12 +633,22 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, Iface1->getDecl(), Iface2->getDecl())) return false; - if (Iface1->getNumProtocols() != Iface2->getNumProtocols()) + break; + } + + case Type::ObjCObject: { + const ObjCObjectType *Obj1 = cast(T1); + const ObjCObjectType *Obj2 = cast(T2); + if (!IsStructurallyEquivalent(Context, + Obj1->getBaseType(), + Obj2->getBaseType())) + return false; + if (Obj1->getNumProtocols() != Obj2->getNumProtocols()) return false; - for (unsigned I = 0, N = Iface1->getNumProtocols(); I != N; ++I) { + for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) { if (!IsStructurallyEquivalent(Context, - Iface1->getProtocol(I), - Iface2->getProtocol(I))) + Obj1->getProtocol(I), + Obj2->getProtocol(I))) return false; } break; @@ -650,14 +661,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Ptr1->getPointeeType(), Ptr2->getPointeeType())) return false; - if (Ptr1->getNumProtocols() != Ptr2->getNumProtocols()) - return false; - for (unsigned I = 0, N = Ptr1->getNumProtocols(); I != N; ++I) { - if (!IsStructurallyEquivalent(Context, - Ptr1->getProtocol(I), - Ptr2->getProtocol(I))) - return false; - } break; } @@ -1305,8 +1308,16 @@ QualType ASTNodeImporter::VisitObjCInterfaceType(ObjCInterfaceType *T) { if (!Class) return QualType(); + return Importer.getToContext().getObjCInterfaceType(Class); +} + +QualType ASTNodeImporter::VisitObjCObjectType(ObjCObjectType *T) { + QualType ToBaseType = Importer.Import(T->getBaseType()); + if (ToBaseType.isNull()) + return QualType(); + llvm::SmallVector Protocols; - for (ObjCInterfaceType::qual_iterator P = T->qual_begin(), + for (ObjCObjectType::qual_iterator P = T->qual_begin(), PEnd = T->qual_end(); P != PEnd; ++P) { ObjCProtocolDecl *Protocol @@ -1316,9 +1327,9 @@ QualType ASTNodeImporter::VisitObjCInterfaceType(ObjCInterfaceType *T) { Protocols.push_back(Protocol); } - return Importer.getToContext().getObjCInterfaceType(Class, - Protocols.data(), - Protocols.size()); + return Importer.getToContext().getObjCObjectType(ToBaseType, + Protocols.data(), + Protocols.size()); } QualType ASTNodeImporter::VisitObjCObjectPointerType(ObjCObjectPointerType *T) { @@ -1326,20 +1337,7 @@ QualType ASTNodeImporter::VisitObjCObjectPointerType(ObjCObjectPointerType *T) { if (ToPointeeType.isNull()) return QualType(); - llvm::SmallVector Protocols; - for (ObjCObjectPointerType::qual_iterator P = T->qual_begin(), - PEnd = T->qual_end(); - P != PEnd; ++P) { - ObjCProtocolDecl *Protocol - = dyn_cast_or_null(Importer.Import(*P)); - if (!Protocol) - return QualType(); - Protocols.push_back(Protocol); - } - - return Importer.getToContext().getObjCObjectPointerType(ToPointeeType, - Protocols.data(), - Protocols.size()); + return Importer.getToContext().getObjCObjectPointerType(ToPointeeType); } //---------------------------------------------------------------------------- diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 39643eebcb..c38cec32c3 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2080,9 +2080,9 @@ ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const { break; case Class: - if (const ObjCInterfaceType *Iface - = getClassReceiver()->getAs()) - return Iface->getDecl(); + if (const ObjCObjectType *Ty + = getClassReceiver()->getAs()) + return Ty->getInterface(); break; case SuperInstance: diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index a5c3a209c8..5b484054b5 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -345,29 +345,36 @@ const RecordType *Type::getAsUnionType() const { return 0; } -ObjCInterfaceType::ObjCInterfaceType(QualType Canonical, - ObjCInterfaceDecl *D, - ObjCProtocolDecl **Protos, unsigned NumP) : - Type(ObjCInterface, Canonical, /*Dependent=*/false), - Decl(D), NumProtocols(NumP) -{ +void ObjCInterfaceType::Destroy(ASTContext& C) { + this->~ObjCInterfaceType(); + C.Deallocate(this); +} + +ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, + ObjCProtocolDecl * const *Protocols, + unsigned NumProtocols) + : Type(ObjCObject, Canonical, false), + NumProtocols(NumProtocols), + BaseType(Base) { + assert(this->NumProtocols == NumProtocols && + "bitfield overflow in protocol count"); if (NumProtocols) - memcpy(reinterpret_cast(this + 1), Protos, - NumProtocols * sizeof(*Protos)); + memcpy(getProtocolStorage(), Protocols, + NumProtocols * sizeof(ObjCProtocolDecl*)); } -void ObjCInterfaceType::Destroy(ASTContext& C) { - this->~ObjCInterfaceType(); +void ObjCObjectTypeImpl::Destroy(ASTContext& C) { + this->~ObjCObjectTypeImpl(); C.Deallocate(this); } -const ObjCInterfaceType *Type::getAsObjCQualifiedInterfaceType() const { - // There is no sugar for ObjCInterfaceType's, just return the canonical +const ObjCObjectType *Type::getAsObjCQualifiedInterfaceType() const { + // There is no sugar for ObjCObjectType's, just return the canonical // type pointer if it is the right class. There is no typedef information to // return and these cannot be Address-space qualified. - if (const ObjCInterfaceType *OIT = getAs()) - if (OIT->getNumProtocols()) - return OIT; + if (const ObjCObjectType *T = getAs()) + if (T->getNumProtocols() && T->getInterface()) + return T; return 0; } @@ -375,17 +382,6 @@ bool Type::isObjCQualifiedInterfaceType() const { return getAsObjCQualifiedInterfaceType() != 0; } -ObjCObjectPointerType::ObjCObjectPointerType(QualType Canonical, QualType T, - ObjCProtocolDecl **Protos, - unsigned NumP) : - Type(ObjCObjectPointer, Canonical, /*Dependent=*/false), - PointeeType(T), NumProtocols(NumP) -{ - if (NumProtocols) - memcpy(reinterpret_cast(this + 1), Protos, - NumProtocols * sizeof(*Protos)); -} - void ObjCObjectPointerType::Destroy(ASTContext& C) { this->~ObjCObjectPointerType(); C.Deallocate(this); @@ -638,6 +634,8 @@ bool Type::isIncompleteType() const { case IncompleteArray: // An array of unknown size is an incomplete type (C99 6.2.5p22). return true; + case ObjCObject: + return cast(this)->getBaseType()->isIncompleteType(); case ObjCInterface: // ObjC interfaces are incomplete if they are @class, not @interface. return cast(this)->getDecl()->isForwardDecl(); @@ -768,7 +766,8 @@ bool Type::isSpecifierType() const { case Elaborated: case DependentName: case ObjCInterface: - case ObjCObjectPointer: + case ObjCObject: + case ObjCObjectPointer: // FIXME: object pointers aren't really specifiers return true; default: return false; @@ -953,17 +952,8 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) { getExtInfo()); } -void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID, - QualType OIT, - ObjCProtocolDecl * const *protocols, - unsigned NumProtocols) { - ID.AddPointer(OIT.getAsOpaquePtr()); - for (unsigned i = 0; i != NumProtocols; i++) - ID.AddPointer(protocols[i]); -} - void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getPointeeType(), qual_begin(), getNumProtocols()); + Profile(ID, getPointeeType()); } /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to @@ -1163,17 +1153,17 @@ QualType QualifierCollector::apply(const Type *T) const { return Context->getQualifiedType(T, *this); } -void ObjCInterfaceType::Profile(llvm::FoldingSetNodeID &ID, - const ObjCInterfaceDecl *Decl, - ObjCProtocolDecl * const *protocols, - unsigned NumProtocols) { - ID.AddPointer(Decl); +void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID, + QualType BaseType, + ObjCProtocolDecl * const *Protocols, + unsigned NumProtocols) { + ID.AddPointer(BaseType.getAsOpaquePtr()); for (unsigned i = 0; i != NumProtocols; i++) - ID.AddPointer(protocols[i]); + ID.AddPointer(Protocols[i]); } -void ObjCInterfaceType::Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getDecl(), qual_begin(), getNumProtocols()); +void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getBaseType(), qual_begin(), getNumProtocols()); } Linkage Type::getLinkage() const { @@ -1244,7 +1234,7 @@ Linkage FunctionProtoType::getLinkage() const { return L; } -Linkage ObjCInterfaceType::getLinkage() const { +Linkage ObjCObjectType::getLinkage() const { return ExternalLinkage; } diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 0478d4e39c..ad5b91aac5 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -596,25 +596,37 @@ void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T, std::string &S) { if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. S = ' ' + S; - + std::string ObjCQIString = T->getDecl()->getNameAsString(); - if (T->getNumProtocols()) { - ObjCQIString += '<'; - bool isFirst = true; - for (ObjCInterfaceType::qual_iterator I = T->qual_begin(), - E = T->qual_end(); - I != E; ++I) { - if (isFirst) - isFirst = false; - else - ObjCQIString += ','; - ObjCQIString += (*I)->getNameAsString(); - } - ObjCQIString += '>'; - } S = ObjCQIString + S; } +void TypePrinter::PrintObjCObject(const ObjCObjectType *T, + std::string &S) { + if (T->qual_empty()) + return Print(T->getBaseType(), S); + + std::string tmp; + Print(T->getBaseType(), tmp); + tmp += '<'; + bool isFirst = true; + for (ObjCObjectType::qual_iterator + I = T->qual_begin(), E = T->qual_end(); I != E; ++I) { + if (isFirst) + isFirst = false; + else + tmp += ','; + tmp += (*I)->getNameAsString(); + } + tmp += '>'; + + if (!S.empty()) { + tmp += ' '; + tmp += S; + } + std::swap(tmp, S); +} + void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T, std::string &S) { std::string ObjCQIString; diff --git a/lib/Checker/CFRefCount.cpp b/lib/Checker/CFRefCount.cpp index d26ee1db56..3bcfae3fc8 100644 --- a/lib/Checker/CFRefCount.cpp +++ b/lib/Checker/CFRefCount.cpp @@ -2552,7 +2552,8 @@ static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) { // is a call to a class method whose type we can resolve. In such // cases, promote the return type to XXX* (where XXX is the class). const ObjCInterfaceDecl *D = ME->getReceiverInterface(); - return !D ? RetTy : Ctx.getPointerType(Ctx.getObjCInterfaceType(D)); + return !D ? RetTy : + Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D)); } return RetTy; diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 13b2c20458..e9f42b4640 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -2621,8 +2621,8 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, Dst.Add(Pred); return; } - else if (T->isObjCInterfaceType()) { - // Some code tries to take the sizeof an ObjCInterfaceType, relying that + else if (T->getAs()) { + // Some code tries to take the sizeof an ObjCObjectType, relying that // the compiler has laid out its representation. Just report Unknown // for these. Dst.Add(Pred); diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 462b0b1955..c9bcb1b7e0 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -834,6 +834,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, return RealDecl; } +/// CreateType - get objective-c object type. +llvm::DIType CGDebugInfo::CreateType(const ObjCObjectType *Ty, + llvm::DIFile Unit) { + // Ignore protocols. + return getOrCreateType(Ty->getBaseType(), Unit); +} + /// CreateType - get objective-c interface type. llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, llvm::DIFile Unit) { @@ -1210,6 +1217,8 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, return CreateType(cast(Ty), Unit); case Type::ObjCObjectPointer: return CreateType(cast(Ty), Unit); + case Type::ObjCObject: + return CreateType(cast(Ty), Unit); case Type::ObjCInterface: return CreateType(cast(Ty), Unit); case Type::Builtin: return CreateType(cast(Ty), Unit); diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index c484d4f49c..620a5f2f84 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -80,6 +80,7 @@ class CGDebugInfo { llvm::DIType CreateType(const TagType *Ty, llvm::DIFile F); llvm::DIType CreateType(const RecordType *Ty, llvm::DIFile F); llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F); llvm::DIType CreateType(const EnumType *Ty, llvm::DIFile F); llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F); llvm::DIType CreateType(const ArrayType *Ty, llvm::DIFile F); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 53794152a8..489a9a2044 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -309,8 +309,7 @@ EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), AmountVal); if (!isa(PT->getElementType())) { QualType PTEE = ValTy->getPointeeType(); - if (const ObjCInterfaceType *OIT = - dyn_cast(PTEE)) { + if (const ObjCObjectType *OIT = PTEE->getAs()) { // Handle interface types, which are not represented with a concrete // type. int size = getContext().getTypeSize(OIT) / 8; @@ -1371,8 +1370,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { llvm::ConstantInt::get(Idx->getType(), BaseTypeSize.getQuantity())); Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx"); - } else if (const ObjCInterfaceType *OIT = - dyn_cast(E->getType())) { + } else if (const ObjCObjectType *OIT = + E->getType()->getAs()) { llvm::Value *InterfaceSize = llvm::ConstantInt::get(Idx->getType(), getContext().getTypeSizeInChars(OIT).getQuantity()); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index f6d383704c..2f70969e94 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1334,7 +1334,7 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) { } const QualType ElementType = PT ? PT->getPointeeType() : OPT->getPointeeType(); // Handle interface types, which are not represented with a concrete type. - if (const ObjCInterfaceType *OIT = dyn_cast(ElementType)) { + if (const ObjCObjectType *OIT = ElementType->getAs()) { llvm::Value *InterfaceSize = llvm::ConstantInt::get(Idx->getType(), CGF.getContext().getTypeSizeInChars(OIT).getQuantity()); @@ -1402,8 +1402,7 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { Idx = Builder.CreateNeg(Idx, "sub.ptr.neg"); // Handle interface types, which are not represented with a concrete type. - if (const ObjCInterfaceType *OIT = - dyn_cast(LHSElementType)) { + if (const ObjCObjectType *OIT = LHSElementType->getAs()) { llvm::Value *InterfaceSize = llvm::ConstantInt::get(Idx->getType(), CGF.getContext(). diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index df0263ee12..ce048405af 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -66,8 +66,8 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { case ObjCMessageExpr::Class: { const ObjCInterfaceType *IFace = E->getClassReceiver()->getAs(); - OID = IFace->getDecl(); assert(IFace && "Invalid Objective-C class message send"); + OID = IFace->getDecl(); Receiver = Runtime.GetClass(Builder, OID); isClassMessage = true; break; diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index da64c6907f..a3b62d28a2 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -2225,7 +2225,8 @@ LValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) { - const ObjCInterfaceDecl *ID = ObjectTy->getAs()->getDecl(); + const ObjCInterfaceDecl *ID = + ObjectTy->getAs()->getInterface(); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, EmitIvarOffset(CGF, ID, Ivar)); } diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 5140bb6d9d..279ca72182 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -2938,7 +2938,8 @@ LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) { - const ObjCInterfaceDecl *ID = ObjectTy->getAs()->getDecl(); + const ObjCInterfaceDecl *ID = + ObjectTy->getAs()->getInterface(); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, EmitIvarOffset(CGF, ID, Ivar)); } diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index 291cd7fbde..034e8ef622 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -322,6 +322,9 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { true); } + case Type::ObjCObject: + return ConvertTypeRecursive(cast(Ty).getBaseType()); + case Type::ObjCInterface: { // Objective-C interfaces are always opaque (outside of the // runtime, which can do whatever it likes); we never refine diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 10313980ca..84453b3306 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -1206,6 +1206,12 @@ void CXXNameMangler::mangleType(const ObjCInterfaceType *T) { mangleSourceName(T->getDecl()->getIdentifier()); } +void CXXNameMangler::mangleType(const ObjCObjectType *T) { + // FIXME: do we allow overloading by different protocols? + // If so, we need to mangle them in here. + mangleType(T->getBaseType()); +} + void CXXNameMangler::mangleType(const BlockPointerType *T) { Out << "U13block_pointer"; mangleType(T->getPointeeType()); diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index c329f7b64f..cca434ea8b 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2174,21 +2174,23 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { case pch::TYPE_OBJC_INTERFACE: { unsigned Idx = 0; ObjCInterfaceDecl *ItfD = cast(GetDecl(Record[Idx++])); + return Context->getObjCInterfaceType(ItfD); + } + + case pch::TYPE_OBJC_OBJECT: { + unsigned Idx = 0; + QualType Base = GetType(Record[Idx++]); unsigned NumProtos = Record[Idx++]; llvm::SmallVector Protos; for (unsigned I = 0; I != NumProtos; ++I) Protos.push_back(cast(GetDecl(Record[Idx++]))); - return Context->getObjCInterfaceType(ItfD, Protos.data(), NumProtos); + return Context->getObjCObjectType(Base, Protos.data(), NumProtos); } case pch::TYPE_OBJC_OBJECT_POINTER: { unsigned Idx = 0; - QualType OIT = GetType(Record[Idx++]); - unsigned NumProtos = Record[Idx++]; - llvm::SmallVector Protos; - for (unsigned I = 0; I != NumProtos; ++I) - Protos.push_back(cast(GetDecl(Record[Idx++]))); - return Context->getObjCObjectPointerType(OIT, Protos.data(), NumProtos); + QualType Pointee = GetType(Record[Idx++]); + return Context->getObjCObjectPointerType(Pointee); } case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: { @@ -2364,6 +2366,9 @@ void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { } void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { + TL.setHasBaseTypeAsWritten(Record[Idx++]); TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) @@ -2371,13 +2376,6 @@ void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { } void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setHasBaseTypeAsWritten(Record[Idx++]); - TL.setHasProtocolsAsWritten(Record[Idx++]); - if (TL.hasProtocolsAsWritten()) - for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) - TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++])); } TypeSourceInfo *PCHReader::GetTypeSourceInfo(const RecordData &Record, diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index b323dcf4b8..6a155b8303 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -244,20 +244,21 @@ void PCHTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) { void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { Writer.AddDeclRef(T->getDecl(), Record); + Code = pch::TYPE_OBJC_INTERFACE; +} + +void PCHTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) { + Writer.AddTypeRef(T->getBaseType(), Record); Record.push_back(T->getNumProtocols()); - for (ObjCInterfaceType::qual_iterator I = T->qual_begin(), + for (ObjCObjectType::qual_iterator I = T->qual_begin(), E = T->qual_end(); I != E; ++I) Writer.AddDeclRef(*I, Record); - Code = pch::TYPE_OBJC_INTERFACE; + Code = pch::TYPE_OBJC_OBJECT; } void PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { Writer.AddTypeRef(T->getPointeeType(), Record); - Record.push_back(T->getNumProtocols()); - for (ObjCInterfaceType::qual_iterator I = T->qual_begin(), - E = T->qual_end(); I != E; ++I) - Writer.AddDeclRef(*I, Record); Code = pch::TYPE_OBJC_OBJECT_POINTER; } @@ -406,6 +407,9 @@ void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { } void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { + Record.push_back(TL.hasBaseTypeAsWritten()); Writer.AddSourceLocation(TL.getLAngleLoc(), Record); Writer.AddSourceLocation(TL.getRAngleLoc(), Record); for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) @@ -413,13 +417,6 @@ void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { } void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { Writer.AddSourceLocation(TL.getStarLoc(), Record); - Writer.AddSourceLocation(TL.getLAngleLoc(), Record); - Writer.AddSourceLocation(TL.getRAngleLoc(), Record); - Record.push_back(TL.hasBaseTypeAsWritten()); - Record.push_back(TL.hasProtocolsAsWritten()); - if (TL.hasProtocolsAsWritten()) - for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) - Writer.AddSourceLocation(TL.getProtocolLoc(i), Record); } //===----------------------------------------------------------------------===// diff --git a/lib/Index/Analyzer.cpp b/lib/Index/Analyzer.cpp index 1354fe6be0..6be35ab4a3 100644 --- a/lib/Index/Analyzer.cpp +++ b/lib/Index/Analyzer.cpp @@ -180,7 +180,7 @@ public: if (IsInstanceMethod) return false; - MsgD = Msg->getClassReceiver()->getAs()->getDecl(); + MsgD = Msg->getClassReceiver()->getAs()->getInterface(); break; } @@ -189,7 +189,7 @@ public: if (IsInstanceMethod) return false; - MsgD = Msg->getSuperType()->getAs()->getDecl(); + MsgD = Msg->getSuperType()->getAs()->getInterface(); break; case ObjCMessageExpr::SuperInstance: @@ -292,12 +292,12 @@ public: case ObjCMessageExpr::Class: CanBeClassMethod = true; - MsgD = Msg->getClassReceiver()->getAs()->getDecl(); + MsgD = Msg->getClassReceiver()->getAs()->getInterface(); break; case ObjCMessageExpr::SuperClass: CanBeClassMethod = true; - MsgD = Msg->getSuperType()->getAs()->getDecl(); + MsgD = Msg->getSuperType()->getAs()->getInterface(); break; case ObjCMessageExpr::SuperInstance: diff --git a/lib/Index/ResolveLocation.cpp b/lib/Index/ResolveLocation.cpp index 4bb15943bb..8ef8f3ba7f 100644 --- a/lib/Index/ResolveLocation.cpp +++ b/lib/Index/ResolveLocation.cpp @@ -130,7 +130,7 @@ public: ASTLocation VisitFunctionTypeLoc(FunctionTypeLoc TL); ASTLocation VisitArrayTypeLoc(ArrayTypeLoc TL); ASTLocation VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL); - ASTLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL); + ASTLocation VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL); ASTLocation VisitTypeLoc(TypeLoc TL); }; @@ -454,6 +454,13 @@ ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) if (ContainsLocation(TL.getNameLoc())) return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc()); + return ASTLocation(ParentDecl, TL); +} + +ASTLocation TypeLocResolver::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { + assert(ContainsLocation(TL) && + "Should visit only after verifying that loc is in range"); + for (unsigned i = 0; i != TL.getNumProtocols(); ++i) { SourceLocation L = TL.getProtocolLoc(i); RangePos RP = CheckRange(L); @@ -466,24 +473,6 @@ ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) return ASTLocation(ParentDecl, TL); } -ASTLocation TypeLocResolver::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { - assert(ContainsLocation(TL) && - "Should visit only after verifying that loc is in range"); - - if (TL.hasProtocolsAsWritten()) { - for (unsigned i = 0; i != TL.getNumProtocols(); ++i) { - SourceLocation L = TL.getProtocolLoc(i); - RangePos RP = CheckRange(L); - if (RP == AfterLoc) - break; - if (RP == ContainsLoc) - return ASTLocation(ParentDecl, TL.getProtocol(i), L); - } - } - - return ASTLocation(ParentDecl, TL); -} - ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) { assert(ContainsLocation(TL) && "Should visit only after verifying that loc is in range"); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index b9aa61144a..5e365de695 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -87,8 +87,9 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { } // Create the built-in typedef for 'id'. if (Context.getObjCIdType().isNull()) { - QualType IdT = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy); - TypeSourceInfo *IdInfo = Context.getTrivialTypeSourceInfo(IdT); + QualType T = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, 0, 0); + T = Context.getObjCObjectPointerType(T); + TypeSourceInfo *IdInfo = Context.getTrivialTypeSourceInfo(T); TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext, SourceLocation(), &Context.Idents.get("id"), IdInfo); @@ -98,9 +99,9 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { } // Create the built-in typedef for 'Class'. if (Context.getObjCClassType().isNull()) { - QualType ClassType - = Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy); - TypeSourceInfo *ClassInfo = Context.getTrivialTypeSourceInfo(ClassType); + QualType T = Context.getObjCObjectType(Context.ObjCBuiltinClassTy, 0, 0); + T = Context.getObjCObjectPointerType(T); + TypeSourceInfo *ClassInfo = Context.getTrivialTypeSourceInfo(T); TypedefDecl *ClassTypedef = TypedefDecl::Create(Context, CurContext, SourceLocation(), &Context.Idents.get("Class"), ClassInfo); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 77bf91946c..036ae7e869 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -2047,14 +2047,14 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, I != E; ++I) AddObjCProperties(*I, true, CurContext, Results); } else if ((IsArrow && BaseType->isObjCObjectPointerType()) || - (!IsArrow && BaseType->isObjCInterfaceType())) { + (!IsArrow && BaseType->isObjCObjectType())) { // Objective-C instance variable access. ObjCInterfaceDecl *Class = 0; if (const ObjCObjectPointerType *ObjCPtr = BaseType->getAs()) Class = ObjCPtr->getInterfaceDecl(); else - Class = BaseType->getAs()->getDecl(); + Class = BaseType->getAs()->getInterface(); // Add all ivars from this class and its superclasses. if (Class) { @@ -2911,9 +2911,9 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { ObjCInterfaceDecl *IFace = 0; switch (Msg->getReceiverKind()) { case ObjCMessageExpr::Class: - if (const ObjCInterfaceType *IFaceType - = Msg->getClassReceiver()->getAs()) - IFace = IFaceType->getDecl(); + if (const ObjCObjectType *ObjType + = Msg->getClassReceiver()->getAs()) + IFace = ObjType->getInterface(); break; case ObjCMessageExpr::Instance: { @@ -2994,9 +2994,9 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, if ((CDecl = dyn_cast_or_null(ND))) { // "super" names an interface. Use it. } else if (TypeDecl *TD = dyn_cast_or_null(ND)) { - if (const ObjCInterfaceType *Iface - = Context.getTypeDeclType(TD)->getAs()) - CDecl = Iface->getDecl(); + if (const ObjCObjectType *Iface + = Context.getTypeDeclType(TD)->getAs()) + CDecl = Iface->getInterface(); } else if (ND && isa(ND)) { // "super" names an unresolved type; we can't be more specific. } else { @@ -3030,8 +3030,8 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, if (Receiver) { QualType T = GetTypeFromParser(Receiver, 0); if (!T.isNull()) - if (const ObjCInterfaceType *Interface = T->getAs()) - CDecl = Interface->getDecl(); + if (const ObjCObjectType *Interface = T->getAs()) + CDecl = Interface->getInterface(); } // Add all of the factory methods in this Objective-C class, its protocols, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index fb3100353b..5ea7af7144 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2719,7 +2719,7 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, QualType T = NewVD->getType(); - if (T->isObjCInterfaceType()) { + if (T->isObjCObjectType()) { Diag(NewVD->getLocation(), diag::err_statically_allocated_object); return NewVD->setInvalidDecl(); } @@ -2937,7 +2937,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, D.setInvalidType(); // Do not allow returning a objc interface by-value. - if (R->getAs()->getResultType()->isObjCInterfaceType()) { + if (R->getAs()->getResultType()->isObjCObjectType()) { Diag(D.getIdentifierLoc(), diag::err_object_cannot_be_passed_returned_by_value) << 0 << R->getAs()->getResultType(); @@ -4330,7 +4330,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, // Parameter declarators cannot be interface types. All ObjC objects are // passed by reference. - if (T->isObjCInterfaceType()) { + if (T->isObjCObjectType()) { Diag(NameLoc, diag::err_object_cannot_be_passed_returned_by_value) << 1 << T; New->setInvalidDecl(); @@ -6146,7 +6146,7 @@ void Sema::ActOnFields(Scope* S, } if (Record && FDTTy->getDecl()->hasObjectMember()) Record->setHasObjectMember(true); - } else if (FDTy->isObjCInterfaceType()) { + } else if (FDTy->isObjCObjectType()) { /// A field cannot be an Objective-c object Diag(FD->getLocation(), diag::err_statically_allocated_object); FD->setInvalidDecl(); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 9ed9692114..b166d87340 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -142,8 +142,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, // typedef. If we do, get the underlying class type. if (const TypedefDecl *TDecl = dyn_cast_or_null(PrevDecl)) { QualType T = TDecl->getUnderlyingType(); - if (T->isObjCInterfaceType()) { - if (NamedDecl *IDecl = T->getAs()->getDecl()) + if (T->isObjCObjectType()) { + if (NamedDecl *IDecl = T->getAs()->getInterface()) SuperClassDecl = dyn_cast(IDecl); } } @@ -210,8 +210,8 @@ Sema::DeclPtrTy Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, LookupOrdinaryName, ForRedeclaration); if (const TypedefDecl *TDecl = dyn_cast_or_null(CDeclU)) { QualType T = TDecl->getUnderlyingType(); - if (T->isObjCInterfaceType()) { - if (NamedDecl *IDecl = T->getAs()->getDecl()) { + if (T->isObjCObjectType()) { + if (NamedDecl *IDecl = T->getAs()->getInterface()) { ClassName = IDecl->getIdentifier(); CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, LookupOrdinaryName, ForRedeclaration); @@ -1024,15 +1024,15 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, // // FIXME: Make an extension? TypedefDecl *TDD = dyn_cast(PrevDecl); - if (!TDD || !isa(TDD->getUnderlyingType())) { + if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) { Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i]; Diag(PrevDecl->getLocation(), diag::note_previous_definition); - } else if (TDD) { + } else { // a forward class declaration matching a typedef name of a class refers // to the underlying class. - if (ObjCInterfaceType * OI = - dyn_cast(TDD->getUnderlyingType())) - PrevDecl = OI->getDecl(); + if (const ObjCObjectType *OI = + TDD->getUnderlyingType()->getAs()) + PrevDecl = OI->getInterface(); } } ObjCInterfaceDecl *IDecl = dyn_cast_or_null(PrevDecl); @@ -1532,7 +1532,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( // Methods cannot return interface types. All ObjC objects are // passed by reference. - if (resultDeclType->isObjCInterfaceType()) { + if (resultDeclType->isObjCObjectType()) { Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value) << 0 << resultDeclType; return DeclPtrTy(); @@ -1570,7 +1570,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( ArgInfo[i].Name, ArgType, DI, VarDecl::None, VarDecl::None, 0); - if (ArgType->isObjCInterfaceType()) { + if (ArgType->isObjCObjectType()) { Diag(ArgInfo[i].NameLoc, diag::err_object_cannot_be_passed_returned_by_value) << 1 << ArgType; @@ -1594,7 +1594,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( else // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). ArgType = adjustParameterType(ArgType); - if (ArgType->isObjCInterfaceType()) { + if (ArgType->isObjCObjectType()) { Diag(Param->getLocation(), diag::err_object_cannot_be_passed_returned_by_value) << 1 << ArgType; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 13f44b9a8a..60c716353a 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -294,7 +294,7 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) { bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) { DefaultArgumentPromotion(Expr); - if (Expr->getType()->isObjCInterfaceType() && + if (Expr->getType()->isObjCObjectType() && DiagRuntimeBehavior(Expr->getLocStart(), PDiag(diag::err_cannot_pass_objc_interface_to_vararg) << Expr->getType() << CT)) @@ -2040,7 +2040,7 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType, return true; // Reject sizeof(interface) and sizeof(interface) in 64-bit mode. - if (LangOpts.ObjCNonFragileABI && exprType->isObjCInterfaceType()) { + if (LangOpts.ObjCNonFragileABI && exprType->isObjCObjectType()) { Diag(OpLoc, diag::err_sizeof_nonfragile_interface) << exprType << isSizeof << ExprRange; return true; @@ -2316,7 +2316,7 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc, return ExprError(); // Diagnose bad cases where we step over interface counts. - if (ResultType->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { + if (ResultType->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { Diag(LLoc, diag::err_subscript_nonfragile_interface) << ResultType << BaseExpr->getSourceRange(); return ExprError(); @@ -2924,7 +2924,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // Handle the following exceptional case PObj->isa. if (const ObjCObjectPointerType *OPT = BaseType->getAs()) { - if (OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && + if (OPT->getObjectType()->isObjCId() && MemberName.getAsIdentifierInfo()->isStr("isa")) return Owned(new (Context) ObjCIsaExpr(BaseExpr, true, MemberLoc, Context.getObjCClassType())); @@ -3048,8 +3048,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, } } - // Handle field access to simple records. This also handles access - // to fields of the ObjC 'id' struct. + // Handle field access to simple records. if (const RecordType *RTy = BaseType->getAs()) { if (LookupMemberExprInRecord(*this, R, BaseExpr->getSourceRange(), RTy, OpLoc, SS)) @@ -3060,14 +3059,14 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // Handle access to Objective-C instance variables, such as "Obj->ivar" and // (*Obj).ivar. if ((IsArrow && BaseType->isObjCObjectPointerType()) || - (!IsArrow && BaseType->isObjCInterfaceType())) { + (!IsArrow && BaseType->isObjCObjectType())) { const ObjCObjectPointerType *OPT = BaseType->getAs(); - const ObjCInterfaceType *IFaceT = - OPT ? OPT->getInterfaceType() : BaseType->getAs(); - if (IFaceT) { + ObjCInterfaceDecl *IDecl = + OPT ? OPT->getInterfaceDecl() + : BaseType->getAs()->getInterface(); + if (IDecl) { IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); - ObjCInterfaceDecl *IDecl = IFaceT->getDecl(); ObjCInterfaceDecl *ClassDeclared; ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); @@ -3180,7 +3179,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // Handle the following exceptional case (*Obj).isa. if (!IsArrow && - BaseType->isSpecificBuiltinType(BuiltinType::ObjCId) && + BaseType->isObjCObjectType() && + BaseType->getAs()->isObjCId() && MemberName.getAsIdentifierInfo()->isStr("isa")) return Owned(new (Context) ObjCIsaExpr(BaseExpr, false, MemberLoc, Context.getObjCClassType())); @@ -5064,7 +5064,7 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 return QualType(); } // Diagnose bad cases where we step over interface counts. - if (PointeeTy->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { + if (PointeeTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { Diag(Loc, diag::err_arithmetic_nonfragile_interface) << PointeeTy << PExp->getSourceRange(); return QualType(); @@ -5140,7 +5140,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, return QualType(); // Diagnose bad cases where we step over interface counts. - if (lpointee->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { + if (lpointee->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { Diag(Loc, diag::err_arithmetic_nonfragile_interface) << lpointee << lex->getSourceRange(); return QualType(); @@ -5907,7 +5907,7 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc, << ResType)) return QualType(); // Diagnose bad cases where we step over interface counts. - else if (PointeeTy->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { + else if (PointeeTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { Diag(OpLoc, diag::err_arithmetic_nonfragile_interface) << PointeeTy << Op->getSourceRange(); return QualType(); @@ -7021,7 +7021,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { QualType RetTy = T.getTypePtr()->getAs()->getResultType(); // Do not allow returning a objc interface by-value. - if (RetTy->isObjCInterfaceType()) { + if (RetTy->isObjCObjectType()) { Diag(ParamInfo.getSourceRange().getBegin(), diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; return; @@ -7093,7 +7093,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { QualType RetTy = T->getAs()->getResultType(); // Do not allow returning a objc interface by-value. - if (RetTy->isObjCInterfaceType()) { + if (RetTy->isObjCObjectType()) { Diag(ParamInfo.getSourceRange().getBegin(), diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; } else if (!RetTy->isDependentType()) diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index eb60011ec3..fd4feedf92 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -722,10 +722,8 @@ Sema::OwningExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, // Find the class to which we are sending this message. ObjCInterfaceDecl *Class = 0; - if (const ObjCInterfaceType *ClassType - = ReceiverType->getAs()) - Class = ClassType->getDecl(); - else { + const ObjCObjectType *ClassType = ReceiverType->getAs(); + if (!ClassType || !(Class = ClassType->getInterface())) { Diag(Loc, diag::err_invalid_receiver_class_message) << ReceiverType; return ExprError(); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 06d202d3e0..c6a8b3595a 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -624,7 +624,7 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, } else if (DeclType->isReferenceType()) { CheckReferenceType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); - } else if (DeclType->isObjCInterfaceType()) { + } else if (DeclType->isObjCObjectType()) { SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class) << DeclType; hadError = true; diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 002c39b640..69a338224e 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -199,19 +199,16 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, // gc'able conforms to NSCopying protocol if (getLangOptions().getGCMode() != LangOptions::NonGC && isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) - if (T->isObjCObjectPointerType()) { - QualType InterfaceTy = T->getPointeeType(); - if (const ObjCInterfaceType *OIT = - InterfaceTy->getAs()) { - ObjCInterfaceDecl *IDecl = OIT->getDecl(); - if (IDecl) - if (ObjCProtocolDecl* PNSCopying = - LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc)) - if (IDecl->ClassImplementsProtocol(PNSCopying, true)) - Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId; - } + if (const ObjCObjectPointerType *ObjPtrTy = + T->getAs()) { + ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); + if (IDecl) + if (ObjCProtocolDecl* PNSCopying = + LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc)) + if (IDecl->ClassImplementsProtocol(PNSCopying, true)) + Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId; } - if (T->isObjCInterfaceType()) + if (T->isObjCObjectType()) Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object); DeclContext *DC = cast(CDecl); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 04495e5ca4..bf4e7f74ad 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1543,16 +1543,12 @@ bool Sema::FunctionArgTypesAreEqual(FunctionProtoType* OldType, PTFr->getPointeeType()->isObjCQualifiedClassType())) continue; } - else if (ToType->isObjCObjectPointerType() && - FromType->isObjCObjectPointerType()) { - QualType ToInterfaceTy = ToType->getPointeeType(); - QualType FromInterfaceTy = FromType->getPointeeType(); - if (const ObjCInterfaceType *OITTo = - ToInterfaceTy->getAs()) - if (const ObjCInterfaceType *OITFr = - FromInterfaceTy->getAs()) - if (OITTo->getDecl() == OITFr->getDecl()) - continue; + else if (const ObjCObjectPointerType *PTTo = + ToType->getAs()) { + if (const ObjCObjectPointerType *PTFr = + FromType->getAs()) + if (PTTo->getInterfaceDecl() == PTFr->getInterfaceDecl()) + continue; } return false; } @@ -2141,8 +2137,8 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, // Objective-C++: If one interface is more specific than the // other, it is the better one. - const ObjCInterfaceType* FromIface1 = FromPointee1->getAs(); - const ObjCInterfaceType* FromIface2 = FromPointee2->getAs(); + const ObjCObjectType* FromIface1 = FromPointee1->getAs(); + const ObjCObjectType* FromIface2 = FromPointee2->getAs(); if (FromIface1 && FromIface1) { if (Context.canAssignObjCInterfaces(FromIface2, FromIface1)) return ImplicitConversionSequence::Better; @@ -2348,10 +2344,10 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, QualType ToPointee2 = ToType2->getAs()->getPointeeType().getUnqualifiedType(); - const ObjCInterfaceType* FromIface1 = FromPointee1->getAs(); - const ObjCInterfaceType* FromIface2 = FromPointee2->getAs(); - const ObjCInterfaceType* ToIface1 = ToPointee1->getAs(); - const ObjCInterfaceType* ToIface2 = ToPointee2->getAs(); + const ObjCObjectType* FromIface1 = FromPointee1->getAs(); + const ObjCObjectType* FromIface2 = FromPointee2->getAs(); + const ObjCObjectType* ToIface1 = ToPointee1->getAs(); + const ObjCObjectType* ToIface2 = ToPointee2->getAs(); // -- conversion of C* to B* is better than conversion of C* to A*, if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { @@ -2935,8 +2931,8 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) { /// TryContextuallyConvertToObjCId - Attempt to contextually convert the /// expression From to 'id'. ImplicitConversionSequence Sema::TryContextuallyConvertToObjCId(Expr *From) { - QualType Ty = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy); - return TryImplicitConversion(From, Ty, + QualType Ty = Context.getObjCIdType(); + return TryImplicitConversion(From, Ty, // FIXME: Are these flags correct? /*SuppressUserConversions=*/false, /*AllowExplicit=*/true, @@ -2946,7 +2942,7 @@ ImplicitConversionSequence Sema::TryContextuallyConvertToObjCId(Expr *From) { /// PerformContextuallyConvertToObjCId - Perform a contextual conversion /// of the expression From to 'id'. bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) { - QualType Ty = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy); + QualType Ty = Context.getObjCIdType(); ImplicitConversionSequence ICS = TryContextuallyConvertToObjCId(From); if (!ICS.isBad()) return PerformImplicitConversion(From, Ty, ICS, AA_Converting); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index d904907e97..3200288e43 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -30,7 +30,7 @@ using namespace clang; Sema::OwningStmtResult Sema::ActOnExprStmt(FullExprArg expr) { Expr *E = expr->takeAs(); assert(E && "ActOnExprStmt(): missing expression"); - if (E->getType()->isObjCInterfaceType()) { + if (E->getType()->isObjCObjectType()) { if (LangOpts.ObjCNonFragileABI) Diag(E->getLocEnd(), diag::err_indirection_requires_nonfragile_object) << E->getType(); diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 733d0e9e9a..88ceeca58a 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2652,6 +2652,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, case Type::Record: case Type::Enum: case Type::ObjCInterface: + case Type::ObjCObject: case Type::ObjCObjectPointer: case Type::UnresolvedUsing: #define TYPE(Class, Base) diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index d926b9b61f..e021663515 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -162,9 +162,10 @@ static QualType ConvertDeclSpecToType(Sema &TheSema, case DeclSpec::TST_unspecified: // "" is an objc qualified ID with a missing id. if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) { - Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy, - (ObjCProtocolDecl**)PQ, - DS.getNumProtocolQualifiers()); + Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, + (ObjCProtocolDecl**)PQ, + DS.getNumProtocolQualifiers()); + Result = Context.getObjCObjectPointerType(Result); break; } @@ -299,28 +300,28 @@ static QualType ConvertDeclSpecToType(Sema &TheSema, Result = TheSema.GetTypeFromParser(DS.getTypeRep()); if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) { - if (const ObjCInterfaceType * - Interface = Result->getAs()) { - // It would be nice if protocol qualifiers were only stored with the - // ObjCObjectPointerType. Unfortunately, this isn't possible due - // to the following typedef idiom (which is uncommon, but allowed): - // - // typedef Foo

T; - // static void func() { - // Foo

*yy; - // T *zz; - // } - Result = Context.getObjCInterfaceType(Interface->getDecl(), - (ObjCProtocolDecl**)PQ, - DS.getNumProtocolQualifiers()); - } else if (Result->isObjCIdType()) + if (const ObjCObjectType *ObjT = Result->getAs()) { + // Silently drop any existing protocol qualifiers. + // TODO: determine whether that's the right thing to do. + if (ObjT->getNumProtocols()) + Result = ObjT->getBaseType(); + + if (DS.getNumProtocolQualifiers()) + Result = Context.getObjCObjectType(Result, + (ObjCProtocolDecl**) PQ, + DS.getNumProtocolQualifiers()); + } else if (Result->isObjCIdType()) { // id - Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy, - (ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers()); - else if (Result->isObjCClassType()) { + Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, + (ObjCProtocolDecl**) PQ, + DS.getNumProtocolQualifiers()); + Result = Context.getObjCObjectPointerType(Result); + } else if (Result->isObjCClassType()) { // Class - Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy, - (ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers()); + Result = Context.getObjCObjectType(Context.ObjCBuiltinClassTy, + (ObjCProtocolDecl**) PQ, + DS.getNumProtocolQualifiers()); + Result = Context.getObjCObjectPointerType(Result); } else { TheSema.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers) << DS.getSourceRange(); @@ -503,7 +504,7 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals, Qs.removeRestrict(); } - assert(!T->isObjCInterfaceType() && "Should build ObjCObjectPointerType"); + assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType"); // Build the pointer type. return Context.getQualifiedType(Context.getPointerType(T), Qs); @@ -658,7 +659,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, // array, accept it as a GNU extension: C99 6.7.2.1p2. if (EltTy->getDecl()->hasFlexibleArrayMember()) Diag(Loc, diag::ext_flexible_array_in_array) << T; - } else if (T->isObjCInterfaceType()) { + } else if (T->isObjCObjectType()) { Diag(Loc, diag::err_objc_array_of_interfaces) << T; return QualType(); } @@ -1055,13 +1056,9 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, D.setInvalidType(true); // Build the type anyway. } - if (getLangOptions().ObjC1 && T->isObjCInterfaceType()) { - const ObjCInterfaceType *OIT = T->getAs(); - T = Context.getObjCObjectPointerType(T, - const_cast( - OIT->qual_begin()), - OIT->getNumProtocols(), - DeclType.Ptr.TypeQuals); + if (getLangOptions().ObjC1 && T->getAs()) { + T = Context.getObjCObjectPointerType(T); + T = Context.getCVRQualifiedType(T, DeclType.Ptr.TypeQuals); break; } T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name); @@ -1400,7 +1397,18 @@ namespace { } void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { TL.setNameLoc(DS.getTypeSpecTypeLoc()); + } + void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { + // Handle the base type, which might not have been written explicitly. + if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) { + TL.setHasBaseTypeAsWritten(false); + TL.getBaseLoc().initialize(SourceLocation()); + } else { + TL.setHasBaseTypeAsWritten(true); + Visit(TL.getBaseLoc()); + } + // Protocol qualifiers. if (DS.getProtocolQualifiers()) { assert(TL.getNumProtocols() > 0); assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers()); @@ -1415,34 +1423,8 @@ namespace { } } void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { - assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers()); - TL.setStarLoc(SourceLocation()); - - if (DS.getProtocolQualifiers()) { - assert(TL.getNumProtocols() > 0); - assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers()); - TL.setHasProtocolsAsWritten(true); - TL.setLAngleLoc(DS.getProtocolLAngleLoc()); - TL.setRAngleLoc(DS.getSourceRange().getEnd()); - for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i) - TL.setProtocolLoc(i, DS.getProtocolLocs()[i]); - - } else { - assert(TL.getNumProtocols() == 0); - TL.setHasProtocolsAsWritten(false); - TL.setLAngleLoc(SourceLocation()); - TL.setRAngleLoc(SourceLocation()); - } - - // This might not have been written with an inner type. - if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) { - TL.setHasBaseTypeAsWritten(false); - TL.getBaseTypeLoc().initialize(SourceLocation()); - } else { - TL.setHasBaseTypeAsWritten(true); - Visit(TL.getBaseTypeLoc()); - } + Visit(TL.getPointeeLoc()); } void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { TypeSourceInfo *TInfo = 0; @@ -1515,10 +1497,6 @@ namespace { void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::Pointer); TL.setStarLoc(Chunk.Loc); - TL.setHasBaseTypeAsWritten(true); - TL.setHasProtocolsAsWritten(false); - TL.setLAngleLoc(SourceLocation()); - TL.setRAngleLoc(SourceLocation()); } void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::MemberPointer); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 3515261733..7f756ec4ce 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2445,31 +2445,15 @@ QualType TreeTransform::TransformPointerType(TypeLocBuilder &TLB, return QualType(); QualType Result = TL.getType(); - if (PointeeType->isObjCInterfaceType() || - PointeeType->isSpecificBuiltinType(BuiltinType::ObjCId)) { + if (PointeeType->getAs()) { // A dependent pointer type 'T *' has is being transformed such // that an Objective-C class type is being replaced for 'T'. The // resulting pointer type is an ObjCObjectPointerType, not a // PointerType. - ObjCProtocolDecl **Protocols = 0; - unsigned NumProtocols = 0; - - if (const ObjCInterfaceType *IFace - = PointeeType->getAs()) { - Protocols = const_cast(IFace->qual_begin()); - NumProtocols = IFace->getNumProtocols(); - } - - Result = SemaRef.Context.getObjCObjectPointerType(PointeeType, - Protocols, - NumProtocols); + Result = SemaRef.Context.getObjCObjectPointerType(PointeeType); - ObjCObjectPointerTypeLoc NewT = TLB.push(Result); - NewT.setStarLoc(TL.getSigilLoc()); - NewT.setHasProtocolsAsWritten(false); - NewT.setLAngleLoc(SourceLocation()); - NewT.setRAngleLoc(SourceLocation()); - NewT.setHasBaseTypeAsWritten(true); + ObjCObjectPointerTypeLoc NewT = TLB.push(Result); + NewT.setStarLoc(TL.getStarLoc()); return Result; } @@ -3327,6 +3311,17 @@ TreeTransform::TransformObjCInterfaceType(TypeLocBuilder &TLB, ObjCInterfaceTypeLoc TL, QualType ObjectType) { // ObjCInterfaceType is never dependent. + TLB.pushFullCopy(TL); + return TL.getType(); +} + +template +QualType +TreeTransform::TransformObjCObjectType(TypeLocBuilder &TLB, + ObjCObjectTypeLoc TL, + QualType ObjectType) { + // ObjCObjectType is never dependent. + TLB.pushFullCopy(TL); return TL.getType(); } @@ -3336,6 +3331,7 @@ TreeTransform::TransformObjCObjectPointerType(TypeLocBuilder &TLB, ObjCObjectPointerTypeLoc TL, QualType ObjectType) { // ObjCObjectPointerType is never dependent. + TLB.pushFullCopy(TL); return TL.getType(); } diff --git a/test/SemaObjCXX/deduction.mm b/test/SemaObjCXX/deduction.mm index 0d2fc06dc3..6dd449d6ea 100644 --- a/test/SemaObjCXX/deduction.mm +++ b/test/SemaObjCXX/deduction.mm @@ -26,3 +26,33 @@ namespace test0 { RetainPtr ptr(S); } } + +@class Test1Class; +@protocol Test1Protocol; +namespace test1 { + template struct RemovePointer { + typedef T type; + }; + template struct RemovePointer { + typedef T type; + }; + template struct is_same {}; + template struct is_same { + static void foo(); + }; + template struct tester { + void test() { + is_same::type*>::foo(); // expected-error 2 {{no member named 'foo'}} + } + }; + + template struct tester; + template struct tester >; + template struct tester; + template struct tester >; + template struct tester; + template struct tester*>; + + template struct tester; // expected-note {{in instantiation}} + template struct tester >; // expected-note {{in instantiation}} +} diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 4570c6a1bd..753e90e4b0 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -317,6 +317,7 @@ public: bool VisitTagTypeLoc(TagTypeLoc TL); // FIXME: TemplateTypeParmTypeLoc doesn't provide any location information bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL); + bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL); bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL); bool VisitPointerTypeLoc(PointerTypeLoc TL); bool VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL); @@ -811,6 +812,13 @@ bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU))) return true; + return false; +} + +bool CursorVisitor::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { + if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseLoc())) + return true; + for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) { if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I), TU))) @@ -821,19 +829,7 @@ bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { } bool CursorVisitor::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { - if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseTypeLoc())) - return true; - - if (TL.hasProtocolsAsWritten()) { - for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) { - if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), - TL.getProtocolLoc(I), - TU))) - return true; - } - } - - return false; + return Visit(TL.getPointeeLoc()); } bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) { diff --git a/tools/libclang/CXTypes.cpp b/tools/libclang/CXTypes.cpp index 28dc12a344..137370adb2 100644 --- a/tools/libclang/CXTypes.cpp +++ b/tools/libclang/CXTypes.cpp @@ -173,6 +173,9 @@ CXCursor clang_getTypeDeclaration(CXType CT) { case Type::Typedef: D = cast(TP)->getDecl(); break; + case Type::ObjCObject: + D = cast(TP)->getInterface(); + break; case Type::ObjCInterface: D = cast(TP)->getDecl(); break;