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
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index f3d3778..592b474 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1049,23 +1049,6 @@
// 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 @@
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 @@
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 @@
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