From: Vassil Vassilev Date: Wed, 16 Mar 2016 11:17:04 +0000 (+0000) Subject: [modules] Fix adding a templated friend functions to a namespace from another module. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=64e5a9bb786dabb6728d100712e8cf4d0a0bc5e1;p=clang [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 --- diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index ee475d3cc5..3e04bc5ad7 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -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(DC) || isa(DC)) + // TU is handled elsewhere. + if (isa(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(DC) && D->getFriendObjectKind() == Decl::FOK_None && + !isa(D)) return; // We're only interested in cases where a local declaration is added to an diff --git a/test/Modules/Inputs/PR24954/A.h b/test/Modules/Inputs/PR24954/A.h new file mode 100644 index 0000000000..5e5d5bf92c --- /dev/null +++ b/test/Modules/Inputs/PR24954/A.h @@ -0,0 +1,10 @@ +#include "B.h" + +template +class Expr { +public: + void print(B::basic_ostream& os) { + os << B::setw(42); + os << B::endl; + } +}; diff --git a/test/Modules/Inputs/PR24954/B.h b/test/Modules/Inputs/PR24954/B.h new file mode 100644 index 0000000000..a8ddc71892 --- /dev/null +++ b/test/Modules/Inputs/PR24954/B.h @@ -0,0 +1,30 @@ +namespace B { + + template + struct basic_ostream { + basic_ostream& operator<<(basic_ostream& (*__pf)()); + }; + + + template basic_ostream<_CharT>& + endl(); + + struct S1 { + template friend void + operator<<(basic_ostream<_CharT>& __os, const S1& __x); + }; + + S1 setw(int __n); + + template class S2; + + template void + operator<<(basic_ostream<_CharT>& __os, const S2<_CharT>& __x); + + template + struct S2 { + template friend void + operator<<(basic_ostream<_Cp>& __os, const S2<_Cp>& __x); + }; + +} diff --git a/test/Modules/Inputs/PR24954/module.modulemap b/test/Modules/Inputs/PR24954/module.modulemap new file mode 100644 index 0000000000..49374181d7 --- /dev/null +++ b/test/Modules/Inputs/PR24954/module.modulemap @@ -0,0 +1,9 @@ +module A { + header "A.h" + export * +} + +module B { + header "B.h" + export * +} diff --git a/test/Modules/pr24954.cpp b/test/Modules/pr24954.cpp new file mode 100644 index 0000000000..407ee06e40 --- /dev/null +++ b/test/Modules/pr24954.cpp @@ -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