Put function templates instantiated from friend declarations in the correct

lexical context.  This is required for ADL to work properly;  fixes PR6716.

llvm-svn: 99665
This commit is contained in:
John McCall 2010-03-26 23:10:15 +00:00
parent 4667effa8b
commit 30837102a2
2 changed files with 27 additions and 6 deletions

View File

@ -840,16 +840,18 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
assert(InstTemplate &&
"VisitFunctionDecl/CXXMethodDecl didn't create a template!");
bool isFriend = (InstTemplate->getFriendObjectKind() != Decl::FOK_None);
// Link the instantiation back to the pattern *unless* this is a
// non-definition friend declaration.
if (!InstTemplate->getInstantiatedFromMemberTemplate() &&
!(InstTemplate->getFriendObjectKind() &&
!D->getTemplatedDecl()->isThisDeclarationADefinition()))
!(isFriend && !D->getTemplatedDecl()->isThisDeclarationADefinition()))
InstTemplate->setInstantiatedFromMemberTemplate(D);
// Add non-friends into the owner.
if (!InstTemplate->getFriendObjectKind())
// Make declarations visible in the appropriate context.
if (!isFriend)
Owner->addDecl(InstTemplate);
return InstTemplate;
}
@ -973,7 +975,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
if (Qualifier)
Function->setQualifierInfo(Qualifier, D->getQualifierRange());
Function->setLexicalDeclContext(Owner);
DeclContext *LexicalDC = Owner;
if (!isFriend && D->isOutOfLine()) {
assert(D->getDeclContext()->isFileContext());
LexicalDC = D->getDeclContext();
}
Function->setLexicalDeclContext(LexicalDC);
// Attach the parameters
for (unsigned P = 0; P < Params.size(); ++P)
@ -1000,7 +1008,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
Function->getDeclName(),
TemplateParams, Function);
Function->setDescribedFunctionTemplate(FunctionTemplate);
FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
FunctionTemplate->setLexicalDeclContext(LexicalDC);
if (isFriend && D->isThisDeclarationADefinition()) {
// TODO: should we remember this connection regardless of whether

View File

@ -40,3 +40,15 @@ namespace Test {
D::D() + D::D(); // expected-error {{ invalid operands to binary expression ('D::D' and 'D::D') }}
}
}
// PR6716
namespace test1 {
template <class T> class A {
template <class U> friend void foo(A &, U); // expected-note {{not viable: 1st argument ('A<int> const') would lose const qualifier}}
};
void test() {
const A<int> a;
foo(a, 10); // expected-error {{no matching function for call to 'foo'}}
}
}