forked from OSchip/llvm-project
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:
parent
4667effa8b
commit
30837102a2
|
@ -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
|
||||
|
|
|
@ -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'}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue