forked from OSchip/llvm-project
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. llvm-svn: 68074
This commit is contained in:
parent
adccd30533
commit
dc572a3266
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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<ClassTemplateSpecializationType>(CanonicalType);
|
||||
return dyn_cast<TemplateSpecializationType>(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<ClassTemplateSpecializationDecl>(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<ClassTemplateSpecializationDecl>(DC)) {
|
||||
std::string TemplateArgs
|
||||
= ClassTemplateSpecializationType::PrintTemplateArgumentList(
|
||||
= TemplateSpecializationType::PrintTemplateArgumentList(
|
||||
Spec->getTemplateArgs(),
|
||||
Spec->getNumTemplateArgs());
|
||||
MyPart = Spec->getIdentifier()->getName() + TemplateArgs;
|
||||
|
|
|
@ -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<uintptr_t, 16> Args;
|
||||
llvm::SmallVector<bool, 16> ArgIsType;
|
||||
|
||||
QualType Canon = QualType::ReadVal(D);
|
||||
TemplateDecl *Template = cast<TemplateDecl>(D.ReadPtr<Decl>());
|
||||
unsigned NumArgs = D.ReadInt();
|
||||
|
||||
// FIXME: De-serialize class template specialization types
|
||||
(void)Template;
|
||||
(void)NumArgs;
|
||||
// FIXME: Deserialization support
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<TemplateDecl>(IIDecl)) {
|
||||
Template = DeclPtrTy::make(IIDecl);
|
||||
if ((Template = dyn_cast<TemplateDecl>(IIDecl))) {
|
||||
if (isa<FunctionTemplateDecl>(IIDecl))
|
||||
return TNK_Function_template;
|
||||
if (isa<ClassTemplateDecl>(IIDecl))
|
||||
return TNK_Class_template;
|
||||
assert(isa<TemplateTemplateParmDecl>(IIDecl) && "Unknown TemplateDecl");
|
||||
return TNK_Template_template_parm;
|
||||
TNK = TNK_Function_template;
|
||||
else if (isa<ClassTemplateDecl>(IIDecl))
|
||||
TNK = TNK_Class_template;
|
||||
else if (isa<TemplateTemplateParmDecl>(IIDecl))
|
||||
TNK = TNK_Template_template_parm;
|
||||
else
|
||||
assert(false && "Unknown template declaration kind");
|
||||
} else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(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<CXXRecordDecl>(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<ClassTemplateSpecializationDecl>(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<FunctionDecl>(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<NestedNameSpecifier *>(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<TemplateArgument, 16> 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<typename T, typename U = T> struct A;
|
||||
|
||||
CanonType = Context.getClassTemplateSpecializationType(ClassTemplate,
|
||||
CanonType = Context.getTemplateSpecializationType(Name,
|
||||
&ConvertedTemplateArgs[0],
|
||||
ConvertedTemplateArgs.size());
|
||||
} else {
|
||||
} else if (ClassTemplateDecl *ClassTemplate
|
||||
= dyn_cast<ClassTemplateDecl>(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<TemplateDecl>(TemplateD.getAs<Decl>());
|
||||
ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(Template);
|
||||
Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgsIn,
|
||||
SourceLocation *TemplateArgLocs,
|
||||
SourceLocation RAngleLoc) {
|
||||
TemplateName Template = TemplateD.getAsVal<TemplateName>();
|
||||
|
||||
// Translate the parser's template argument list in our AST format.
|
||||
llvm::SmallVector<TemplateArgument, 16> 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<TemplateName>();
|
||||
ClassTemplateDecl *ClassTemplate
|
||||
= dyn_cast_or_null<ClassTemplateDecl>(TemplateD.getAs<Decl>());
|
||||
if (!ClassTemplate)
|
||||
return true;
|
||||
= cast<ClassTemplateDecl>(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:
|
||||
|
|
|
@ -114,7 +114,7 @@ void Sema::PrintInstantiationStack() {
|
|||
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
|
||||
TemplateDecl *Template = cast<TemplateDecl>((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<TemplateArgument, 16> 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<ClassTemplateDecl>(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
|
||||
|
|
Loading…
Reference in New Issue