aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-05-18 05:45:02 +0000
committerDouglas Gregor <dgregor@apple.com>2010-05-18 05:45:02 +0000
commit238058c372cfb7bdaf489f51171eb1380ebfd6a6 (patch)
treef39d05ef4f083475ea744fd147be20898953143c /lib/Sema/SemaTemplateInstantiateDecl.cpp
parentc6772ce9c80ff524c7c522b5f0b37de58786bd84 (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.cpp103
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