diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-05-18 05:45:02 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-05-18 05:45:02 +0000 |
commit | 238058c372cfb7bdaf489f51171eb1380ebfd6a6 (patch) | |
tree | f39d05ef4f083475ea744fd147be20898953143c /lib/Sema/SemaTemplateInstantiateDecl.cpp | |
parent | c6772ce9c80ff524c7c522b5f0b37de58786bd84 (diff) |
I hate this commit.
Revert much of the implementation of C++98/03 [temp.friend]p5 in
r103943 and its follow-ons r103948 and r103952. While our
implementation was technically correct, other compilers don't seem to
implement this paragraph (which forces the instantiation of friend
functions defined in a class template when a class template
specialization is instantiated), and doing so broke a bunch of Boost
libraries.
Since this behavior has changed in C++0x (which instantiates the
friend function definitions when they are used), we're going to skip
the nowhere-implemented C++98/03 semantics and go straight to the
C++0x semantics.
This commit is a band-aid to get Boost up and running again. It
doesn't really fix PR6952 (which this commit un-fixes), but it does
deal with the way Boost.Units abuses this particular paragraph.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104014 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 103 |
1 files changed, 33 insertions, 70 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index f3d37787f8..592b474dfb 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1049,23 +1049,6 @@ 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)) @@ -1146,17 +1129,44 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0); DC->makeDeclVisibleInContext(PrincipalDecl, /*Recoverable=*/ false); + + if (!SemaRef.getLangOptions().CPlusPlus0x && + D->isThisDeclarationADefinition()) { + // Check for a function body. + const FunctionDecl *Definition = 0; + if (Function->getBody(Definition) && + Definition->getTemplateSpecializationKind() == TSK_Undeclared) { + SemaRef.Diag(Function->getLocation(), diag::err_redefinition) + << Function->getDeclName(); + SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition); + Function->setInvalidDecl(); + } + // Check for redefinitions due to other instantiations of this or + // a similar friend function. + else for (FunctionDecl::redecl_iterator R = Function->redecls_begin(), + REnd = Function->redecls_end(); + R != REnd; ++R) { + if (*R != Function && + ((*R)->getFriendObjectKind() != Decl::FOK_None)) { + if (const FunctionDecl *RPattern + = (*R)->getTemplateInstantiationPattern()) + if (RPattern->getBody(RPattern)) { + SemaRef.Diag(Function->getLocation(), diag::err_redefinition) + << Function->getDeclName(); + SemaRef.Diag((*R)->getLocation(), diag::note_previous_definition); + Function->setInvalidDecl(); + break; + } + } + } + } + } if (Function->isOverloadedOperator() && !DC->isRecord() && 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; } @@ -1981,34 +1991,13 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, bool Recursive, bool DefinitionRequired) { - if (Function->isInvalidDecl()) + if (Function->isInvalidDecl() || Function->getBody()) return; // Never instantiate an explicit specialization. if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) return; - const FunctionDecl *Definition = 0; - if (Function->getBody(Definition)) { - // We are trying to instantiate a friend function specialization inside - // a class template, but there is already another (non-template) definition - // of the same function. - if (Definition->getTemplateSpecializationKind() == TSK_Undeclared) { - InstantiatingTemplate Inst(*this, PointOfInstantiation, Function); - if (Inst) - return; - - Diag(Function->getLocation(), diag::err_redefinition) - << Function->getDeclName(); - Diag(Definition->getLocation(), diag::note_previous_definition); - Function->setInvalidDecl(); - } - - // We have an explicit instantiation (which already occurred) and an - // implicit instantiation. Return without complaint. - return; - } - // Find the function body that we'll be substituting. const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern(); Stmt *Pattern = 0; @@ -2035,32 +2024,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, return; } - // If this is an instantiation of friend function defined within a class - // template or class template specialization or member class thereof, - // determine whether there were multiple instantiations of its lexical class. - if (PatternDecl->getFriendObjectKind() != Decl::FOK_None) { - for (FunctionDecl::redecl_iterator R = Function->redecls_begin(), - REnd = Function->redecls_end(); - R != REnd; ++R) { - if (*R != Function && - ((*R)->getFriendObjectKind() != Decl::FOK_None)) { - if (const FunctionDecl *RPattern - = (*R)->getTemplateInstantiationPattern()) - if (RPattern->getBody(RPattern)) { - InstantiatingTemplate Inst(*this, PointOfInstantiation, Function); - if (Inst) - return; - - Diag(Function->getLocation(), diag::err_redefinition) - << Function->getDeclName(); - Diag((*R)->getLocation(), diag::note_previous_definition); - Function->setInvalidDecl(); - return; - } - } - } - } - // C++0x [temp.explicit]p9: // Except for inline functions, other explicit instantiation declarations // have the effect of suppressing the implicit instantiation of the entity |