[modules] Fix adding a templated friend functions to a namespace from another module.

When clang adds argument dependent lookup candidates, it can perform template
instantiation. For example, it can instantiate a templated friend function and
register it in the enclosing namespace's lookup table.

Fixes https://llvm.org/bugs/show_bug.cgi?id=24954

Reviewed by Richard Smith.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@263634 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Vassil Vassilev 2016-03-16 11:17:04 +00:00
parent 9c1825952c
commit 64e5a9bb78
5 changed files with 66 additions and 2 deletions

View File

@ -5751,8 +5751,16 @@ static bool isImportedDeclContext(ASTReader *Chain, const Decl *D) {
}
void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
// TU and namespaces are handled elsewhere.
if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC))
// TU is handled elsewhere.
if (isa<TranslationUnitDecl>(DC))
return;
// Namespaces are handled elsewhere, except for template instantiations of
// FunctionTemplateDecls in namespaces. We are interested in cases where the
// local instantiations are added to an imported context. Only happens when
// adding ADL lookup candidates, for example templated friends.
if (isa<NamespaceDecl>(DC) && D->getFriendObjectKind() == Decl::FOK_None &&
!isa<FunctionTemplateDecl>(D))
return;
// We're only interested in cases where a local declaration is added to an

View File

@ -0,0 +1,10 @@
#include "B.h"
template <class T>
class Expr {
public:
void print(B::basic_ostream<char>& os) {
os << B::setw(42);
os << B::endl;
}
};

View File

@ -0,0 +1,30 @@
namespace B {
template <class _CharT>
struct basic_ostream {
basic_ostream& operator<<(basic_ostream& (*__pf)());
};
template <class _CharT> basic_ostream<_CharT>&
endl();
struct S1 {
template <class _CharT> friend void
operator<<(basic_ostream<_CharT>& __os, const S1& __x);
};
S1 setw(int __n);
template <class _CharT> class S2;
template <class _CharT> void
operator<<(basic_ostream<_CharT>& __os, const S2<_CharT>& __x);
template <class _CharT>
struct S2 {
template <class _Cp> friend void
operator<<(basic_ostream<_Cp>& __os, const S2<_Cp>& __x);
};
}

View File

@ -0,0 +1,9 @@
module A {
header "A.h"
export *
}
module B {
header "B.h"
export *
}

7
test/Modules/pr24954.cpp Normal file
View File

@ -0,0 +1,7 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -I%S/Inputs/PR24954 -verify %s
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I%S/Inputs/PR24954 -verify %s
#include "A.h"
// expected-no-diagnostics