aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-03-30 22:58:21 +0000
committerDouglas Gregor <dgregor@apple.com>2009-03-30 22:58:21 +0000
commit7532dc66648cfe7432c9fe66dec5225f0ab301c6 (patch)
treedaa4d64ecc29357f90c6a51341fecdf79eae2025
parente31c0d206b872b056dc42c3af21b11d5de4edfd9 (diff)
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<int>) is more accurate. Rather than representing std::vector<int> as std::(vector<int>) we represent it as (std::vector)<int> 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
-rw-r--r--include/clang/AST/ASTContext.h22
-rw-r--r--include/clang/AST/DeclTemplate.h2
-rw-r--r--include/clang/AST/TemplateName.h246
-rw-r--r--include/clang/AST/Type.h52
-rw-r--r--include/clang/AST/TypeNodes.def2
-rw-r--r--include/clang/Parse/Action.h26
-rw-r--r--include/clang/Parse/Parser.h5
-rw-r--r--lib/AST/ASTContext.cpp78
-rw-r--r--lib/AST/TemplateName.cpp54
-rw-r--r--lib/AST/Type.cpp60
-rw-r--r--lib/AST/TypeSerialization.cpp22
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp2
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp3
-rw-r--r--lib/Parse/MinimalAction.cpp2
-rw-r--r--lib/Parse/ParseDeclCXX.cpp2
-rw-r--r--lib/Parse/ParseExprCXX.cpp2
-rw-r--r--lib/Parse/ParseTemplate.cpp25
-rw-r--r--lib/Parse/Parser.cpp2
-rw-r--r--lib/Sema/Sema.h27
-rw-r--r--lib/Sema/SemaTemplate.cpp120
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp22
21 files changed, 576 insertions, 200 deletions
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<FunctionNoProtoType> FunctionNoProtoTypes;
llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes;
llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
- llvm::FoldingSet<ClassTemplateSpecializationType>
- ClassTemplateSpecializationTypes;
+ llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes;
llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes;
llvm::FoldingSet<TypenameType> TypenameTypes;
llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes;
llvm::FoldingSet<ObjCQualifiedIdType> ObjCQualifiedIdTypes;
+ llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
+ llvm::FoldingSet<DependentTemplateName> 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<ClassTemplateSpecializationDecl> 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<typename T> class X { };
+///
+/// X<int> xi;
+/// \endcode
+///
+/// Here, the 'X' in \c X<int> 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<typename MetaFun, typename T1, typename T2> struct apply2 {
+/// typedef typename MetaFun::template apply<T1, T2>::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<TemplateDecl *, QualifiedTemplateName *,
+ DependentTemplateName *> 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<QualifiedTemplateName *>();
+ }
+
+ /// \brief Retrieve the underlying dependent template name
+ /// structure, if any.
+ DependentTemplateName *getAsDependentTemplateName() const {
+ return Storage.dyn_cast<DependentTemplateName *>();
+ }
+
+ /// \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<NestedNameSpecifier *, 1> 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<clang::TemplateName> {
+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<int>. 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<int>. 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<int> will refer to
-/// a tag type for the instantiation
+/// a tag type for the instantiation
/// @c std::vector<int, std::allocator<int>>.
-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<N>.
+ 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<TemplateParamsTy *, 4> TemplateParameterLists;
@@ -1050,7 +1051,7 @@ private:
typedef llvm::SmallVector<bool, 16> TemplateArgIsTypeList;
typedef llvm::SmallVector<SourceLocation, 16> 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<TemplateDecl *>())
+ 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<TemplateTemplateParmDecl>(Template);
+ }
+
+ return true;
+}
+
+void TemplateName::Print(llvm::raw_ostream &OS) const {
+ if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
+ 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<TypeOfType>(this))
return TOT->getUnderlyingType().getDesugaredType();
- if (const ClassTemplateSpecializationType *Spec
- = dyn_cast<ClassTemplateSpecializationType>(this))
+ if (const TemplateSpecializationType *Spec
+ = dyn_cast<TemplateSpecializationType>(this))
return Spec->getCanonicalTypeInternal().getDesugaredType();
if (const QualifiedNameType *QualName = dyn_cast<QualifiedNameType>(this))
return QualName->getNamedType().getDesugaredType();
@@ -549,11 +549,11 @@ const TemplateTypeParmType *Type::getAsTemplateTypeParmType() const {
return dyn_cast<TemplateTypeParmType>(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<ClassTemplateSpecializati