]> granicus.if.org Git - clang/commitdiff
Introduce ObjCProtocolListType type subclass.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 29 Sep 2009 19:42:55 +0000 (19:42 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 29 Sep 2009 19:42:55 +0000 (19:42 +0000)
This is used only for keeping detailed type source information for protocol references,
it should not participate in the semantics of the type system.

Its protocol list is not canonicalized.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83093 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
include/clang/AST/Type.h
include/clang/AST/TypeNodes.def
include/clang/Frontend/PCHBitCodes.h
lib/AST/ASTContext.cpp
lib/AST/Type.cpp
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
lib/Sema/TreeTransform.h

index bdd87be369c9574bf20210c9668121e50088cb38..bb9e3861be0928f3ca4c92f35e559f8badc21d75 100644 (file)
@@ -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);
index 952671915f25a57e3576f7f70f1f55ec2765cf21..cef52175d1937b96e859ee3d4b866beb3ca73bce 100644 (file)
@@ -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;
index a2feb513a8962e81c64caaec7c9a05455ee51e9d..6c6bd20e8528399eca4d6f5ed168a77f4c8f60f1 100644 (file)
@@ -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
index f0eea414f1874094c2534114033a9e79c3fc61f3..2655217a833d68fa3f4ca85cb9325940ca8c6736 100644 (file)
@@ -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
index e0223b009f6f57cae466309a4b2e88bf9a094179..1fa492c874be5b3611e3172407feb9a6b027e98e 100644 (file)
@@ -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
index c3eade2cb9611dccae9f58e1313abb4abe4d52cf..70b9fa594623bb123e18428111140659861e7055 100644 (file)
@@ -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;
index 73c0b8d9911c4e468be1ea95d1bc00e8b7f6ee10..ead00ee75ffd80be2ad4dd93ea0359ef4a144c77 100644 (file)
@@ -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();
index 8ef846f767221866dcacf735854d99aee12b9d9c..08a1661e1d377f4dfac9fe5c62d34136e216be5b 100644 (file)
@@ -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);
 
index ffbf69b51aaf88a930cbc8f06e329cad028d1551..ec5c6676f5d20cd192d122c3a2c0e8de31565353 100644 (file)
@@ -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
 //===----------------------------------------------------------------------===//