diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 5 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 40 | ||||
-rw-r--r-- | include/clang/AST/TypeNodes.def | 1 | ||||
-rw-r--r-- | include/clang/Frontend/PCHBitCodes.h | 10 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 23 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 31 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 10 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 7 |
9 files changed, 133 insertions, 4 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index bdd87be369..bb9e3861be 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -86,6 +86,7 @@ class ASTContext { llvm::FoldingSet<TypenameType> TypenameTypes; llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes; llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; + llvm::FoldingSet<ObjCProtocolListType> ObjCProtocolListTypes; llvm::FoldingSet<ElaboratedType> ElaboratedTypes; llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; @@ -510,6 +511,10 @@ public: ObjCProtocolDecl **ProtocolList = 0, unsigned NumProtocols = 0); + QualType getObjCProtocolListType(QualType T, + ObjCProtocolDecl **Protocols, + unsigned NumProtocols); + /// getTypeOfType - GCC extension. QualType getTypeOfExprType(Expr *e); QualType getTypeOfType(QualType t); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 952671915f..cef52175d1 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -2443,6 +2443,46 @@ public: static bool classof(const ObjCObjectPointerType *) { return true; } }; +/// \brief An ObjC Protocol list that qualifies a type. +/// +/// This is used only for keeping detailed type source information, it should +/// not participate in the semantics of the type system. +/// The protocol list is not canonicalized. +class ObjCProtocolListType : public Type, public llvm::FoldingSetNode { + QualType BaseType; + + // List of protocols for this protocol conforming object type. + llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols; + + ObjCProtocolListType(QualType T, ObjCProtocolDecl **Protos, unsigned NumP) : + Type(ObjCProtocolList, QualType(), /*Dependent=*/false), + BaseType(T), Protocols(Protos, Protos+NumP) { } + friend class ASTContext; // ASTContext creates these. + +public: + QualType getBaseType() const { return BaseType; } + + /// \brief Provides access to the list of protocols qualifying the base type. + typedef llvm::SmallVector<ObjCProtocolDecl*, 4>::const_iterator qual_iterator; + + qual_iterator qual_begin() const { return Protocols.begin(); } + qual_iterator qual_end() const { return Protocols.end(); } + bool qual_empty() const { return Protocols.size() == 0; } + + /// \brief Return the number of qualifying protocols. + unsigned getNumProtocols() const { return Protocols.size(); } + + void Profile(llvm::FoldingSetNodeID &ID); + static void Profile(llvm::FoldingSetNodeID &ID, QualType T, + ObjCProtocolDecl **protocols, unsigned NumProtocols); + virtual void getAsStringInternal(std::string &InnerString, + const PrintingPolicy &Policy) const; + static bool classof(const Type *T) { + return T->getTypeClass() == ObjCProtocolList; + } + static bool classof(const ObjCProtocolListType *) { return true; } +}; + /// A qualifier set is used to build a set of qualifiers. class QualifierCollector : public Qualifiers { ASTContext *Context; diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index a2feb513a8..6c6bd20e85 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -87,6 +87,7 @@ NON_CANONICAL_TYPE(QualifiedName, Type) DEPENDENT_TYPE(Typename, Type) TYPE(ObjCInterface, Type) TYPE(ObjCObjectPointer, Type) +NON_CANONICAL_TYPE(ObjCProtocolList, Type) // These types are always leaves in the type hierarchy. #ifdef LEAF_TYPE diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index f0eea414f1..2655217a83 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -394,14 +394,16 @@ namespace clang { TYPE_OBJC_INTERFACE = 21, /// \brief An ObjCObjectPointerType record. TYPE_OBJC_OBJECT_POINTER = 22, + /// \brief An ObjCProtocolListType record. + TYPE_OBJC_PROTOCOL_LIST = 23, /// \brief a DecltypeType record. - TYPE_DECLTYPE = 23, + TYPE_DECLTYPE = 24, /// \brief A ConstantArrayWithExprType record. - TYPE_CONSTANT_ARRAY_WITH_EXPR = 24, + TYPE_CONSTANT_ARRAY_WITH_EXPR = 25, /// \brief A ConstantArrayWithoutExprType record. - TYPE_CONSTANT_ARRAY_WITHOUT_EXPR = 25, + TYPE_CONSTANT_ARRAY_WITHOUT_EXPR = 26, /// \brief An ElaboratedType record. - TYPE_ELABORATED = 26 + TYPE_ELABORATED = 27 }; /// \brief The type IDs for special types constructed by semantic diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e0223b009f..1fa492c874 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -551,6 +551,10 @@ ASTContext::getTypeInfo(const Type *T) { assert(false && "Should not see dependent types"); break; + case Type::ObjCProtocolList: + assert(false && "Should not see protocol list types"); + break; + case Type::FunctionNoProto: case Type::FunctionProto: // GCC extension: alignof(function) = 32 bits @@ -1989,6 +1993,25 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl, return QualType(QType, 0); } +QualType ASTContext::getObjCProtocolListType(QualType T, + ObjCProtocolDecl **Protocols, + unsigned NumProtocols) { + llvm::FoldingSetNodeID ID; + ObjCProtocolListType::Profile(ID, T, Protocols, NumProtocols); + + void *InsertPos = 0; + if (ObjCProtocolListType *QT = + ObjCProtocolListTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(QT, 0); + + // No Match; + ObjCProtocolListType *QType = new (*this, TypeAlignment) + ObjCProtocolListType(T, Protocols, NumProtocols); + Types.push_back(QType); + ObjCProtocolListTypes.InsertNode(QType, InsertPos); + return QualType(QType, 0); +} + /// getTypeOfExprType - Unlike many "get<Type>" 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 diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index c3eade2cb9..70b9fa5946 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -752,6 +752,18 @@ void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getPointeeType(), 0, 0); } +void ObjCProtocolListType::Profile(llvm::FoldingSetNodeID &ID, + QualType OIT, ObjCProtocolDecl **protocols, + unsigned NumProtocols) { + ID.AddPointer(OIT.getAsOpaquePtr()); + for (unsigned i = 0; i != NumProtocols; i++) + ID.AddPointer(protocols[i]); +} + +void ObjCProtocolListType::Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getBaseType(), &Protocols[0], getNumProtocols()); +} + /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to /// potentially looking through *all* consequtive typedefs. This returns the /// sum of the type qualifiers, so if you have: @@ -1490,6 +1502,25 @@ void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString, InnerString = ObjCQIString + InnerString; } +void ObjCProtocolListType::getAsStringInternal(std::string &InnerString, + const PrintingPolicy &Policy) const { + if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. + InnerString = ' ' + InnerString; + + std::string ObjCQIString = getBaseType().getAsString(Policy); + ObjCQIString += '<'; + bool isFirst = true; + for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) { + if (isFirst) + isFirst = false; + else + ObjCQIString += ','; + ObjCQIString += (*I)->getNameAsString(); + } + ObjCQIString += '>'; + InnerString = ObjCQIString + InnerString; +} + void ElaboratedType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { std::string TypeStr; diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 73c0b8d991..ead00ee75f 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1970,6 +1970,16 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++]))); return Context->getObjCObjectPointerType(OIT, Protos.data(), NumProtos); } + + case pch::TYPE_OBJC_PROTOCOL_LIST: { + unsigned Idx = 0; + QualType OIT = GetType(Record[Idx++]); + unsigned NumProtos = Record[Idx++]; + llvm::SmallVector<ObjCProtocolDecl*, 4> Protos; + for (unsigned I = 0; I != NumProtos; ++I) + Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++]))); + return Context->getObjCProtocolListType(OIT, Protos.data(), NumProtos); + } } // Suppress a GCC warning return QualType(); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 8ef846f767..08a1661e1d 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -255,6 +255,15 @@ PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { Code = pch::TYPE_OBJC_OBJECT_POINTER; } +void PCHTypeWriter::VisitObjCProtocolListType(const ObjCProtocolListType *T) { + Writer.AddTypeRef(T->getBaseType(), Record); + Record.push_back(T->getNumProtocols()); + for (ObjCProtocolListType::qual_iterator I = T->qual_begin(), + E = T->qual_end(); I != E; ++I) + Writer.AddDeclRef(*I, Record); + Code = pch::TYPE_OBJC_PROTOCOL_LIST; +} + //===----------------------------------------------------------------------===// // PCHWriter Implementation //===----------------------------------------------------------------------===// @@ -425,6 +434,7 @@ void PCHWriter::WriteBlockInfoBlock() { RECORD(TYPE_ENUM); RECORD(TYPE_OBJC_INTERFACE); RECORD(TYPE_OBJC_OBJECT_POINTER); + RECORD(TYPE_OBJC_PROTOCOL_LIST); // Statements and Exprs can occur in the Types block. AddStmtsExprs(Stream, Record); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index ffbf69b51a..ec5c6676f5 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2485,6 +2485,13 @@ QualType TreeTransform<Derived>::TransformObjCObjectPointerType( return QualType(T, 0); } +template<typename Derived> +QualType TreeTransform<Derived>::TransformObjCProtocolListType( + const ObjCProtocolListType *T) { + assert(false && "Should not see ObjCProtocolList types"); + return QualType(T, 0); +} + //===----------------------------------------------------------------------===// // Statement transformation //===----------------------------------------------------------------------===// |