aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-08-27 16:57:43 +0000
committerDouglas Gregor <dgregor@apple.com>2009-08-27 16:57:43 +0000
commitd60e105e6d1624da647ef7dd35a9cf6fad1b763e (patch)
treec96598344ed8cf15681c7b8987323cf861547667 /lib/Sema/SemaTemplateInstantiateDecl.cpp
parent19377389530101d583955537729e8889d487d59e (diff)
Implement instantiation of the declarations of member function
templates within class templates, producing a member function template of a class template specialization. If you can parse that, I'm sorry. Example: template<typename T> struct X { template<typename U> void f(T, U); }; When we instantiate X<int>, we now instantiate the declaration X<int>::f, which looks like this: template<typename U> void X<int>::f(int, U); The path this takes through TemplateDeclInstantiator::VisitCXXMethodDecl is convoluted and ugly, but I don't know how to improve it yet. I'm resting my hopes on the multi-level substitution required to instantiate definitions of nested templates, which may simplify this code as well. More testing to come... git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80252 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp71
1 files changed, 62 insertions, 9 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 5e91789083..42fc1f8165 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -48,13 +48,15 @@ namespace {
Decl *VisitFriendClassDecl(FriendClassDecl *D);
Decl *VisitFunctionDecl(FunctionDecl *D);
Decl *VisitCXXRecordDecl(CXXRecordDecl *D);
- Decl *VisitCXXMethodDecl(CXXMethodDecl *D);
+ Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
+ TemplateParameterList *TemplateParams = 0);
Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D);
Decl *VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
Decl *VisitClassTemplateDecl(ClassTemplateDecl *D);
+ Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
// Base case. FIXME: Remove once we can instantiate everything.
@@ -356,7 +358,8 @@ Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
- if (!InstParams) return NULL;
+ if (!InstParams)
+ return NULL;
CXXRecordDecl *Pattern = D->getTemplatedDecl();
CXXRecordDecl *RecordInst
@@ -375,6 +378,32 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
return Inst;
}
+Decl *
+TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ TemplateParameterList *TempParams = D->getTemplateParameters();
+ TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+ if (!InstParams)
+ return NULL;
+
+ // FIXME: Handle instantiation of nested function templates that aren't
+ // member function templates. This could happen inside a FriendDecl.
+ assert(isa<CXXMethodDecl>(D->getTemplatedDecl()));
+ CXXMethodDecl *InstMethod
+ = cast_or_null<CXXMethodDecl>(
+ VisitCXXMethodDecl(cast<CXXMethodDecl>(D->getTemplatedDecl()),
+ InstParams));
+ if (!InstMethod)
+ return 0;
+
+ // Link the instantiated function template declaration to the function
+ // template from which it was instantiated.
+ FunctionTemplateDecl *InstTemplate = InstMethod->getDescribedFunctionTemplate();
+ assert(InstTemplate && "VisitCXXMethodDecl didn't create a template!");
+ InstTemplate->setInstantiatedFromMemberTemplate(D);
+ Owner->addDecl(InstTemplate);
+ return InstTemplate;
+}
+
Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
CXXRecordDecl *PrevDecl = 0;
if (D->isInjectedClassName())
@@ -481,12 +510,15 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
return Function;
}
-Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
- // Check whether there is already a function template specialization for
- // this declaration.
+Decl *
+TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
+ TemplateParameterList *TemplateParams) {
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
void *InsertPos = 0;
- if (FunctionTemplate) {
+ if (FunctionTemplate && !TemplateParams) {
+ // We are creating a function template specialization from a function
+ // template. Check whether there is already a function template
+ // specialization for this particular set of template arguments.
llvm::FoldingSetNodeID ID;
FunctionTemplateSpecializationInfo::Profile(ID,
TemplateArgs.getFlatArgumentList(),
@@ -548,7 +580,28 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
D->isStatic(), D->isInline());
}
- if (!FunctionTemplate)
+ if (TemplateParams) {
+ // Our resulting instantiation is actually a function template, since we
+ // are substituting only the outer template parameters. For example, given
+ //
+ // template<typename T>
+ // struct X {
+ // template<typename U> void f(T, U);
+ // };
+ //
+ // X<int> x;
+ //
+ // We are instantiating the member template "f" within X<int>, which means
+ // substituting int for T, but leaving "f" as a member function template.
+ // Build the function template itself.
+ FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, Record,
+ Method->getLocation(),
+ Method->getDeclName(),
+ TemplateParams, Method);
+ if (D->isOutOfLine())
+ FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
+ Method->setDescribedFunctionTemplate(FunctionTemplate);
+ } else if (!FunctionTemplate)
Method->setInstantiationOfMemberFunction(D);
// If we are instantiating a member function defined
@@ -567,7 +620,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
NamedDecl *PrevDecl = 0;
- if (!FunctionTemplate) {
+ if (!FunctionTemplate || TemplateParams) {
PrevDecl = SemaRef.LookupQualifiedName(Owner, Name,
Sema::LookupOrdinaryName, true);
@@ -579,7 +632,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
PrevDecl = 0;
}
- if (FunctionTemplate)
+ if (FunctionTemplate && !TemplateParams)
// Record this function template specialization.
Method->setFunctionTemplateSpecialization(SemaRef.Context,
FunctionTemplate,