Index: cfe/trunk/include/clang/AST/Type.h =================================================================== --- cfe/trunk/include/clang/AST/Type.h +++ cfe/trunk/include/clang/AST/Type.h @@ -4699,6 +4699,59 @@ } }; +/// This class wraps the list of protocol qualifiers. For types that can +/// take ObjC protocol qualifers, they can subclass this class. +template +class ObjCProtocolQualifiers { +protected: + ObjCProtocolQualifiers() {} + ObjCProtocolDecl * const *getProtocolStorage() const { + return const_cast(this)->getProtocolStorage(); + } + + ObjCProtocolDecl **getProtocolStorage() { + return static_cast(this)->getProtocolStorageImpl(); + } + void setNumProtocols(unsigned N) { + static_cast(this)->setNumProtocolsImpl(N); + } + void initialize(ArrayRef protocols) { + setNumProtocols(protocols.size()); + assert(getNumProtocols() == protocols.size() && + "bitfield overflow in protocol count"); + if (!protocols.empty()) + memcpy(getProtocolStorage(), protocols.data(), + protocols.size() * sizeof(ObjCProtocolDecl*)); + } + +public: + typedef ObjCProtocolDecl * const *qual_iterator; + typedef llvm::iterator_range qual_range; + + qual_range quals() const { return qual_range(qual_begin(), qual_end()); } + qual_iterator qual_begin() const { return getProtocolStorage(); } + qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); } + + bool qual_empty() const { return getNumProtocols() == 0; } + + /// Return the number of qualifying protocols in this type, or 0 if + /// there are none. + unsigned getNumProtocols() const { + return static_cast(this)->getNumProtocolsImpl(); + } + + /// Fetch a protocol by index. + ObjCProtocolDecl *getProtocol(unsigned I) const { + assert(I < getNumProtocols() && "Out-of-range protocol access"); + return qual_begin()[I]; + } + + /// Retrieve all of the protocol qualifiers. + ArrayRef getProtocols() const { + return ArrayRef(qual_begin(), getNumProtocols()); + } +}; + /// Represents a class type in Objective C. /// /// Every Objective C type is a combination of a base type, a set of @@ -4727,7 +4780,9 @@ /// 'id

' is an ObjCObjectPointerType whose pointee is an ObjCObjectType /// 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 { +class ObjCObjectType : public Type, + public ObjCProtocolQualifiers { + friend class ObjCProtocolQualifiers; // ObjCObjectType.NumTypeArgs - the number of type arguments stored // after the ObjCObjectPointerType node. // ObjCObjectType.NumProtocols - the number of protocols stored @@ -4747,16 +4802,20 @@ mutable llvm::PointerIntPair CachedSuperClassType; - ObjCProtocolDecl * const *getProtocolStorage() const { - return const_cast(this)->getProtocolStorage(); - } - QualType *getTypeArgStorage(); const QualType *getTypeArgStorage() const { return const_cast(this)->getTypeArgStorage(); } - ObjCProtocolDecl **getProtocolStorage(); + ObjCProtocolDecl **getProtocolStorageImpl(); + /// Return the number of qualifying protocols in this interface type, + /// or 0 if there are none. + unsigned getNumProtocolsImpl() const { + return ObjCObjectTypeBits.NumProtocols; + } + void setNumProtocolsImpl(unsigned N) { + ObjCObjectTypeBits.NumProtocols = N; + } protected: ObjCObjectType(QualType Canonical, QualType Base, @@ -4833,30 +4892,6 @@ ObjCObjectTypeBits.NumTypeArgs); } - typedef ObjCProtocolDecl * const *qual_iterator; - typedef llvm::iterator_range qual_range; - - qual_range quals() const { return qual_range(qual_begin(), qual_end()); } - qual_iterator qual_begin() const { return getProtocolStorage(); } - qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); } - - bool qual_empty() const { return getNumProtocols() == 0; } - - /// Return the number of qualifying protocols in this interface type, - /// or 0 if there are none. - unsigned getNumProtocols() const { return ObjCObjectTypeBits.NumProtocols; } - - /// Fetch a protocol by index. - ObjCProtocolDecl *getProtocol(unsigned I) const { - assert(I < getNumProtocols() && "Out-of-range protocol access"); - return qual_begin()[I]; - } - - /// Retrieve all of the protocol qualifiers. - ArrayRef getProtocols() const { - return ArrayRef(qual_begin(), getNumProtocols()); - } - /// Whether this is a "__kindof" type as written. bool isKindOfTypeAsWritten() const { return ObjCObjectTypeBits.IsKindOf; } @@ -4919,7 +4954,7 @@ return reinterpret_cast(static_cast(this)+1); } -inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() { +inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorageImpl() { return reinterpret_cast( getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs); } Index: cfe/trunk/lib/AST/Type.cpp =================================================================== --- cfe/trunk/lib/AST/Type.cpp +++ cfe/trunk/lib/AST/Type.cpp @@ -546,15 +546,9 @@ ObjCObjectTypeBits.NumTypeArgs = typeArgs.size(); assert(getTypeArgsAsWritten().size() == typeArgs.size() && "bitfield overflow in type argument count"); - ObjCObjectTypeBits.NumProtocols = protocols.size(); - assert(getNumProtocols() == protocols.size() && - "bitfield overflow in protocol count"); if (!typeArgs.empty()) memcpy(getTypeArgStorage(), typeArgs.data(), typeArgs.size() * sizeof(QualType)); - if (!protocols.empty()) - memcpy(getProtocolStorage(), protocols.data(), - protocols.size() * sizeof(ObjCProtocolDecl*)); for (auto typeArg : typeArgs) { if (typeArg->isDependentType()) @@ -565,6 +559,9 @@ if (typeArg->containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); } + // Initialize the protocol qualifiers. The protocol storage is known + // after we set number of type arguments. + initialize(protocols); } bool ObjCObjectType::isSpecialized() const {