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