diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-05-17 16:38:00 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-05-17 16:38:00 +0000 |
commit | ac7c2c8a9d47df7d652364af3043c41816a18fa4 (patch) | |
tree | a4b33b559c0a83207b977300df403d68bd39e192 /lib/Sema/SemaTemplateInstantiateDecl.cpp | |
parent | 3d91bbcdab155181556969cad6ec97014405aced (diff) |
C++98/03 [temp.friend]p4 requires that inline function definitions
within class templates be instantiated along with each class template
specialization, even if the functions are not used. Do so, as a baby
step toward PR6952.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103943 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index adba32ecec..41c6218664 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1009,6 +1009,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Params[P]->setOwningFunction(Function); Function->setParams(Params.data(), Params.size()); + SourceLocation InstantiateAtPOI; if (TemplateParams) { // Our resulting instantiation is actually a function template, since we // are substituting only the outer template parameters. For example, given @@ -1047,6 +1048,23 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, // TODO: should we remember this connection regardless of whether // the friend declaration provided a body? Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); + if (!SemaRef.getLangOptions().CPlusPlus0x) { + // C++03 [temp.friend]p4: + // When a function is defined in a friend function declaration in a + // class template, the function is defined at each instantiation of the + // class template. The function is defined even if it is never used. + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Owner)) { + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Record)) + InstantiateAtPOI = Spec->getPointOfInstantiation(); + else if (MemberSpecializationInfo *MSInfo + = Record->getMemberSpecializationInfo()) + InstantiateAtPOI = MSInfo->getPointOfInstantiation(); + } + + if (InstantiateAtPOI.isInvalid()) + InstantiateAtPOI = Function->getLocation(); + } } if (InitFunctionInstantiation(Function, D)) @@ -1133,6 +1151,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) PrincipalDecl->setNonMemberOperator(); + // If we need to instantiate this function now (because it is a C++98/03 + // friend function defined inside a class template), do so. + if (InstantiateAtPOI.isValid()) + SemaRef.MarkDeclarationReferenced(InstantiateAtPOI, Function); + return Function; } |