llvm::FoldingSet<TypenameType> TypenameTypes;
llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes;
llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
+ llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
QualType getTypenameType(NestedNameSpecifier *NNS,
const TemplateSpecializationType *TemplateId,
QualType Canon = QualType());
+ QualType getElaboratedType(QualType UnderlyingType,
+ ElaboratedType::TagKind Tag);
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
ObjCProtocolDecl **Protocols = 0,
class TagDecl
: public TypeDecl, public DeclContext, public Redeclarable<TagDecl> {
public:
- enum TagKind {
- TK_struct,
- TK_union,
- TK_class,
- TK_enum
- };
+ // This is really ugly.
+ typedef ElaboratedType::TagKind TagKind;
+ static const TagKind TK_struct = ElaboratedType::TK_struct;
+ static const TagKind TK_union = ElaboratedType::TK_union;
+ static const TagKind TK_class = ElaboratedType::TK_class;
+ static const TagKind TK_enum = ElaboratedType::TK_enum;
private:
// FIXME: This can be packed into the bitfields in Decl.
TagDecl* getDefinition(ASTContext& C) const;
const char *getKindName() const {
- switch (getTagKind()) {
- default: assert(0 && "Unknown TagKind!");
- case TK_struct: return "struct";
- case TK_union: return "union";
- case TK_class: return "class";
- case TK_enum: return "enum";
- }
+ return ElaboratedType::getNameForTagKind(getTagKind());
}
/// getTagKindForTypeSpec - Converts a type specifier (DeclSpec::TST)
static bool classof(const EnumType *) { return true; }
};
+/// ElaboratedType - A non-canonical type used to represents uses of
+/// elaborated type specifiers in C++. For example:
+///
+/// void foo(union MyUnion);
+/// ^^^^^^^^^^^^^
+///
+/// At the moment, for efficiency we do not create elaborated types in
+/// C, since outside of typedefs all references to structs would
+/// necessarily be elaborated.
+class ElaboratedType : public Type, public llvm::FoldingSetNode {
+public:
+ enum TagKind {
+ TK_struct,
+ TK_union,
+ TK_class,
+ TK_enum
+ };
+
+private:
+ /// The tag that was used in this elaborated type specifier.
+ TagKind Tag;
+
+ /// The underlying type.
+ QualType UnderlyingType;
+
+ explicit ElaboratedType(QualType Ty, TagKind Tag, QualType Canon)
+ : Type(Elaborated, Canon, Canon->isDependentType()),
+ Tag(Tag), UnderlyingType(Ty) { }
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ TagKind getTagKind() const { return Tag; }
+ QualType getUnderlyingType() const { return UnderlyingType; }
+
+ static const char *getNameForTagKind(TagKind Kind) {
+ switch (Kind) {
+ default: assert(0 && "Unknown TagKind!");
+ case TK_struct: return "struct";
+ case TK_union: return "union";
+ case TK_class: return "class";
+ case TK_enum: return "enum";
+ }
+ }
+
+ virtual void getAsStringInternal(std::string &InnerString,
+ const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getUnderlyingType(), getTagKind());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType T, TagKind Tag) {
+ ID.AddPointer(T.getAsOpaquePtr());
+ ID.AddInteger(Tag);
+ }
+
+ static bool classof(const ElaboratedType*) { return true; }
+ static bool classof(const Type *T) { return T->getTypeClass() == Elaborated; }
+};
+
class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
unsigned Depth : 15;
unsigned Index : 16;
ABSTRACT_TYPE(Tag, Type)
TYPE(Record, TagType)
TYPE(Enum, TagType)
+NON_CANONICAL_TYPE(Elaborated, Type)
DEPENDENT_TYPE(TemplateTypeParm, Type)
TYPE(TemplateSpecialization, Type)
NON_CANONICAL_TYPE(QualifiedName, Type)
/// \brief A ConstantArrayWithExprType record.
TYPE_CONSTANT_ARRAY_WITH_EXPR = 24,
/// \brief A ConstantArrayWithoutExprType record.
- TYPE_CONSTANT_ARRAY_WITHOUT_EXPR = 25
+ TYPE_CONSTANT_ARRAY_WITHOUT_EXPR = 25,
+ /// \brief An ElaboratedType record.
+ TYPE_ELABORATED = 26
};
/// \brief The type IDs for special types constructed by semantic
break;
}
+ case Type::Elaborated: {
+ return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType().getTypePtr());
+ }
+
case Type::Typedef: {
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
return QualType(T, 0);
}
+QualType
+ASTContext::getElaboratedType(QualType UnderlyingType,
+ ElaboratedType::TagKind Tag) {
+ llvm::FoldingSetNodeID ID;
+ ElaboratedType::Profile(ID, UnderlyingType, Tag);
+
+ void *InsertPos = 0;
+ ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
+ if (T)
+ return QualType(T, 0);
+
+ QualType Canon = getCanonicalType(UnderlyingType);
+
+ T = new (*this) ElaboratedType(UnderlyingType, Tag, Canon);
+ Types.push_back(T);
+ ElaboratedTypes.InsertNode(T, InsertPos);
+ return QualType(T, 0);
+}
+
/// CmpProtocolNames - Comparison predicate for sorting protocols
/// alphabetically.
static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
InnerString = ObjCQIString + InnerString;
}
+void ElaboratedType::getAsStringInternal(std::string &InnerString,
+ const PrintingPolicy &Policy) const {
+ std::string TypeStr;
+ PrintingPolicy InnerPolicy(Policy);
+ InnerPolicy.SuppressTagKind = true;
+ UnderlyingType.getAsStringInternal(InnerString, InnerPolicy);
+
+ InnerString = std::string(getNameForTagKind(getTagKind())) + ' ' + InnerString;
+}
+
void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
if (Policy.SuppressTag)
return;
case Type::FunctionProto:
case Type::FunctionNoProto:
return Slot = CreateType(cast<FunctionType>(Ty), Unit);
+ case Type::Elaborated:
+ return Slot = getOrCreateType(cast<ElaboratedType>(Ty)->getUnderlyingType(),
+ Unit);
case Type::ConstantArray:
case Type::ConstantArrayWithExpr:
assert(Record.size() == 1 && "incorrect encoding of enum type");
return Context->getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
+ case pch::TYPE_ELABORATED: {
+ assert(Record.size() == 2 && "incorrect encoding of elaborated type");
+ unsigned Tag = Record[1];
+ return Context->getElaboratedType(GetType(Record[0]),
+ (ElaboratedType::TagKind) Tag);
+ }
+
case pch::TYPE_OBJC_INTERFACE: {
unsigned Idx = 0;
ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
Code = pch::TYPE_ENUM;
}
+void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
+ Writer.AddTypeRef(T->getUnderlyingType(), Record);
+ Record.push_back(T->getTagKind());
+ Code = pch::TYPE_ELABORATED;
+}
+
void
PCHTypeWriter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
QualType RebuildEnumType(EnumDecl *Enum) {
return SemaRef.Context.getTypeDeclType(Enum);
}
+
+ /// \brief Build a new elaborated type.
+ QualType RebuildElaboratedType(QualType T, ElaboratedType::TagKind Tag) {
+ return SemaRef.Context.getElaboratedType(T, Tag);
+ }
/// \brief Build a new typeof(expr) type.
///
return getDerived().RebuildEnumType(Enum);
}
+
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformElaboratedType(
+ const ElaboratedType *T) {
+ QualType Underlying = getDerived().TransformType(T->getUnderlyingType());
+ if (Underlying.isNull())
+ return QualType();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Underlying == T->getUnderlyingType())
+ return QualType(T, 0);
+
+ return getDerived().RebuildElaboratedType(Underlying, T->getTagKind());
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::TransformTemplateTypeParmType(