fix dual aspect of PR8007,

namely when the friend function prototype is already used
at the point of the template definition that is supposed
to inject the friend function. Testcase verifies four
scenarios.
I would like receive some code review for this.

llvm-svn: 112524
This commit is contained in:
Gabor Greif 2010-08-30 21:10:05 +00:00
parent 66d2c8e886
commit 718d515b3a
2 changed files with 37 additions and 11 deletions

View File

@ -1166,7 +1166,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0);
DC->makeDeclVisibleInContext(PrincipalDecl, /*Recoverable=*/ false);
bool queuedInstantiation = false;
if (!SemaRef.getLangOptions().CPlusPlus0x &&
D->isThisDeclarationADefinition()) {
// Check for a function body.
@ -1185,7 +1187,22 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
R != REnd; ++R) {
if (*R == Function)
continue;
if (R->getFriendObjectKind() != Decl::FOK_None) {
switch (R->getFriendObjectKind()) {
case Decl::FOK_None:
if (!queuedInstantiation && R->isUsed(false)) {
if (MemberSpecializationInfo *MSInfo
= Function->getMemberSpecializationInfo()) {
if (MSInfo->getPointOfInstantiation().isInvalid()) {
SourceLocation Loc = R->getLocation(); // FIXME
MSInfo->setPointOfInstantiation(Loc);
SemaRef.PendingLocalImplicitInstantiations.push_back(
std::make_pair(Function, Loc));
queuedInstantiation = true;
}
}
}
break;
default:
if (const FunctionDecl *RPattern
= R->getTemplateInstantiationPattern())
if (RPattern->hasBody(RPattern)) {
@ -1198,7 +1215,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
}
}
}
}
if (Function->isOverloadedOperator() && !DC->isRecord() &&

View File

@ -1,8 +1,9 @@
// RUN: %clang %s -S -emit-llvm -o - | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE"
// RUN: %clang %s -S -emit-llvm -o - -DPROTOTYPE | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE"
// RUN: %clang -cc1 %s -DREDEFINE -verify
// RUN: %clang -cc1 %s -DPROTOTYPE -DREDEFINE -verify
// PR8007: friend function not instantiated, reordered version.
// Corresponds to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38392
// XFAIL: *
struct std_ostream
{
@ -17,6 +18,7 @@ struct Streamer;
typedef struct Foo {} Foo;
std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
void test(const Streamer<Foo>& foo)
{
cout << foo;
@ -38,6 +40,21 @@ struct Streamer
void operator () (std_ostream&) const;
};
#ifdef PROTOTYPE
std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
#endif
#ifdef INSTANTIATE
template struct Streamer<Foo>;
#endif
#ifdef REDEFINE
std_ostream& operator << (std_ostream& o, const Streamer<Foo>&) // expected-note{{is here}}
{
return o;
}
#endif
template <>
void Streamer<Foo>::operator () (std_ostream& o) const // expected-note{{requested here}}
{
@ -49,10 +66,3 @@ int main(void)
test(foo);
}
#ifdef REDEFINE
std_ostream& operator << (std_ostream& o, const Streamer<Foo>&) // expected-note{{is here}}
{
// Sema should flag this as a redefinition
return o;
}
#endif