diff options
| author | John McCall <rjmccall@apple.com> | 2010-03-26 23:10:15 +0000 | 
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2010-03-26 23:10:15 +0000 | 
| commit | 30837102a2ef32218c5d95d372b9ab3561733b6c (patch) | |
| tree | 79c89310337a2a9ad971687a95432db2be69f154 /clang | |
| parent | 4667effa8bdd9df81e51e1e3219c7cd0f525af58 (diff) | |
| download | bcm5719-llvm-30837102a2ef32218c5d95d372b9ab3561733b6c.tar.gz bcm5719-llvm-30837102a2ef32218c5d95d372b9ab3561733b6c.zip  | |
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
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 21 | ||||
| -rw-r--r-- | clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp | 12 | 
2 files changed, 27 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index e795f0ad1bc..59c9819751c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -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 diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp index b59e6ca320e..df3429ef31c 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp @@ -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'}} +  } +}  | 

