forked from OSchip/llvm-project
[llvm up]
A template name can refer to a set of overloaded function templates. Model this in TemplateName, which can now refer to an OverloadedFunctionDecl that contains function templates. This removes an unspeakable hack in Sema::isTemplateName. llvm-svn: 77488
This commit is contained in:
parent
f5e7c2fbfc
commit
aa87ebc0c1
|
@ -583,7 +583,10 @@ public:
|
|||
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
||||
bool TemplateKeyword,
|
||||
TemplateDecl *Template);
|
||||
|
||||
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
||||
bool TemplateKeyword,
|
||||
OverloadedFunctionDecl *Template);
|
||||
|
||||
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name);
|
||||
|
||||
|
|
|
@ -28,7 +28,9 @@ class IdentifierInfo;
|
|||
class NestedNameSpecifier;
|
||||
struct PrintingPolicy;
|
||||
class QualifiedTemplateName;
|
||||
class NamedDecl;
|
||||
class TemplateDecl;
|
||||
class OverloadedFunctionDecl;
|
||||
|
||||
/// \brief Represents a C++ template name within the type system.
|
||||
///
|
||||
|
@ -58,7 +60,8 @@ class TemplateDecl;
|
|||
/// 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 *,
|
||||
typedef llvm::PointerUnion4<TemplateDecl *, OverloadedFunctionDecl *,
|
||||
QualifiedTemplateName *,
|
||||
DependentTemplateName *> StorageType;
|
||||
|
||||
StorageType Storage;
|
||||
|
@ -70,6 +73,8 @@ class TemplateName {
|
|||
public:
|
||||
TemplateName() : Storage() { }
|
||||
explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
|
||||
explicit TemplateName(OverloadedFunctionDecl *FunctionTemplates)
|
||||
: Storage(FunctionTemplates) { }
|
||||
explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
|
||||
explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
|
||||
|
||||
|
@ -78,9 +83,19 @@ public:
|
|||
///
|
||||
/// \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.
|
||||
/// declaration because it is a dependent name, or if it refers to a
|
||||
/// set of function templates, returns NULL.
|
||||
TemplateDecl *getAsTemplateDecl() const;
|
||||
|
||||
/// \brief Retrieve the the underlying, overloaded function template
|
||||
// declarations that this template name refers to, if known.
|
||||
///
|
||||
/// \returns The set of overloaded function templates that this template
|
||||
/// name refers to, if known. If the template name does not refer to a
|
||||
/// specific set of function templates because it is a dependent name or
|
||||
/// refers to a single template, returns NULL.
|
||||
OverloadedFunctionDecl *getAsOverloadedFunctionDecl() const;
|
||||
|
||||
/// \brief Retrieve the underlying qualified template name
|
||||
/// structure, if any.
|
||||
QualifiedTemplateName *getAsQualifiedTemplateName() const {
|
||||
|
@ -145,16 +160,22 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
|
|||
/// this name with DependentTemplateName).
|
||||
llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier;
|
||||
|
||||
/// \brief The template declaration that this qualified name refers
|
||||
/// to.
|
||||
TemplateDecl *Template;
|
||||
/// \brief The template declaration or set of overloaded function templates
|
||||
/// that this qualified name refers to.
|
||||
NamedDecl *Template;
|
||||
|
||||
friend class ASTContext;
|
||||
|
||||
QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
|
||||
TemplateDecl *Template)
|
||||
: Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) { }
|
||||
: Qualifier(NNS, TemplateKeyword? 1 : 0),
|
||||
Template(reinterpret_cast<NamedDecl *>(Template)) { }
|
||||
|
||||
QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
|
||||
OverloadedFunctionDecl *Template)
|
||||
: Qualifier(NNS, TemplateKeyword? 1 : 0),
|
||||
Template(reinterpret_cast<NamedDecl *>(Template)) { }
|
||||
|
||||
public:
|
||||
/// \brief Return the nested name specifier that qualifies this name.
|
||||
NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
|
||||
|
@ -163,16 +184,26 @@ public:
|
|||
/// keyword.
|
||||
bool hasTemplateKeyword() const { return Qualifier.getInt(); }
|
||||
|
||||
/// \brief The template declaration or set of overloaded functions that
|
||||
/// that qualified name refers to.
|
||||
NamedDecl *getDecl() const { return Template; }
|
||||
|
||||
/// \brief The template declaration to which this qualified name
|
||||
/// refers.
|
||||
TemplateDecl *getTemplateDecl() const { return Template; }
|
||||
/// refers, or NULL if this qualified name refers to a set of overloaded
|
||||
/// function templates.
|
||||
TemplateDecl *getTemplateDecl() const;
|
||||
|
||||
/// \brief The set of overloaded function tempaltes to which this qualified
|
||||
/// name refers, or NULL if this qualified name refers to a single
|
||||
/// template declaration.
|
||||
OverloadedFunctionDecl *getOverloadedFunctionDecl() const;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl());
|
||||
Profile(ID, getQualifier(), hasTemplateKeyword(), getDecl());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
|
||||
bool TemplateKeyword, TemplateDecl *Template) {
|
||||
bool TemplateKeyword, NamedDecl *Template) {
|
||||
ID.AddPointer(NNS);
|
||||
ID.AddBoolean(TemplateKeyword);
|
||||
ID.AddPointer(Template);
|
||||
|
|
|
@ -2036,6 +2036,12 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) {
|
|||
if (TemplateDecl *Template = Name.getAsTemplateDecl())
|
||||
return TemplateName(cast<TemplateDecl>(Template->getCanonicalDecl()));
|
||||
|
||||
// If this template name refers to a set of overloaded function templates,
|
||||
/// the canonical template name merely stores the set of function templates.
|
||||
if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl())
|
||||
// FIXME: Can't really canonicalize a set of overloaded functions, can we?
|
||||
return TemplateName(Ovl);
|
||||
|
||||
DependentTemplateName *DTN = Name.getAsDependentTemplateName();
|
||||
assert(DTN && "Non-dependent template names must refer to template decls.");
|
||||
return DTN->CanonicalTemplateName;
|
||||
|
@ -3052,6 +3058,25 @@ TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
|||
return TemplateName(QTN);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template name that represents a qualified
|
||||
/// template name such as \c std::vector.
|
||||
TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
||||
bool TemplateKeyword,
|
||||
OverloadedFunctionDecl *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,
|
||||
|
|
|
@ -29,14 +29,26 @@ TemplateDecl *TemplateName::getAsTemplateDecl() const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
OverloadedFunctionDecl *TemplateName::getAsOverloadedFunctionDecl() const {
|
||||
if (OverloadedFunctionDecl *Ovl
|
||||
= Storage.dyn_cast<OverloadedFunctionDecl *>())
|
||||
return Ovl;
|
||||
|
||||
if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
|
||||
return QTN->getOverloadedFunctionDecl();
|
||||
|
||||
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 isa<TemplateTemplateParmDecl>(Template) ||
|
||||
Template->getDeclContext()->isDependentContext();
|
||||
}
|
||||
|
||||
if (OverloadedFunctionDecl *Ovl = getAsOverloadedFunctionDecl())
|
||||
return Ovl->getDeclContext()->isDependentContext();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -45,16 +57,20 @@ TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
|
|||
bool SuppressNNS) const {
|
||||
if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
|
||||
OS << Template->getIdentifier()->getName();
|
||||
else if (OverloadedFunctionDecl *Ovl
|
||||
= Storage.dyn_cast<OverloadedFunctionDecl *>())
|
||||
OS << Ovl->getNameAsString();
|
||||
else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
|
||||
if (!SuppressNNS)
|
||||
QTN->getQualifier()->print(OS, Policy);
|
||||
if (QTN->hasTemplateKeyword())
|
||||
OS << "template ";
|
||||
OS << QTN->getTemplateDecl()->getIdentifier()->getName();
|
||||
OS << QTN->getDecl()->getNameAsString();
|
||||
} else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
|
||||
if (!SuppressNNS)
|
||||
DTN->getQualifier()->print(OS, Policy);
|
||||
OS << "template ";
|
||||
// FIXME: Shouldn't we have a more general kind of name?
|
||||
OS << DTN->getName()->getName();
|
||||
}
|
||||
}
|
||||
|
@ -65,3 +81,13 @@ void TemplateName::dump() const {
|
|||
LO.Bool = true;
|
||||
print(llvm::errs(), PrintingPolicy(LO));
|
||||
}
|
||||
|
||||
TemplateDecl *QualifiedTemplateName::getTemplateDecl() const {
|
||||
return dyn_cast<TemplateDecl>(Template);
|
||||
}
|
||||
|
||||
OverloadedFunctionDecl *
|
||||
QualifiedTemplateName::getOverloadedFunctionDecl() const {
|
||||
return dyn_cast<OverloadedFunctionDecl>(Template);
|
||||
}
|
||||
|
||||
|
|
|
@ -2701,6 +2701,8 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
|
|||
} else if (TemplateIdRefExpr *TemplateIdRef
|
||||
= dyn_cast<TemplateIdRefExpr>(FnExpr)) {
|
||||
NDecl = TemplateIdRef->getTemplateName().getAsTemplateDecl();
|
||||
if (!NDecl)
|
||||
NDecl = TemplateIdRef->getTemplateName().getAsOverloadedFunctionDecl();
|
||||
HasExplicitTemplateArgs = true;
|
||||
ExplicitTemplateArgs = TemplateIdRef->getTemplateArgs();
|
||||
NumExplicitTemplateArgs = TemplateIdRef->getNumTemplateArgs();
|
||||
|
|
|
@ -1596,8 +1596,7 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
|
|||
if (DRE)
|
||||
Ovl = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl());
|
||||
else if (TIRE)
|
||||
Ovl = dyn_cast_or_null<OverloadedFunctionDecl>(
|
||||
TIRE->getTemplateName().getAsTemplateDecl());
|
||||
Ovl = TIRE->getTemplateName().getAsOverloadedFunctionDecl();
|
||||
if (!Ovl)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -93,10 +93,18 @@ TemplateNameKind Sema::isTemplateName(const IdentifierInfo &II, Scope *S,
|
|||
if (isa<FunctionTemplateDecl>(*F))
|
||||
OvlTemplate->addOverload(*F);
|
||||
}
|
||||
|
||||
// FIXME: HACK! We need TemplateName to be able to refer to
|
||||
// sets of overloaded function templates.
|
||||
TemplateResult = TemplateTy::make(OvlTemplate);
|
||||
|
||||
// Form the resulting TemplateName
|
||||
if (SS && SS->isSet() && !SS->isInvalid()) {
|
||||
NestedNameSpecifier *Qualifier
|
||||
= static_cast<NestedNameSpecifier *>(SS->getScopeRep());
|
||||
TemplateResult
|
||||
= TemplateTy::make(Context.getQualifiedTemplateName(Qualifier,
|
||||
false,
|
||||
OvlTemplate));
|
||||
} else {
|
||||
TemplateResult = TemplateTy::make(TemplateName(OvlTemplate));
|
||||
}
|
||||
return TNK_Function_template;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,8 @@ TemplateExprInstantiator::VisitUnresolvedFunctionNameExpr(
|
|||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitTemplateIdRefExpr(TemplateIdRefExpr *E) {
|
||||
TemplateName Template
|
||||
= SemaRef.InstantiateTemplateName(E->getTemplateName(), E->getTemplateNameLoc(),
|
||||
= SemaRef.InstantiateTemplateName(E->getTemplateName(),
|
||||
E->getTemplateNameLoc(),
|
||||
TemplateArgs);
|
||||
// FIXME: Can InstantiateTemplateName report an error?
|
||||
|
||||
|
|
Loading…
Reference in New Issue