From: Douglas Gregor Date: Mon, 30 Mar 2009 22:58:21 +0000 (+0000) Subject: Improve the representation of template names in the AST. This X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7532dc66648cfe7432c9fe66dec5225f0ab301c6;p=clang Improve the representation of template names in the AST. This representation handles the various ways in which one can name a template, including unqualified references ("vector"), qualified references ("std::vector"), and dependent template names ("MetaFun::template apply"). One immediate effect of this change is that the representation of nested-name-specifiers in type names for class template specializations (e.g., std::vector) is more accurate. Rather than representing std::vector as std::(vector) we represent it as (std::vector) which more closely follows the C++ grammar. Additionally, templates are no longer represented as declarations (DeclPtrTy) in Parse-Sema interactions. Instead, I've introduced a new OpaquePtr type (TemplateTy) that holds the representation of a TemplateName. This will simplify the handling of dependent template-names, once we get there. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68074 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index bb2d80e7d1..b270ddca67 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -19,6 +19,7 @@ #include "clang/AST/Builtins.h" #include "clang/AST/Decl.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" @@ -71,13 +72,15 @@ class ASTContext { llvm::FoldingSet FunctionNoProtoTypes; llvm::FoldingSet FunctionProtoTypes; llvm::FoldingSet TemplateTypeParmTypes; - llvm::FoldingSet - ClassTemplateSpecializationTypes; + llvm::FoldingSet TemplateSpecializationTypes; llvm::FoldingSet QualifiedNameTypes; llvm::FoldingSet TypenameTypes; llvm::FoldingSet ObjCQualifiedInterfaceTypes; llvm::FoldingSet ObjCQualifiedIdTypes; + llvm::FoldingSet QualifiedTemplateNames; + llvm::FoldingSet DependentTemplateNames; + /// \brief The set of nested name specifiers. /// /// This set is managed by the NestedNameSpecifier class. @@ -291,10 +294,10 @@ public: QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, IdentifierInfo *Name = 0); - QualType getClassTemplateSpecializationType(TemplateDecl *Template, - const TemplateArgument *Args, - unsigned NumArgs, - QualType Canon = QualType()); + QualType getTemplateSpecializationType(TemplateName T, + const TemplateArgument *Args, + unsigned NumArgs, + QualType Canon = QualType()); QualType getQualifiedNameType(NestedNameSpecifier *NNS, QualType NamedType); @@ -407,6 +410,13 @@ public: QualType getFixedWidthIntType(unsigned Width, bool Signed); + TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, + bool TemplateKeyword, + TemplateDecl *Template); + + TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, + const IdentifierInfo *Name); + private: QualType getFromTargetType(unsigned Type) const; diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 4638e6bef4..794ab2cf08 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -705,7 +705,7 @@ protected: llvm::FoldingSet Specializations; }; - /// \brief Previous declaration of + /// \brief Previous declaration of this class template. ClassTemplateDecl *PreviousDeclaration; /// \brief Pointer to the data that is common to all of the diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h new file mode 100644 index 0000000000..3107a35841 --- /dev/null +++ b/include/clang/AST/TemplateName.h @@ -0,0 +1,246 @@ +//===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the TemplateName interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TEMPLATENAME_H +#define LLVM_CLANG_AST_TEMPLATENAME_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/PointerLikeTypeTraits.h" + +namespace llvm { + class raw_ostream; +} + +namespace clang { + +class DependentTemplateName; +class IdentifierInfo; +class NestedNameSpecifier; +class QualifiedTemplateName; +class TemplateDecl; + +/// \brief Represents a C++ template name within the type system. +/// +/// A C++ template name refers to a template within the C++ type +/// system. In most cases, a template name is simply a reference to a +/// class template, e.g. +/// +/// \code +/// template class X { }; +/// +/// X xi; +/// \endcode +/// +/// Here, the 'X' in \c X is a template name that refers to the +/// declaration of the class template X, above. Template names can +/// also refer to function templates, C++0x template aliases, etc. +/// +/// Some template names are dependent. For example, consider: +/// +/// \code +/// template struct apply2 { +/// typedef typename MetaFun::template apply::type type; +/// }; +/// \endcode +/// +/// Here, "apply" is treated as a template name within the typename +/// specifier in the typedef. "apply" is a nested template, and can +/// only be understood in the context of +class TemplateName { + typedef llvm::PointerUnion3 StorageType; + + StorageType Storage; + + explicit TemplateName(void *Ptr) { + Storage = StorageType::getFromOpaqueValue(Ptr); + } + +public: + TemplateName() : Storage() { } + explicit TemplateName(TemplateDecl *Template) : Storage(Template) { } + explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { } + explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { } + + /// \brief Retrieve the the underlying template declaration that + /// this template name refers to, if known. + /// + /// \returns The template declaration that this template name refers + /// to, if any. If the template name does not refer to a specific + /// declaration because it is a dependent name, returns NULL. + TemplateDecl *getAsTemplateDecl() const; + + /// \brief Retrieve the underlying qualified template name + /// structure, if any. + QualifiedTemplateName *getAsQualifiedTemplateName() const { + return Storage.dyn_cast(); + } + + /// \brief Retrieve the underlying dependent template name + /// structure, if any. + DependentTemplateName *getAsDependentTemplateName() const { + return Storage.dyn_cast(); + } + + /// \brief Determines whether this is a dependent template name. + bool isDependent() const; + + /// \brief Print the template name. + void Print(llvm::raw_ostream &OS) const; + + void Profile(llvm::FoldingSetNodeID &ID) { + ID.AddPointer(Storage.getOpaqueValue()); + } + + /// \brief Retrieve the template name as a void pointer. + void *getAsVoidPointer() const { return Storage.getOpaqueValue(); } + + /// \brief Build a template name from a void pointer. + static TemplateName getFromVoidPointer(void *Ptr) { + return TemplateName(Ptr); + } +}; + +/// \brief Represents a template name that was expressed as a +/// qualified name. +/// +/// This kind of template name refers to a template name that was +/// preceded by a nested name specifier, e.g., \c std::vector. Here, +/// the nested name specifier is "std::" and the template name is the +/// declaration for "vector". The QualifiedTemplateName class is only +/// used to provide "sugar" for template names that were expressed +/// with a qualified name, and has no semantic meaning. In this +/// manner, it is to TemplateName what QualifiedNameType is to Type, +/// providing extra syntactic sugar for downstream clients. +class QualifiedTemplateName : public llvm::FoldingSetNode { + /// \brief The nested name specifier that qualifies the template name. + /// + /// The bit is used to indicate whether the "template" keyword was + /// present before the template name itself. Note that the + /// "template" keyword is always redundant in this case (otherwise, + /// the template name would be a dependent name and we would express + /// this name with DependentTemplateName). + llvm::PointerIntPair Qualifier; + + /// \brief The template declaration that this qualified name refers + /// to. + TemplateDecl *Template; + + friend class ASTContext; + + QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, + TemplateDecl *Template) + : Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) { } + +public: + /// \brief Return the nested name specifier that qualifies this name. + NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } + + /// \brief Whether the template name was prefixed by the "template" + /// keyword. + bool hasTemplateKeyword() const { return Qualifier.getInt(); } + + /// \brief The template declaration to which this qualified name + /// refers. + TemplateDecl *getTemplateDecl() const { return Template; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + bool TemplateKeyword, TemplateDecl *Template) { + ID.AddPointer(NNS); + ID.AddBoolean(TemplateKeyword); + ID.AddPointer(Template); + } +}; + +/// \brief Represents a dependent template name that cannot be +/// resolved prior to template instantiation. +/// +/// This kind of template name refers to a dependent template name, +/// including its nested name specifier. For example, +/// DependentTemplateName can refer to "MetaFun::template apply", +/// where "MetaFun::" is the nested name specifier and "apply" is the +/// template name referenced. The "template" keyword is implied. +class DependentTemplateName : public llvm::FoldingSetNode { + /// \brief The nested name specifier that qualifies the template + /// name. + NestedNameSpecifier *Qualifier; + + /// \brief The dependent template name. + const IdentifierInfo *Name; + + /// \brief The canonical template name to which this dependent + /// template name refers. + /// + /// The canonical template name for a dependent template name is + /// another dependent template name whose nested name specifier is + /// canonical. + TemplateName CanonicalTemplateName; + + friend class ASTContext; + + DependentTemplateName(NestedNameSpecifier *Qualifier, + const IdentifierInfo *Name) + : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(this) { } + + DependentTemplateName(NestedNameSpecifier *Qualifier, + const IdentifierInfo *Name, + TemplateName Canon) + : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(Canon) { } + +public: + /// \brief Return the nested name specifier that qualifies this name. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// \brief Return the name to which this dependent template name + /// refers. + const IdentifierInfo *getName() const { return Name; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getQualifier(), getName()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + const IdentifierInfo *Name) { + ID.AddPointer(NNS); + ID.AddPointer(Name); + } +}; + +} + +namespace llvm { + +/// \brief The clang::TemplateName class is effectively a pointer. +template<> +class PointerLikeTypeTraits { +public: + static inline void *getAsVoidPointer(clang::TemplateName TN) { + return TN.getAsVoidPointer(); + } + + static inline clang::TemplateName getFromVoidPointer(void *Ptr) { + return clang::TemplateName::getFromVoidPointer(Ptr); + } + + // No bits are available! + enum { NumLowBitsAvailable = 0 }; +}; + +} + +#endif diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index ea1b496cd3..62cd2787ac 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -16,11 +16,13 @@ #include "clang/Basic/Diagnostic.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TemplateName.h" #include "llvm/Support/Casting.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/Bitcode/SerializationFwd.h" + using llvm::isa; using llvm::cast; using llvm::cast_or_null; @@ -39,7 +41,7 @@ namespace clang { class TemplateDecl; class TemplateTypeParmDecl; class NonTypeTemplateParmDecl; - class TemplateTemplateParamDecl; + class TemplateTemplateParmDecl; class TagDecl; class RecordDecl; class CXXRecordDecl; @@ -437,8 +439,8 @@ public: const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const; const TemplateTypeParmType *getAsTemplateTypeParmType() const; - const ClassTemplateSpecializationType * - getAsClassTemplateSpecializationType() const; + const TemplateSpecializationType * + getAsTemplateSpecializationType() const; /// getAsPointerToObjCInterfaceType - If this is a pointer to an ObjC /// interface, return the interface type, otherwise return null. @@ -1494,32 +1496,34 @@ protected: friend class Type; }; -/// \brief Represents the type of a class template specialization as -/// written in the source code. +/// \brief Represents the type of a template specialization as written +/// in the source code. /// -/// Class template specialization types represent the syntactic form -/// of a template-id that refers to a type, e.g., @c vector. All -/// class template specialization types are syntactic sugar, whose -/// canonical type will point to some other type node that represents -/// the instantiation or class template specialization. For example, a +/// Template specialization types represent the syntactic form of a +/// template-id that refers to a type, e.g., @c vector. Some +/// template specialization types are syntactic sugar, whose canonical +/// type will point to some other type node that represents the +/// instantiation or class template specialization. For example, a /// class template specialization type of @c vector will refer to -/// a tag type for the instantiation +/// a tag type for the instantiation /// @c std::vector>. -class ClassTemplateSpecializationType +/// +/// Other template specialization types, for which the template name +/// is dependent, may be canonical types. These types are always +/// dependent. +class TemplateSpecializationType : public Type, public llvm::FoldingSetNode { - // FIXME: Do we want templates to have a representation in the type - // system? It will probably help with dependent templates and - // possibly with template-names preceded by a nested-name-specifier. - TemplateDecl *Template; + /// \brief The name of the template being specialized. + TemplateName Template; /// \brief - The number of template arguments named in this class /// template specialization. unsigned NumArgs; - ClassTemplateSpecializationType(TemplateDecl *T, - const TemplateArgument *Args, - unsigned NumArgs, QualType Canon); + TemplateSpecializationType(TemplateName T, + const TemplateArgument *Args, + unsigned NumArgs, QualType Canon); virtual void Destroy(ASTContext& C); @@ -1541,8 +1545,8 @@ public: iterator begin() const { return getArgs(); } iterator end() const; - /// \brief Retrieve the template that we are specializing. - TemplateDecl *getTemplate() const { return Template; } + /// \brief Retrieve the name of the template that we are specializing. + TemplateName getTemplateName() const { return Template; } /// \brief Retrieve the template arguments. const TemplateArgument *getArgs() const { @@ -1562,13 +1566,13 @@ public: Profile(ID, Template, getArgs(), NumArgs); } - static void Profile(llvm::FoldingSetNodeID &ID, TemplateDecl *T, + static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, const TemplateArgument *Args, unsigned NumArgs); static bool classof(const Type *T) { - return T->getTypeClass() == ClassTemplateSpecialization; + return T->getTypeClass() == TemplateSpecialization; } - static bool classof(const ClassTemplateSpecializationType *T) { return true; } + static bool classof(const TemplateSpecializationType *T) { return true; } protected: virtual void EmitImpl(llvm::Serializer& S) const; diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 42057139f8..e98ff4200f 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -72,7 +72,7 @@ ABSTRACT_TYPE(Tag, Type) TYPE(Record, TagType) TYPE(Enum, TagType) DEPENDENT_TYPE(TemplateTypeParm, Type) -NON_CANONICAL_TYPE(ClassTemplateSpecialization, Type) +TYPE(TemplateSpecialization, Type) NON_CANONICAL_TYPE(QualifiedName, Type) DEPENDENT_TYPE(Typename, Type) TYPE(ObjCInterface, Type) diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index a58fc81c83..f1837faac5 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -72,7 +72,8 @@ public: typedef ActionBase::StmtTy StmtTy; typedef OpaquePtr<0> DeclPtrTy; typedef OpaquePtr<1> DeclGroupPtrTy; - typedef void TypeTy; // FIXME: Change TypeTy to use OpaquePtr<1>. + typedef void TypeTy; // FIXME: Change TypeTy to use OpaquePtr. + typedef OpaquePtr<2> TemplateTy; typedef void AttrTy; typedef void BaseTy; typedef void MemInitTy; @@ -157,7 +158,7 @@ public: /// optional CXXScope can be passed to indicate the C++ scope in /// which the identifier will be found. virtual TemplateNameKind isTemplateName(IdentifierInfo &II, Scope *S, - DeclPtrTy &TemplateDecl, + TemplateTy &Template, const CXXScopeSpec *SS = 0) = 0; /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the @@ -1206,8 +1207,8 @@ public: return DeclResult(); } - /// \brief Form a class template specialization from a template and - /// a list of template arguments. + /// \brief Form a type from a template and a list of template + /// arguments. /// /// This action merely forms the type for the template-id, possibly /// checking well-formedness of the template arguments. It does not @@ -1219,13 +1220,12 @@ public: /// \param IsSpecialization true when we are naming the class /// template specialization as part of an explicit class /// specialization or class template partial specialization. - virtual TypeResult ActOnClassTemplateId(DeclPtrTy Template, - SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, - SourceLocation RAngleLoc, - const CXXScopeSpec *SS) { + virtual TypeResult ActOnTemplateIdType(TemplateTy Template, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation *TemplateArgLocs, + SourceLocation RAngleLoc) { return TypeResult(); }; @@ -1279,7 +1279,7 @@ public: ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, SourceLocation KWLoc, const CXXScopeSpec &SS, - DeclPtrTy Template, + TemplateTy Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, @@ -1569,7 +1569,7 @@ public: const CXXScopeSpec *SS); virtual TemplateNameKind isTemplateName(IdentifierInfo &II, Scope *S, - DeclPtrTy &TemplateDecl, + TemplateTy &Template, const CXXScopeSpec *SS = 0); /// ActOnDeclarator - If this is a typedef declarator, we modify the diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index ca2d706f23..86bda4551a 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -126,6 +126,7 @@ public: typedef Action::MemInitTy MemInitTy; typedef Action::CXXScopeTy CXXScopeTy; typedef Action::TemplateParamsTy TemplateParamsTy; + typedef Action::TemplateTy TemplateTy; typedef llvm::SmallVector TemplateParameterLists; @@ -1050,7 +1051,7 @@ private: typedef llvm::SmallVector TemplateArgIsTypeList; typedef llvm::SmallVector TemplateArgLocationList; - bool ParseTemplateIdAfterTemplateName(DeclPtrTy Template, + bool ParseTemplateIdAfterTemplateName(TemplateTy Template, SourceLocation TemplateNameLoc, const CXXScopeSpec *SS, bool ConsumeLastToken, @@ -1060,7 +1061,7 @@ private: TemplateArgLocationList &TemplateArgLocations, SourceLocation &RAngleLoc); - void AnnotateTemplateIdToken(DeclPtrTy Template, TemplateNameKind TNK, + void AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, const CXXScopeSpec *SS, SourceLocation TemplateKWLoc = SourceLocation(), bool AllowTypeAnnotation = true); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index f3cf6b18eb..bb17954727 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -483,6 +483,10 @@ ASTContext::getTypeInfo(const Type *T) { Align = Layout.getAlignment(); break; } + + case Type::TemplateSpecialization: + assert(false && "Dependent types have no size"); + break; } assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2"); @@ -1358,30 +1362,31 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, } QualType -ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template, - const TemplateArgument *Args, - unsigned NumArgs, - QualType Canon) { +ASTContext::getTemplateSpecializationType(TemplateName Template, + const TemplateArgument *Args, + unsigned NumArgs, + QualType Canon) { + // FIXME: If Template is dependent, canonicalize it! + if (!Canon.isNull()) Canon = getCanonicalType(Canon); llvm::FoldingSetNodeID ID; - ClassTemplateSpecializationType::Profile(ID, Template, Args, NumArgs); + TemplateSpecializationType::Profile(ID, Template, Args, NumArgs); void *InsertPos = 0; - ClassTemplateSpecializationType *Spec - = ClassTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); + TemplateSpecializationType *Spec + = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); if (Spec) return QualType(Spec, 0); - void *Mem = Allocate((sizeof(ClassTemplateSpecializationType) + + void *Mem = Allocate((sizeof(TemplateSpecializationType) + sizeof(TemplateArgument) * NumArgs), 8); - Spec = new (Mem) ClassTemplateSpecializationType(Template, Args, NumArgs, - Canon); + Spec = new (Mem) TemplateSpecializationType(Template, Args, NumArgs, Canon); Types.push_back(Spec); - ClassTemplateSpecializationTypes.InsertNode(Spec, InsertPos); + TemplateSpecializationTypes.InsertNode(Spec, InsertPos); return QualType(Spec, 0); } @@ -2486,6 +2491,53 @@ void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) { ObjCConstantStringType = getObjCInterfaceType(Decl); } +/// \brief Retrieve the template name that represents a qualified +/// template name such as \c std::vector. +TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, + bool TemplateKeyword, + TemplateDecl *Template) { + llvm::FoldingSetNodeID ID; + QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template); + + void *InsertPos = 0; + QualifiedTemplateName *QTN = + QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos); + if (!QTN) { + QTN = new (*this,4) QualifiedTemplateName(NNS, TemplateKeyword, Template); + QualifiedTemplateNames.InsertNode(QTN, InsertPos); + } + + return TemplateName(QTN); +} + +/// \brief Retrieve the template name that represents a dependent +/// template name such as \c MetaFun::template apply. +TemplateName ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, + const IdentifierInfo *Name) { + assert(NNS->isDependent() && "Nested name specifier must be dependent"); + + llvm::FoldingSetNodeID ID; + DependentTemplateName::Profile(ID, NNS, Name); + + void *InsertPos = 0; + DependentTemplateName *QTN = + DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); + + if (QTN) + return TemplateName(QTN); + + NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); + if (CanonNNS == NNS) { + QTN = new (*this,4) DependentTemplateName(NNS, Name); + } else { + TemplateName Canon = getDependentTemplateName(CanonNNS, Name); + QTN = new (*this,4) DependentTemplateName(NNS, Name, Canon); + } + + DependentTemplateNames.InsertNode(QTN, InsertPos); + return TemplateName(QTN); +} + /// getFromTargetType - Given one of the integer types provided by /// TargetInfo, produce the corresponding type. The unsigned @p Type /// is actually a value of type @c TargetInfo::IntType. @@ -3033,6 +3085,10 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { ResultType.setCVRQualifiers(LHSCan.getCVRQualifiers()); return ResultType; #endif + + case Type::TemplateSpecialization: + assert(false && "Dependent types have no size"); + break; } return QualType(); diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp new file mode 100644 index 0000000000..4e54fe4955 --- /dev/null +++ b/lib/AST/TemplateName.cpp @@ -0,0 +1,54 @@ +//===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the TemplateName interface and subclasses. +// +//===----------------------------------------------------------------------===// +#include "clang/AST/TemplateName.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "llvm/Support/raw_ostream.h" + +using namespace clang; + +TemplateDecl *TemplateName::getAsTemplateDecl() const { + if (TemplateDecl *Template = Storage.dyn_cast()) + return Template; + + if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) + return QTN->getTemplateDecl(); + + return 0; +} + +bool TemplateName::isDependent() const { + if (TemplateDecl *Template = getAsTemplateDecl()) { + // FIXME: We don't yet have a notion of dependent + // declarations. When we do, check that. This hack won't last + // long!. + return isa(Template); + } + + return true; +} + +void TemplateName::Print(llvm::raw_ostream &OS) const { + if (TemplateDecl *Template = Storage.dyn_cast()) + OS << Template->getIdentifier()->getName(); + else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { + QTN->getQualifier()->Print(OS); + if (QTN->hasTemplateKeyword()) + OS << "template "; + OS << QTN->getTemplateDecl()->getIdentifier()->getName(); + } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { + DTN->getQualifier()->Print(OS); + OS << "template "; + OS << DTN->getName()->getName(); + } +} diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 0a3e8f91f0..6922dcc6c0 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -93,8 +93,8 @@ QualType Type::getDesugaredType() const { return TOE->getUnderlyingExpr()->getType().getDesugaredType(); if (const TypeOfType *TOT = dyn_cast(this)) return TOT->getUnderlyingType().getDesugaredType(); - if (const ClassTemplateSpecializationType *Spec - = dyn_cast(this)) + if (const TemplateSpecializationType *Spec + = dyn_cast(this)) return Spec->getCanonicalTypeInternal().getDesugaredType(); if (const QualifiedNameType *QualName = dyn_cast(this)) return QualName->getNamedType().getDesugaredType(); @@ -549,11 +549,11 @@ const TemplateTypeParmType *Type::getAsTemplateTypeParmType() const { return dyn_cast(CanonicalType); } -const ClassTemplateSpecializationType * -Type::getAsClassTemplateSpecializationType() const { +const TemplateSpecializationType * +Type::getAsTemplateSpecializationType() const { // There is no sugar for class template specialization types, so // just return the canonical type pointer if it is the right class. - return dyn_cast(CanonicalType); + return dyn_cast(CanonicalType); } bool Type::isIntegerType() const { @@ -972,7 +972,7 @@ bool EnumType::classof(const TagType *TT) { } bool -ClassTemplateSpecializationType:: +TemplateSpecializationType:: anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) { for (unsigned Idx = 0; Idx < NumArgs; ++Idx) { switch (Args[Idx].getKind()) { @@ -997,17 +997,16 @@ anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) { return false; } -ClassTemplateSpecializationType:: -ClassTemplateSpecializationType(TemplateDecl *T, const TemplateArgument *Args, - unsigned NumArgs, QualType Canon) - : Type(ClassTemplateSpecialization, +TemplateSpecializationType:: +TemplateSpecializationType(TemplateName T, const TemplateArgument *Args, + unsigned NumArgs, QualType Canon) + : Type(TemplateSpecialization, Canon.isNull()? QualType(this, 0) : Canon, - /*FIXME: Check for dependent template */ - anyDependentTemplateArguments(Args, NumArgs)), + T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)), Template(T), NumArgs(NumArgs) { assert((!Canon.isNull() || - anyDependentTemplateArguments(Args, NumArgs)) && + T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)) && "No canonical type for non-dependent class template specialization"); TemplateArgument *TemplateArgs @@ -1016,7 +1015,7 @@ ClassTemplateSpecializationType(TemplateDecl *T, const TemplateArgument *Args, new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]); } -void ClassTemplateSpecializationType::Destroy(ASTContext& C) { +void TemplateSpecializationType::Destroy(ASTContext& C) { for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { // FIXME: Not all expressions get cloned, so we can't yet perform // this destruction. @@ -1025,24 +1024,23 @@ void ClassTemplateSpecializationType::Destroy(ASTContext& C) { } } -ClassTemplateSpecializationType::iterator -ClassTemplateSpecializationType::end() const { +TemplateSpecializationType::iterator +TemplateSpecializationType::end() const { return begin() + getNumArgs(); } const TemplateArgument & -ClassTemplateSpecializationType::getArg(unsigned Idx) const { +TemplateSpecializationType::getArg(unsigned Idx) const { assert(Idx < getNumArgs() && "Template argument out of range"); return getArgs()[Idx]; } void -ClassTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, - TemplateDecl *T, - const TemplateArgument *Args, - unsigned NumArgs) { - ID.AddPointer(T); - +TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, + TemplateName T, + const TemplateArgument *Args, + unsigned NumArgs) { + T.Profile(ID); for (unsigned Idx = 0; Idx < NumArgs; ++Idx) Args[Idx].Profile(ID); } @@ -1351,7 +1349,7 @@ void TemplateTypeParmType::getAsStringInternal(std::string &InnerString) const { InnerString = Name->getName() + InnerString; } -std::string ClassTemplateSpecializationType::PrintTemplateArgumentList( +std::string TemplateSpecializationType::PrintTemplateArgumentList( const TemplateArgument *Args, unsigned NumArgs) { std::string SpecString; @@ -1403,9 +1401,15 @@ std::string ClassTemplateSpecializationType::PrintTemplateArgumentList( } void -ClassTemplateSpecializationType:: +TemplateSpecializationType:: getAsStringInternal(std::string &InnerString) const { - std::string SpecString = Template->getNameAsString(); + std::string SpecString; + + { + llvm::raw_string_ostream OS(SpecString); + Template.Print(OS); + } + SpecString += PrintTemplateArgumentList(getArgs(), getNumArgs()); if (InnerString.empty()) InnerString.swap(SpecString); @@ -1515,7 +1519,7 @@ void TagType::getAsStringInternal(std::string &InnerString, if (ClassTemplateSpecializationDecl *Spec = dyn_cast(getDecl())) { std::string TemplateArgs - = ClassTemplateSpecializationType::PrintTemplateArgumentList( + = TemplateSpecializationType::PrintTemplateArgumentList( Spec->getTemplateArgs(), Spec->getNumTemplateArgs()); InnerString = TemplateArgs + InnerString; @@ -1534,7 +1538,7 @@ void TagType::getAsStringInternal(std::string &InnerString, } else if (ClassTemplateSpecializationDecl *Spec = dyn_cast(DC)) { std::string TemplateArgs - = ClassTemplateSpecializationType::PrintTemplateArgumentList( + = TemplateSpecializationType::PrintTemplateArgumentList( Spec->getTemplateArgs(), Spec->getNumTemplateArgs()); MyPart = Spec->getIdentifier()->getName() + TemplateArgs; diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp index 4f0334f47a..0562416da0 100644 --- a/lib/AST/TypeSerialization.cpp +++ b/lib/AST/TypeSerialization.cpp @@ -391,29 +391,17 @@ Type* TemplateTypeParmType::CreateImpl(ASTContext& Context, Deserializer& D) { } //===----------------------------------------------------------------------===// -// ClassTemplateSpecializationType +// TemplateSpecializationType //===----------------------------------------------------------------------===// -void ClassTemplateSpecializationType::EmitImpl(Serializer& S) const { - S.Emit(getCanonicalTypeInternal()); - S.EmitPtr(Template); - S.EmitInt(NumArgs); - // FIXME: Serialize class template specialization types +void TemplateSpecializationType::EmitImpl(Serializer& S) const { + // FIXME: Serialization support } Type* -ClassTemplateSpecializationType:: +TemplateSpecializationType:: CreateImpl(ASTContext& Context, Deserializer& D) { - llvm::SmallVector Args; - llvm::SmallVector ArgIsType; - - QualType Canon = QualType::ReadVal(D); - TemplateDecl *Template = cast(D.ReadPtr()); - unsigned NumArgs = D.ReadInt(); - - // FIXME: De-serialize class template specialization types - (void)Template; - (void)NumArgs; + // FIXME: Deserialization support return 0; } diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 7233bbf8e2..bde6fba137 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -561,7 +561,7 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, case Type::FixedWidthInt: case Type::BlockPointer: case Type::MemberPointer: - case Type::ClassTemplateSpecialization: + case Type::TemplateSpecialization: case Type::QualifiedName: case Type::ObjCQualifiedClass: // Unsupported types diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index 85d7384c6c..5367c71b2c 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -392,6 +392,9 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { // http://gcc.gnu.org/onlinedocs/gccint/Type-Layout.html#Type-Layout assert(0 && "FIXME: We can't handle member pointers yet."); return llvm::OpaqueType::get(); + + case Type::TemplateSpecialization: + assert(false && "Dependent types can't get here"); } // FIXME: implement. diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp index f31aef61d3..e99e96a7dc 100644 --- a/lib/Parse/MinimalAction.cpp +++ b/lib/Parse/MinimalAction.cpp @@ -135,7 +135,7 @@ bool MinimalAction::isCurrentClassName(const IdentifierInfo &, Scope *, TemplateNameKind MinimalAction::isTemplateName(IdentifierInfo &II, Scope *S, - DeclPtrTy &TemplateDecl, + TemplateTy &TemplateDecl, const CXXScopeSpec *SS) { return TNK_Non_template; } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 37a460cd41..fdfc7315a8 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -474,7 +474,7 @@ void Parser::ParseClassSpecifier(DeclSpec &DS, TagOrTempResult = Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TK, StartLoc, SS, - DeclPtrTy::make(TemplateId->Template), + TemplateTy::make(TemplateId->Template), TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index dc57ac141c..4d419bbd87 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -117,7 +117,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { // an operator and not as part of a simple-template-id. } - DeclPtrTy Template; + TemplateTy Template; TemplateNameKind TNK = TNK_Non_template; // FIXME: If the nested-name-specifier thus far is dependent, // set TNK = TNK_Dependent_template_name and skip the diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index b962cbf646..8eda694864 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -406,7 +406,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { /// last token in the stream (e.g., so that it can be replaced with an /// annotation token). bool -Parser::ParseTemplateIdAfterTemplateName(DeclPtrTy Template, +Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, SourceLocation TemplateNameLoc, const CXXScopeSpec *SS, bool ConsumeLastToken, @@ -499,7 +499,7 @@ Parser::ParseTemplateIdAfterTemplateName(DeclPtrTy Template, /// replaced with a type annotation token. Otherwise, the /// simple-template-id is always replaced with a template-id /// annotation token. -void Parser::AnnotateTemplateIdToken(DeclPtrTy Template, TemplateNameKind TNK, +void Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, const CXXScopeSpec *SS, SourceLocation TemplateKWLoc, bool AllowTypeAnnotation) { @@ -531,12 +531,13 @@ void Parser::AnnotateTemplateIdToken(DeclPtrTy Template, TemplateNameKind TNK, return; // Build the annotation token. + // FIXME: Not just for class templates! if (TNK == TNK_Class_template && AllowTypeAnnotation) { Action::TypeResult Type - = Actions.ActOnClassTemplateId(Template, TemplateNameLoc, - LAngleLoc, TemplateArgsPtr, - &TemplateArgLocations[0], - RAngleLoc, SS); + = Actions.ActOnTemplateIdType(Template, TemplateNameLoc, + LAngleLoc, TemplateArgsPtr, + &TemplateArgLocations[0], + RAngleLoc); if (Type.isInvalid()) // FIXME: better recovery? return; @@ -603,12 +604,12 @@ bool Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { TemplateId->NumArgs); Action::TypeResult Type - = Actions.ActOnClassTemplateId(DeclPtrTy::make(TemplateId->Template), - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), - TemplateId->RAngleLoc, SS); + = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template), + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->getTemplateArgLocations(), + TemplateId->RAngleLoc); if (Type.isInvalid()) { // FIXME: better recovery? ConsumeToken(); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index b34c241fd1..a101aaa732 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -885,7 +885,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { // If this is a template-id, annotate with a template-id or type token. if (NextToken().is(tok::less)) { - DeclPtrTy Template; + TemplateTy Template; if (TemplateNameKind TNK = Actions.isTemplateName(*Tok.getIdentifierInfo(), CurScope, Template, &SS)) diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index b7903c1b59..c46b044c29 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1691,7 +1691,7 @@ public: // C++ Templates [C++ 14] // virtual TemplateNameKind isTemplateName(IdentifierInfo &II, Scope *S, - DeclPtrTy &TemplateDecl, + TemplateTy &Template, const CXXScopeSpec *SS = 0); bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); TemplateDecl *AdjustDeclIfTemplate(DeclPtrTy &Decl); @@ -1742,20 +1742,19 @@ public: MultiTemplateParamsArg TemplateParameterLists, AccessSpecifier AS); - QualType CheckClassTemplateId(ClassTemplateDecl *ClassTemplate, - SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc); + QualType CheckTemplateIdType(TemplateName Template, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceLocation RAngleLoc); virtual TypeResult - ActOnClassTemplateId(DeclPtrTy Template, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, - SourceLocation RAngleLoc, - const CXXScopeSpec *SS); + ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation *TemplateArgLocs, + SourceLocation RAngleLoc); bool CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate, ClassTemplateSpecializationDecl *PrevDecl, @@ -1766,7 +1765,7 @@ public: ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, SourceLocation KWLoc, const CXXScopeSpec &SS, - DeclPtrTy Template, + TemplateTy Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 773a2b1b92..56a016d270 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -27,19 +27,23 @@ using namespace clang; /// passed to indicate the C++ scope in which the identifier will be /// found. TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S, - DeclPtrTy &Template, + TemplateTy &TemplateResult, const CXXScopeSpec *SS) { NamedDecl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName); + TemplateNameKind TNK = TNK_Non_template; + TemplateDecl *Template = 0; + if (IIDecl) { - if (isa(IIDecl)) { - Template = DeclPtrTy::make(IIDecl); + if ((Template = dyn_cast(IIDecl))) { if (isa(IIDecl)) - return TNK_Function_template; - if (isa(IIDecl)) - return TNK_Class_template; - assert(isa(IIDecl) && "Unknown TemplateDecl"); - return TNK_Template_template_parm; + TNK = TNK_Function_template; + else if (isa(IIDecl)) + TNK = TNK_Class_template; + else if (isa(IIDecl)) + TNK = TNK_Template_template_parm; + else + assert(false && "Unknown template declaration kind"); } else if (CXXRecordDecl *Record = dyn_cast(IIDecl)) { // C++ [temp.local]p1: // Like normal (non-template) classes, class templates have an @@ -54,12 +58,12 @@ TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S, // specialization. if (Record->isInjectedClassName()) { Record = cast(Context.getCanonicalDecl(Record)); - if ((Template = DeclPtrTy::make(Record->getDescribedClassTemplate()))) - return TNK_Class_template; - if (ClassTemplateSpecializationDecl *Spec + if ((Template = Record->getDescribedClassTemplate())) + TNK = TNK_Class_template; + else if (ClassTemplateSpecializationDecl *Spec = dyn_cast(Record)) { - Template = DeclPtrTy::make(Spec->getSpecializedTemplate()); - return TNK_Class_template; + Template = Spec->getSpecializedTemplate(); + TNK = TNK_Class_template; } } } @@ -67,7 +71,7 @@ TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S, // FIXME: What follows is a gross hack. if (FunctionDecl *FD = dyn_cast(IIDecl)) { if (FD->getType()->isDependentType()) { - Template = DeclPtrTy::make(FD); + TemplateResult = TemplateTy::make(FD); return TNK_Function_template; } } else if (OverloadedFunctionDecl *Ovl @@ -76,13 +80,25 @@ TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S, FEnd = Ovl->function_end(); F != FEnd; ++F) { if ((*F)->getType()->isDependentType()) { - Template = DeclPtrTy::make(Ovl); + TemplateResult = TemplateTy::make(Ovl); return TNK_Function_template; } } } + + if (TNK != TNK_Non_template) { + if (SS && SS->isSet() && !SS->isInvalid()) { + NestedNameSpecifier *Qualifier + = static_cast(SS->getScopeRep()); + TemplateResult + = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, + false, + Template)); + } else + TemplateResult = TemplateTy::make(TemplateName(Template)); + } } - return TNK_Non_template; + return TNK; } /// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining @@ -700,27 +716,30 @@ translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, } } -QualType Sema::CheckClassTemplateId(ClassTemplateDecl *ClassTemplate, - SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc) { +QualType Sema::CheckTemplateIdType(TemplateName Name, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceLocation RAngleLoc) { + TemplateDecl *Template = Name.getAsTemplateDecl(); + assert(Template && "Cannot handle dependent template-names yet"); + // Check that the template argument list is well-formed for this // template. llvm::SmallVector ConvertedTemplateArgs; - if (CheckTemplateArgumentList(ClassTemplate, TemplateLoc, LAngleLoc, + if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc, TemplateArgs, NumTemplateArgs, RAngleLoc, ConvertedTemplateArgs)) return QualType(); assert((ConvertedTemplateArgs.size() == - ClassTemplate->getTemplateParameters()->size()) && + Template->getTemplateParameters()->size()) && "Converted template argument list is too short!"); QualType CanonType; - if (ClassTemplateSpecializationType::anyDependentTemplateArguments( + if (TemplateSpecializationType::anyDependentTemplateArguments( TemplateArgs, NumTemplateArgs)) { // This class template specialization is a dependent @@ -731,10 +750,11 @@ QualType Sema::CheckClassTemplateId(ClassTemplateDecl *ClassTemplate, // // template struct A; - CanonType = Context.getClassTemplateSpecializationType(ClassTemplate, + CanonType = Context.getTemplateSpecializationType(Name, &ConvertedTemplateArgs[0], ConvertedTemplateArgs.size()); - } else { + } else if (ClassTemplateDecl *ClassTemplate + = dyn_cast(Template)) { // Find the class template specialization declaration that // corresponds to these arguments. llvm::FoldingSetNodeID ID; @@ -764,35 +784,26 @@ QualType Sema::CheckClassTemplateId(ClassTemplateDecl *ClassTemplate, // Build the fully-sugared type for this class template // specialization, which refers back to the class template // specialization we created or found. - return Context.getClassTemplateSpecializationType(ClassTemplate, - TemplateArgs, - NumTemplateArgs, - CanonType); + return Context.getTemplateSpecializationType(Name, TemplateArgs, + NumTemplateArgs, CanonType); } Action::TypeResult -Sema::ActOnClassTemplateId(DeclPtrTy TemplateD, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation *TemplateArgLocs, - SourceLocation RAngleLoc, - const CXXScopeSpec *SS) { - TemplateDecl *Template = cast(TemplateD.getAs()); - ClassTemplateDecl *ClassTemplate = cast(Template); +Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation *TemplateArgLocs, + SourceLocation RAngleLoc) { + TemplateName Template = TemplateD.getAsVal(); // Translate the parser's template argument list in our AST format. llvm::SmallVector TemplateArgs; translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); - QualType Result = CheckClassTemplateId(ClassTemplate, TemplateLoc, - LAngleLoc, - &TemplateArgs[0], - TemplateArgs.size(), - RAngleLoc); + QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc, + &TemplateArgs[0], TemplateArgs.size(), + RAngleLoc); - if (SS) - Result = getQualifiedNameType(*SS, Result); - TemplateArgsIn.release(); return Result.getAsOpaquePtr(); } @@ -1795,7 +1806,7 @@ Sema::DeclResult Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, SourceLocation KWLoc, const CXXScopeSpec &SS, - DeclPtrTy TemplateD, + TemplateTy TemplateD, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, @@ -1804,10 +1815,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, AttributeList *Attr, MultiTemplateParamsArg TemplateParameterLists) { // Find the class template we're specializing + TemplateName Name = TemplateD.getAsVal(); ClassTemplateDecl *ClassTemplate - = dyn_cast_or_null(TemplateD.getAs()); - if (!ClassTemplate) - return true; + = cast(Name.getAsTemplateDecl()); // Check the validity of the template headers that introduce this // template. @@ -1937,11 +1947,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // name based on the "canonical" representation used to store the // template arguments in the specialization. QualType WrittenTy - = Context.getClassTemplateSpecializationType(ClassTemplate, - &TemplateArgs[0], - TemplateArgs.size(), + = Context.getTemplateSpecializationType(Name, + &TemplateArgs[0], + TemplateArgs.size(), Context.getTypeDeclType(Specialization)); - Specialization->setTypeAsWritten(getQualifiedNameType(SS, WrittenTy)); + Specialization->setTypeAsWritten(WrittenTy); TemplateArgsIn.release(); // C++ [temp.expl.spec]p9: diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 257870374c..08f96012dd 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -114,7 +114,7 @@ void Sema::PrintInstantiationStack() { case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: { TemplateDecl *Template = cast((Decl *)Active->Entity); std::string TemplateArgsStr - = ClassTemplateSpecializationType::PrintTemplateArgumentList( + = TemplateSpecializationType::PrintTemplateArgumentList( Active->TemplateArgs, Active->NumTemplateArgs); Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), @@ -433,13 +433,12 @@ InstantiateTemplateTypeParmType(const TemplateTypeParmType *T, QualType TemplateTypeInstantiator:: -InstantiateClassTemplateSpecializationType( - const ClassTemplateSpecializationType *T, +InstantiateTemplateSpecializationType( + const TemplateSpecializationType *T, unsigned Quals) const { llvm::SmallVector InstantiatedTemplateArgs; InstantiatedTemplateArgs.reserve(T->getNumArgs()); - for (ClassTemplateSpecializationType::iterator Arg = T->begin(), - ArgEnd = T->end(); + for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end(); Arg != ArgEnd; ++Arg) { switch (Arg->getKind()) { case TemplateArgument::Type: { @@ -473,12 +472,13 @@ InstantiateClassTemplateSpecializationType( // FIXME: We're missing the locations of the template name, '<', and // '>'. - return SemaRef.CheckClassTemplateId(cast(T->getTemplate()), - Loc, - SourceLocation(), - &InstantiatedTemplateArgs[0], - InstantiatedTemplateArgs.size(), - SourceLocation()); + // FIXME: Need to instantiate into the template name. + return SemaRef.CheckTemplateIdType(T->getTemplateName(), + Loc, + SourceLocation(), + &InstantiatedTemplateArgs[0], + InstantiatedTemplateArgs.size(), + SourceLocation()); } QualType