aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-10-13 16:30:37 +0000
committerDouglas Gregor <dgregor@apple.com>2009-10-13 16:30:37 +0000
commitfd056bc86a8b22a9421b5d921bbca276d0f9d0f7 (patch)
treee70aa9a7122aa2803f39ddd507f7c02bc1f87594 /lib/Sema/SemaTemplateInstantiateDecl.cpp
parenta735b206fdb5c15767a45289e1ffb3b568f70f2b (diff)
When explicitly specializing a member that is a template, mark the
template as a specialization. For example, this occurs with: template<typename T> struct X { template<typename U> struct Inner { /* ... */ }; }; template<> template<typename T> struct X<int>::Inner { T member; }; We need to treat templates that are member specializations as special in two contexts: - When looking for a definition of a member template, we look through the instantiation chain until we hit the primary template *or a member specialization*. This allows us to distinguish between the primary "Inner" definition and the X<int>::Inner definition, above. - When computing all of the levels of template arguments needed to instantiate a member template, don't add template arguments from contexts outside of the instantiation of a member specialization, since the user has already manually substituted those arguments. Fix up the existing test for p18, which was actually wrong (but we didn't diagnose it because of our poor handling of member specializations of templates), and add a new test for member specializations of templates. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83974 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp14
1 files changed, 10 insertions, 4 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index b03734346c..33fa28866e 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -581,7 +581,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
PrevDecl = 0;
}
- SemaRef.CheckFunctionDeclaration(Function, PrevDecl, Redeclaration,
+ SemaRef.CheckFunctionDeclaration(Function, PrevDecl, false, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
// If the original function was part of a friend declaration,
@@ -748,7 +748,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
- SemaRef.CheckFunctionDeclaration(Method, PrevDecl, Redeclaration,
+ SemaRef.CheckFunctionDeclaration(Method, PrevDecl, false, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
if (!FunctionTemplate && (!Method->isInvalidDecl() || !PrevDecl) &&
@@ -1057,9 +1057,15 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// Find the function body that we'll be substituting.
const FunctionDecl *PatternDecl = 0;
if (FunctionTemplateDecl *Primary = Function->getPrimaryTemplate()) {
- while (Primary->getInstantiatedFromMemberTemplate())
+ while (Primary->getInstantiatedFromMemberTemplate()) {
+ // If we have hit a point where the user provided a specialization of
+ // this template, we're done looking.
+ if (Primary->isMemberSpecialization())
+ break;
+
Primary = Primary->getInstantiatedFromMemberTemplate();
-
+ }
+
PatternDecl = Primary->getTemplatedDecl();
} else
PatternDecl = Function->getInstantiatedFromMemberFunction();