DeclarationName getNameForTemplate(TemplateName Name);
+ TemplateName getOverloadedTemplateName(NamedDecl * const *Begin,
+ NamedDecl * const *End);
+
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
bool TemplateKeyword,
TemplateDecl *Template);
- TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
- bool TemplateKeyword,
- OverloadedFunctionDecl *Template);
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
const IdentifierInfo *Name);
class QualifiedTemplateName;
class NamedDecl;
class TemplateDecl;
-class OverloadedFunctionDecl;
+
+/// \brief A structure for storing the information associated with an
+/// overloaded template name.
+class OverloadedTemplateStorage {
+ union {
+ unsigned Size;
+ NamedDecl *Storage[1];
+ };
+
+ friend class ASTContext;
+
+ OverloadedTemplateStorage(unsigned Size) : Size(Size) {}
+
+ NamedDecl **getStorage() {
+ return &Storage[1];
+ }
+ NamedDecl * const *getStorage() const {
+ return &Storage[1];
+ }
+
+public:
+ typedef NamedDecl *const *iterator;
+
+ unsigned size() const { return Size; }
+
+ iterator begin() const { return getStorage(); }
+ iterator end() const { return getStorage() + size(); }
+};
/// \brief Represents a C++ template name within the type system.
///
/// specifier in the typedef. "apply" is a nested template, and can
/// only be understood in the context of
class TemplateName {
- typedef llvm::PointerUnion4<TemplateDecl *, OverloadedFunctionDecl *,
+ typedef llvm::PointerUnion4<TemplateDecl *,
+ OverloadedTemplateStorage *,
QualifiedTemplateName *,
DependentTemplateName *> StorageType;
public:
TemplateName() : Storage() { }
explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
- explicit TemplateName(OverloadedFunctionDecl *FunctionTemplates)
- : Storage(FunctionTemplates) { }
+ explicit TemplateName(OverloadedTemplateStorage *Storage)
+ : Storage(Storage) { }
explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
/// 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;
+ OverloadedTemplateStorage *getAsOverloadedTemplate() const {
+ return Storage.dyn_cast<OverloadedTemplateStorage *>();
+ }
/// \brief Retrieve the underlying qualified template name
/// structure, if any.
/// \brief The template declaration or set of overloaded function templates
/// that this qualified name refers to.
- NamedDecl *Template;
+ TemplateDecl *Template;
friend class ASTContext;
QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
TemplateDecl *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)) { }
+ Template(Template) { }
public:
/// \brief Return the nested name specifier that qualifies this name.
/// 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 that this qualified name refers
+ /// to.
+ TemplateDecl *getDecl() const { return Template; }
/// \brief The template declaration to which this qualified name
- /// 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;
+ /// refers.
+ TemplateDecl *getTemplateDecl() const { return Template; }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getQualifier(), hasTemplateKeyword(), getDecl());
+ Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl());
}
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
- bool TemplateKeyword, NamedDecl *Template) {
+ bool TemplateKeyword, TemplateDecl *Template) {
ID.AddPointer(NNS);
ID.AddBoolean(TemplateKeyword);
ID.AddPointer(Template);
}
}
- assert(Name.getAsOverloadedFunctionDecl());
- return Name.getAsOverloadedFunctionDecl()->getDeclName();
+ OverloadedTemplateStorage *Storage = Name.getAsOverloadedTemplate();
+ assert(Storage);
+ return (*Storage->begin())->getDeclName();
}
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()) {
- OverloadedFunctionDecl *CanonOvl = 0;
- for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
- FEnd = Ovl->function_end();
- F != FEnd; ++F) {
- Decl *Canon = F->get()->getCanonicalDecl();
- if (CanonOvl || Canon != F->get()) {
- if (!CanonOvl)
- CanonOvl = OverloadedFunctionDecl::Create(*this,
- Ovl->getDeclContext(),
- Ovl->getDeclName());
-
- CanonOvl->addOverload(
- AnyFunctionDecl::getFromNamedDecl(cast<NamedDecl>(Canon)));
- }
- }
-
- return TemplateName(CanonOvl? CanonOvl : Ovl);
- }
+ assert(!Name.getAsOverloadedTemplate());
DependentTemplateName *DTN = Name.getAsDependentTemplateName();
assert(DTN && "Non-dependent template names must refer to template decls.");
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);
+/// \brief Retrieve the template name that corresponds to a non-empty
+/// lookup.
+TemplateName ASTContext::getOverloadedTemplateName(NamedDecl * const *Begin,
+ NamedDecl * const *End) {
+ unsigned size = End - Begin;
+ assert(size > 1 && "set is not overloaded!");
- void *InsertPos = 0;
- QualifiedTemplateName *QTN =
- QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
- if (!QTN) {
- QTN = new (*this,4) QualifiedTemplateName(NNS, TemplateKeyword, Template);
- QualifiedTemplateNames.InsertNode(QTN, InsertPos);
+ void *memory = Allocate(sizeof(OverloadedTemplateStorage) +
+ size * sizeof(FunctionTemplateDecl*));
+ OverloadedTemplateStorage *OT = new(memory) OverloadedTemplateStorage(size);
+
+ NamedDecl **Storage = OT->getStorage();
+ for (NamedDecl * const *I = Begin; I != End; ++I) {
+ NamedDecl *D = *I;
+ assert(isa<FunctionTemplateDecl>(D) ||
+ (isa<UsingShadowDecl>(D) &&
+ isa<FunctionTemplateDecl>(D->getUnderlyingDecl())));
+ *Storage++ = D;
}
- return TemplateName(QTN);
+ return TemplateName(OT);
}
/// \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) {
+ TemplateDecl *Template) {
llvm::FoldingSetNodeID ID;
QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template);
void *InsertPos = 0;
QualifiedTemplateName *QTN =
- QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+ QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
if (!QTN) {
QTN = new (*this,4) QualifiedTemplateName(NNS, TemplateKeyword, Template);
QualifiedTemplateNames.InsertNode(QTN, InsertPos);
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()) {
return isa<TemplateTemplateParmDecl>(Template) ||
Template->getDeclContext()->isDependentContext();
}
- if (OverloadedFunctionDecl *Ovl = getAsOverloadedFunctionDecl())
- return Ovl->getDeclContext()->isDependentContext();
+ assert(!getAsOverloadedTemplate() &&
+ "overloaded templates shouldn't survive to here");
return true;
}
bool SuppressNNS) const {
if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
OS << Template->getNameAsString();
- else if (OverloadedFunctionDecl *Ovl
- = Storage.dyn_cast<OverloadedFunctionDecl *>())
- OS << Ovl->getNameAsString();
else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
if (!SuppressNNS)
QTN->getQualifier()->print(OS, Policy);
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);
-}
-
case UnqualifiedId::IK_TemplateId: {
TemplateName TName
- = TemplateName::getFromVoidPointer(Name.TemplateId->Template);
- if (TemplateDecl *Template = TName.getAsTemplateDecl())
- return Template->getDeclName();
- if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl())
- return Ovl->getDeclName();
-
- return DeclarationName();
+ = TemplateName::getFromVoidPointer(Name.TemplateId->Template);
+ return Context.getNameForTemplate(TName);
}
}
if (TemplateDecl *TD = TName.getAsTemplateDecl())
R.addDecl(TD);
- else if (OverloadedFunctionDecl *OD
- = TName.getAsOverloadedFunctionDecl())
- for (OverloadIterator I(OD), E; I != E; ++I)
+ else if (OverloadedTemplateStorage *OT = TName.getAsOverloadedTemplate())
+ for (OverloadedTemplateStorage::iterator I = OT->begin(), E = OT->end();
+ I != E; ++I)
R.addDecl(*I);
R.resolveKind();
if (R.empty())
return TNK_Non_template;
- NamedDecl *Template = R.getAsSingleDecl(Context);
-
- if (SS.isSet() && !SS.isInvalid()) {
- NestedNameSpecifier *Qualifier
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
- if (OverloadedFunctionDecl *Ovl
- = dyn_cast<OverloadedFunctionDecl>(Template))
- TemplateResult
- = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, false,
- Ovl));
- else
- TemplateResult
- = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, false,
- cast<TemplateDecl>(Template)));
- } else if (OverloadedFunctionDecl *Ovl
- = dyn_cast<OverloadedFunctionDecl>(Template)) {
- TemplateResult = TemplateTy::make(TemplateName(Ovl));
+ TemplateName Template;
+ TemplateNameKind TemplateKind;
+
+ unsigned ResultCount = R.end() - R.begin();
+ if (ResultCount > 1) {
+ // We assume that we'll preserve the qualifier from a function
+ // template name in other ways.
+ Template = Context.getOverloadedTemplateName(R.begin(), R.end());
+ TemplateKind = TNK_Function_template;
} else {
- TemplateResult = TemplateTy::make(
- TemplateName(cast<TemplateDecl>(Template)));
- }
+ TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl());
- if (isa<ClassTemplateDecl>(Template) ||
- isa<TemplateTemplateParmDecl>(Template))
- return TNK_Type_template;
+ if (SS.isSet() && !SS.isInvalid()) {
+ NestedNameSpecifier *Qualifier
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ Template = Context.getQualifiedTemplateName(Qualifier, false, TD);
+ } else {
+ Template = TemplateName(TD);
+ }
+
+ if (isa<FunctionTemplateDecl>(TD))
+ TemplateKind = TNK_Function_template;
+ else {
+ assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD));
+ TemplateKind = TNK_Type_template;
+ }
+ }
- assert((isa<FunctionTemplateDecl>(Template) ||
- isa<OverloadedFunctionDecl>(Template)) &&
- "Unhandled template kind in Sema::isTemplateName");
- return TNK_Function_template;
+ TemplateResult = TemplateTy::make(Template);
+ return TemplateKind;
}
void Sema::LookupTemplateName(LookupResult &Found,