llvm::FoldingSet<TypenameType> TypenameTypes;
llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes;
llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
+ llvm::FoldingSet<ObjCProtocolListType> ObjCProtocolListTypes;
llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
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);
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;
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
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
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
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
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:
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;
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();
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
//===----------------------------------------------------------------------===//
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);
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
//===----------------------------------------------------------------------===//