mirror of https://github.com/microsoft/clang.git
[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:
parent
9c1825952c
commit
64e5a9bb78
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
module A {
|
||||
header "A.h"
|
||||
export *
|
||||
}
|
||||
|
||||
module B {
|
||||
header "B.h"
|
||||
export *
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue