summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
authored <ed@FreeBSD.org>2009-07-04 13:58:54 +0000
committered <ed@FreeBSD.org>2009-07-04 13:58:54 +0000
commit4981926bf654fe5a2c3893f24ca44106b217e71e (patch)
tree8ddfe382e1c6d590dc240e76f7cd45cea5c78e24 /lib/Sema/SemaTemplateInstantiateDecl.cpp
parentc1ff020ff2d3e7ba86f7ab986ac7569c34f2ab1a (diff)
downloadFreeBSD-src-4981926bf654fe5a2c3893f24ca44106b217e71e.zip
FreeBSD-src-4981926bf654fe5a2c3893f24ca44106b217e71e.tar.gz
Import Clang r74788.
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp124
1 files changed, 96 insertions, 28 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a05095f..f597199 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -98,7 +98,7 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
if (Invalid)
Typedef->setInvalidDecl();
- Owner->addDecl(SemaRef.Context, Typedef);
+ Owner->addDecl(Typedef);
return Typedef;
}
@@ -124,7 +124,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// are not static data members.
bool Redeclaration = false;
SemaRef.CheckVariableDeclaration(Var, 0, Redeclaration);
- Owner->addDecl(SemaRef.Context, Var);
+ Owner->addDecl(Var);
if (D->getInit()) {
OwningExprResult Init
@@ -188,7 +188,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
if (Invalid)
Field->setInvalidDecl();
- Owner->addDecl(SemaRef.Context, Field);
+ Owner->addDecl(Field);
}
return Field;
@@ -219,14 +219,14 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
/*PrevDecl=*/0);
Enum->setInstantiationOfMemberEnum(D);
Enum->setAccess(D->getAccess());
- Owner->addDecl(SemaRef.Context, Enum);
+ Owner->addDecl(Enum);
Enum->startDefinition();
llvm::SmallVector<Sema::DeclPtrTy, 4> Enumerators;
EnumConstantDecl *LastEnumConst = 0;
- for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(SemaRef.Context),
- ECEnd = D->enumerator_end(SemaRef.Context);
+ for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(),
+ ECEnd = D->enumerator_end();
EC != ECEnd; ++EC) {
// The specified value for the enumerator.
OwningExprResult Value = SemaRef.Owned((Expr *)0);
@@ -257,7 +257,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
}
if (EnumConst) {
- Enum->addDecl(SemaRef.Context, EnumConst);
+ Enum->addDecl(EnumConst);
Enumerators.push_back(Sema::DeclPtrTy::make(EnumConst));
LastEnumConst = EnumConst;
}
@@ -289,12 +289,29 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
if (!D->isInjectedClassName())
Record->setInstantiationOfMemberClass(D);
- Owner->addDecl(SemaRef.Context, Record);
+ Owner->addDecl(Record);
return Record;
}
Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
- // FIXME: Look for existing specializations (explicit or otherwise).
+ // Check whether there is already a function template specialization for
+ // this declaration.
+ FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
+ void *InsertPos = 0;
+ if (FunctionTemplate) {
+ llvm::FoldingSetNodeID ID;
+ FunctionTemplateSpecializationInfo::Profile(ID,
+ TemplateArgs.getFlatArgumentList(),
+ TemplateArgs.flat_size());
+
+ FunctionTemplateSpecializationInfo *Info
+ = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID,
+ InsertPos);
+
+ // If we already have a function template specialization, return it.
+ if (Info)
+ return Info->Function;
+ }
Sema::LocalInstantiationScope Scope(SemaRef);
@@ -325,10 +342,15 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
NamedDecl *PrevDecl = 0;
SemaRef.CheckFunctionDeclaration(Function, PrevDecl, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
-
- // FIXME: link this to the function template from which it was instantiated.
-
+ if (FunctionTemplate) {
+ // Record this function template specialization.
+ Function->setFunctionTemplateSpecialization(SemaRef.Context,
+ FunctionTemplate,
+ &TemplateArgs,
+ InsertPos);
+ }
+
return Function;
}
@@ -372,7 +394,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
/*FIXME:*/OverloadableAttrRequired);
if (!Method->isInvalidDecl() || !PrevDecl)
- Owner->addDecl(SemaRef.Context, Method);
+ Owner->addDecl(Method);
return Method;
}
@@ -420,7 +442,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
/*FIXME:*/OverloadableAttrRequired);
Record->addedConstructor(SemaRef.Context, Constructor);
- Owner->addDecl(SemaRef.Context, Constructor);
+ Owner->addDecl(Constructor);
return Constructor;
}
@@ -452,7 +474,7 @@ Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
NamedDecl *PrevDecl = 0;
SemaRef.CheckFunctionDeclaration(Destructor, PrevDecl, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
- Owner->addDecl(SemaRef.Context, Destructor);
+ Owner->addDecl(Destructor);
return Destructor;
}
@@ -485,7 +507,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
NamedDecl *PrevDecl = 0;
SemaRef.CheckFunctionDeclaration(Conversion, PrevDecl, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
- Owner->addDecl(SemaRef.Context, Conversion);
+ Owner->addDecl(Conversion);
return Conversion;
}
@@ -606,6 +628,28 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
FunctionDecl *Tmpl) {
if (Tmpl->isDeleted())
New->setDeleted();
+
+ // If we are performing substituting explicitly-specified template arguments
+ // or deduced template arguments into a function template and we reach this
+ // point, we are now past the point where SFINAE applies and have committed
+ // to keeping the new function template specialization. We therefore
+ // convert the active template instantiation for the function template
+ // into a template instantiation for this specific function template
+ // specialization, which is not a SFINAE context, so that we diagnose any
+ // further errors in the declaration itself.
+ typedef Sema::ActiveTemplateInstantiation ActiveInstType;
+ ActiveInstType &ActiveInst = SemaRef.ActiveTemplateInstantiations.back();
+ if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
+ ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
+ if (FunctionTemplateDecl *FunTmpl
+ = dyn_cast<FunctionTemplateDecl>((Decl *)ActiveInst.Entity)) {
+ assert(FunTmpl->getTemplatedDecl() == Tmpl &&
+ "Deduction from the wrong function template?");
+ ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
+ ActiveInst.Entity = reinterpret_cast<uintptr_t>(New);
+ }
+ }
+
return false;
}
@@ -641,14 +685,23 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
/// \brief Instantiate the definition of the given function from its
/// template.
///
+/// \param PointOfInstantiation the point at which the instantiation was
+/// required. Note that this is not precisely a "point of instantiation"
+/// for the function, but it's close.
+///
/// \param Function the already-instantiated declaration of a
-/// function.
+/// function template specialization or member function of a class template
+/// specialization.
+///
+/// \param Recursive if true, recursively instantiates any functions that
+/// are required by this instantiation.
void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
- FunctionDecl *Function) {
+ FunctionDecl *Function,
+ bool Recursive) {
if (Function->isInvalidDecl())
return;
- assert(!Function->getBody(Context) && "Already instantiated!");
+ assert(!Function->getBody() && "Already instantiated!");
// Find the function body that we'll be substituting.
const FunctionDecl *PatternDecl = 0;
@@ -658,7 +711,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
PatternDecl = Function->getInstantiatedFromMemberFunction();
Stmt *Pattern = 0;
if (PatternDecl)
- Pattern = PatternDecl->getBody(Context, PatternDecl);
+ Pattern = PatternDecl->getBody(PatternDecl);
if (!Pattern)
return;
@@ -667,6 +720,13 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (Inst)
return;
+ // If we're performing recursive template instantiation, create our own
+ // queue of pending implicit instantiations that we will instantiate later,
+ // while we're still within our own instantiation context.
+ std::deque<PendingImplicitInstantiation> SavedPendingImplicitInstantiations;
+ if (Recursive)
+ PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
+
ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function));
// Introduce a new scope where local variable instantiations will be
@@ -695,6 +755,15 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
DeclGroupRef DG(Function);
Consumer.HandleTopLevelDecl(DG);
+
+ if (Recursive) {
+ // Instantiate any pending implicit instantiations found during the
+ // instantiation of this template.
+ PerformPendingImplicitInstantiations();
+
+ // Restore the set of pending implicit instantiations.
+ PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
+ }
}
/// \brief Instantiate the definition of the given variable from its
@@ -787,8 +856,7 @@ NamedDecl * Sema::InstantiateCurrentDeclRef(NamedDecl *D) {
// find the instantiation of the declaration D.
NamedDecl *Result = 0;
if (D->getDeclName()) {
- DeclContext::lookup_result Found
- = ParentDC->lookup(Context, D->getDeclName());
+ DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName());
Result = findInstantiationOf(Context, D, Found.first, Found.second);
} else {
// Since we don't have a name for the entity we're looking for,
@@ -800,8 +868,8 @@ NamedDecl * Sema::InstantiateCurrentDeclRef(NamedDecl *D) {
//
// FIXME: Find a better way to find these instantiations!
Result = findInstantiationOf(Context, D,
- ParentDC->decls_begin(Context),
- ParentDC->decls_end(Context));
+ ParentDC->decls_begin(),
+ ParentDC->decls_end());
}
assert(Result && "Unable to find instantiation of declaration!");
D = Result;
@@ -838,12 +906,12 @@ NamedDecl * Sema::InstantiateCurrentDeclRef(NamedDecl *D) {
void Sema::PerformPendingImplicitInstantiations() {
while (!PendingImplicitInstantiations.empty()) {
PendingImplicitInstantiation Inst = PendingImplicitInstantiations.front();
- PendingImplicitInstantiations.pop();
+ PendingImplicitInstantiations.pop_front();
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first))
- if (!Function->getBody(Context))
- InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function);
+ if (!Function->getBody())
+ InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true);
- // FIXME: instantiation static member variables
+ // FIXME: instantiate static member variables
}
}
OpenPOWER on IntegriCloud