From: Douglas Gregor Date: Thu, 5 Feb 2009 23:33:38 +0000 (+0000) Subject: Improve the representation of template type parameters. We now X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fab9d67cebb87be968e7ae31a3b549a5279b5d51;p=clang Improve the representation of template type parameters. We now canonicalize by template parameter depth, index, and name, and the unnamed version of a template parameter serves as the canonical. TemplateTypeParmDecl no longer needs to inherit from TemplateParmPosition, since depth and index information is present within the type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63899 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index bf6fa99f2c..616b548269 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -68,6 +68,7 @@ class ASTContext { llvm::FoldingSet VectorTypes; llvm::FoldingSet FunctionTypeNoProtos; llvm::FoldingSet FunctionTypeProtos; + llvm::FoldingSet TemplateTypeParmTypes; llvm::FoldingSet ObjCQualifiedInterfaceTypes; llvm::FoldingSet ObjCQualifiedIdTypes; /// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts. @@ -256,9 +257,11 @@ public: /// getTypedefType - Return the unique reference to the type for the /// specified typename decl. QualType getTypedefType(TypedefDecl *Decl); - QualType getTemplateTypeParmType(TemplateTypeParmDecl *Decl); QualType getObjCInterfaceType(ObjCInterfaceDecl *Decl); - + + QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, + IdentifierInfo *Name = 0); + /// getObjCQualifiedInterfaceType - Return a /// ObjCQualifiedInterfaceType type for the given interface decl and /// the conforming protocol list. diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index b3ec04936d..15945affce 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -762,13 +762,15 @@ protected: /// TypeDecl - Represents a declaration of a type. /// class TypeDecl : public NamedDecl { - /// TypeForDecl - This indicates the Type object that represents this - /// TypeDecl. It is a cache maintained by ASTContext::getTypedefType, - /// ASTContext::getTagDeclType, and ASTContext::getTemplateTypeParmType. + /// TypeForDecl - This indicates the Type object that represents + /// this TypeDecl. It is a cache maintained by + /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and + /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl. Type *TypeForDecl; friend class ASTContext; friend class DeclContext; friend class TagDecl; + friend class TemplateTypeParmDecl; protected: TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 98fd42df43..64e4ea95b5 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -201,30 +201,28 @@ public: /// @code /// template class vector; /// @endcode -class TemplateTypeParmDecl - : public TypeDecl, protected TemplateParmPosition { - /// Typename - Whether this template type parameter was declaration - /// with the 'typename' keyword. If false, it was declared with the +class TemplateTypeParmDecl : public TypeDecl { + /// \brief Whether this template type parameter was declaration with + /// the 'typename' keyword. If false, it was declared with the /// 'class' keyword. bool Typename : 1; - TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, bool Typename) - : TypeDecl(TemplateTypeParm, DC, L, Id), TemplateParmPosition(D, P), - Typename(Typename) { } + TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + bool Typename, QualType Type) + : TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename) { + TypeForDecl = Type.getTypePtr(); + } + public: static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, bool Typename); - /// wasDeclarationWithTypename - Whether this template type - /// parameter was declared with the 'typename' keyword. If not, it - /// was declared with the 'class' keyword. + /// \brief Whether this template type parameter was declared with + /// the 'typename' keyword. If not, it was declared with the 'class' + /// keyword. bool wasDeclaredWithTypename() const { return Typename; } - using TemplateParmPosition::getDepth; - using TemplateParmPosition::getPosition; - // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == TemplateTypeParm; @@ -232,10 +230,10 @@ public: static bool classof(const TemplateTypeParmDecl *D) { return true; } protected: - /// EmitImpl - Serialize this TemplateTypeParmDecl. Called by Decl::Emit. + /// Serialize this TemplateTypeParmDecl. Called by Decl::Emit. virtual void EmitImpl(llvm::Serializer& S) const; - /// CreateImpl - Deserialize a TemplateTypeParmDecl. Called by Decl::Create. + /// Deserialize a TemplateTypeParmDecl. Called by Decl::Create. static TemplateTypeParmDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C); friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 6b2797307f..666d952645 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1188,7 +1188,7 @@ public: TypedefDecl *getDecl() const { return Decl; } /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to - /// potentially looking through *all* consequtive typedefs. This returns the + /// potentially looking through *all* consecutive typedefs. This returns the /// sum of the type qualifiers, so if you have: /// typedef const int A; /// typedef volatile A B; @@ -1350,20 +1350,40 @@ public: static bool classof(const EnumType *) { return true; } }; -class TemplateTypeParmType : public Type { - TemplateTypeParmDecl *Decl; +class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { + unsigned Depth : 16; + unsigned Index : 16; + IdentifierInfo *Name; -protected: - TemplateTypeParmType(TemplateTypeParmDecl *D) - : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true), Decl(D) { } + TemplateTypeParmType(unsigned D, unsigned I, IdentifierInfo *N, + QualType Canon) + : Type(TemplateTypeParm, Canon, /*Dependent=*/true), + Depth(D), Index(I), Name(N) { } - friend class ASTContext; // ASTContext creates these + TemplateTypeParmType(unsigned D, unsigned I) + : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true), + Depth(D), Index(I), Name(0) { } -public: - TemplateTypeParmDecl *getDecl() const { return Decl; } + friend class ASTContext; // ASTContext creates these +public: + unsigned getDepth() const { return Depth; } + unsigned getIndex() const { return Index; } + IdentifierInfo *getName() const { return Name; } + virtual void getAsStringInternal(std::string &InnerString) const; + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Depth, Index, Name); + } + + static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth, + unsigned Index, IdentifierInfo *Name) { + ID.AddInteger(Depth); + ID.AddInteger(Index); + ID.AddPointer(Name); + } + static bool classof(const Type *T) { return T->getTypeClass() == TemplateTypeParm; } @@ -1374,7 +1394,7 @@ protected: static Type* CreateImpl(ASTContext& Context, llvm::Deserializer& D); friend class Type; }; - + /// ObjCInterfaceType - Interfaces are the core concept in Objective-C for /// object oriented design. They basically correspond to C++ classes. There /// are two kinds of interface types, normal interfaces like "NSString" and diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7784aed764..a87a902d06 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1144,9 +1144,9 @@ QualType ASTContext::getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl) { if (TypedefDecl *Typedef = dyn_cast(Decl)) return getTypedefType(Typedef); - else if (TemplateTypeParmDecl *TP = dyn_cast(Decl)) - return getTemplateTypeParmType(TP); - else if (ObjCInterfaceDecl *ObjCInterface = dyn_cast(Decl)) + else if (isa(Decl)) { + assert(false && "Template type parameter types are always available."); + } else if (ObjCInterfaceDecl *ObjCInterface = dyn_cast(Decl)) return getObjCInterfaceType(ObjCInterface); if (CXXRecordDecl *CXXRecord = dyn_cast(Decl)) { @@ -1185,16 +1185,6 @@ QualType ASTContext::getTypedefType(TypedefDecl *Decl) { return QualType(Decl->TypeForDecl, 0); } -/// getTemplateTypeParmType - Return the unique reference to the type -/// for the specified template type parameter declaration. -QualType ASTContext::getTemplateTypeParmType(TemplateTypeParmDecl *Decl) { - if (!Decl->TypeForDecl) { - Decl->TypeForDecl = new (*this,8) TemplateTypeParmType(Decl); - Types.push_back(Decl->TypeForDecl); - } - return QualType(Decl->TypeForDecl, 0); -} - /// getObjCInterfaceType - Return the unique reference to the type for the /// specified ObjC interface decl. QualType ASTContext::getObjCInterfaceType(ObjCInterfaceDecl *Decl) { @@ -1205,6 +1195,31 @@ QualType ASTContext::getObjCInterfaceType(ObjCInterfaceDecl *Decl) { return QualType(Decl->TypeForDecl, 0); } +/// \brief Retrieve the template type parameter type for a template +/// parameter with the given depth, index, and (optionally) name. +QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, + IdentifierInfo *Name) { + llvm::FoldingSetNodeID ID; + TemplateTypeParmType::Profile(ID, Depth, Index, Name); + void *InsertPos = 0; + TemplateTypeParmType *TypeParm + = TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); + + if (TypeParm) + return QualType(TypeParm, 0); + + if (Name) + TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index, Name, + getTemplateTypeParmType(Depth, Index)); + else + TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index); + + Types.push_back(TypeParm); + TemplateTypeParmTypes.InsertNode(TypeParm, InsertPos); + + return QualType(TypeParm, 0); +} + /// CmpProtocolNames - Comparison predicate for sorting protocols /// alphabetically. static bool CmpProtocolNames(const ObjCProtocolDecl *LHS, diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp index dcb8cda33b..ea027df1df 100644 --- a/lib/AST/DeclSerialization.cpp +++ b/lib/AST/DeclSerialization.cpp @@ -598,21 +598,17 @@ TypedefDecl* TypedefDecl::CreateImpl(Deserializer& D, ASTContext& C) { //===----------------------------------------------------------------------===// void TemplateTypeParmDecl::EmitImpl(Serializer& S) const { - S.EmitInt(Depth); - S.EmitInt(Position); S.EmitBool(Typename); - NamedDecl::EmitInRec(S); + TypeDecl::EmitInRec(S); } TemplateTypeParmDecl * TemplateTypeParmDecl::CreateImpl(Deserializer& D, ASTContext& C) { - unsigned Depth = D.ReadInt(); - unsigned Position = D.ReadInt(); bool Typename = D.ReadBool(); TemplateTypeParmDecl *decl - = new (C) TemplateTypeParmDecl(0, SourceLocation(), Depth, Position, - 0, Typename); - decl->NamedDecl::ReadInRec(D, C); + = new (C) TemplateTypeParmDecl(0, SourceLocation(), 0, Typename, + QualType()); + decl->TypeDecl::ReadInRec(D, C); return decl; } diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 08cd5b377d..394939569e 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -78,7 +78,8 @@ TemplateTypeParmDecl * TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, bool Typename) { - return new (C) TemplateTypeParmDecl(DC, L, D, P, Id, Typename); + QualType Type = C.getTemplateTypeParmType(D, P, Id); + return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type); } //===----------------------------------------------------------------------===// diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index f39a325e0d..199ad29ec6 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1138,7 +1138,12 @@ void TypedefType::getAsStringInternal(std::string &InnerString) const { void TemplateTypeParmType::getAsStringInternal(std::string &InnerString) const { if (!InnerString.empty()) // Prefix the basic type, e.g. 'parmname X'. InnerString = ' ' + InnerString; - InnerString = getDecl()->getIdentifier()->getName() + InnerString; + + if (!Name) + InnerString = "type-parameter-" + llvm::utostr_32(Depth) + '-' + + llvm::utostr_32(Index) + InnerString; + else + InnerString = Name->getName() + InnerString; } void ObjCInterfaceType::getAsStringInternal(std::string &InnerString) const { diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp index 12c3d03c12..57598d3afc 100644 --- a/lib/AST/TypeSerialization.cpp +++ b/lib/AST/TypeSerialization.cpp @@ -127,7 +127,7 @@ void Type::Create(ASTContext& Context, unsigned i, Deserializer& D) { break; case Type::TemplateTypeParm: - D.RegisterPtr(PtrID,TemplateTypeParmType::CreateImpl(Context, D)); + D.RegisterPtr(PtrID, TemplateTypeParmType::CreateImpl(Context, D)); break; case Type::VariableArray: @@ -364,20 +364,18 @@ Type* TypeOfType::CreateImpl(ASTContext& Context, Deserializer& D) { //===----------------------------------------------------------------------===// void TemplateTypeParmType::EmitImpl(Serializer& S) const { - S.EmitPtr(getDecl()); + S.EmitInt(Depth); + S.EmitInt(Index); + S.EmitPtr(Name); } Type* TemplateTypeParmType::CreateImpl(ASTContext& Context, Deserializer& D) { - std::vector& Types = - const_cast&>(Context.getTypes()); - - TemplateTypeParmType* T = new TemplateTypeParmType(NULL); - Types.push_back(T); - - D.ReadPtr(T->Decl); // May be backpatched. - return T; + unsigned Depth = D.ReadInt(); + unsigned Index = D.ReadInt(); + IdentifierInfo *Name = D.ReadPtr(); + return Context.getTemplateTypeParmType(Depth, Index, Name).getTypePtr(); } - + //===----------------------------------------------------------------------===// // VariableArrayType //===----------------------------------------------------------------------===//