diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 3 | ||||
-rw-r--r-- | include/clang/AST/Decl.h | 20 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 59 | ||||
-rw-r--r-- | include/clang/AST/TypeNodes.def | 1 | ||||
-rw-r--r-- | include/clang/Frontend/PCHBitCodes.h | 4 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 23 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 3 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 7 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 20 |
11 files changed, 142 insertions, 14 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 01da133c07..f9419fb3c2 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<ElaboratedType> ElaboratedTypes; llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; @@ -471,6 +472,8 @@ public: 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, diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 28456fff9f..765d04947c 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1267,12 +1267,12 @@ class TypedefDecl; 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. @@ -1354,13 +1354,7 @@ public: 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) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 70bafc1dec..f46227d85f 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1770,6 +1770,65 @@ public: 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; diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index a318663442..f1d3b362ce 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -75,6 +75,7 @@ NON_CANONICAL_TYPE(Decltype, Type) 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) diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index fc3fc20d57..92a541ea19 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -399,7 +399,9 @@ namespace clang { /// \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 diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 1143b305ad..780b1fdc42 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -733,6 +733,10 @@ ASTContext::getTypeInfo(const Type *T) { 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>()) { @@ -1901,6 +1905,25 @@ ASTContext::getTypenameType(NestedNameSpecifier *NNS, 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, diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index c6ea357fbd..f4dad13f41 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1674,6 +1674,16 @@ void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString, 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; diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index c4759b965c..e53f1fa525 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -792,6 +792,9 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, 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: diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 4fcf026549..a7e6c0c8f9 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1941,6 +1941,13 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { 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++])); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 4b8847c098..985d99abbe 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -225,6 +225,12 @@ void PCHTypeWriter::VisitEnumType(const EnumType *T) { 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) { diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 22e01ab581..b49ed5487b 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -441,6 +441,11 @@ public: 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. /// @@ -2328,6 +2333,21 @@ QualType TreeTransform<Derived>::TransformEnumType(const EnumType *T) { 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( |