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:
parent
66d2c8e886
commit
718d515b3a
|
@ -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() &&
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue