The decloning patch reversed the order of the calls to maybe_clone_body
and import_export_decl; as a result, the linkage flags copying that
happens in the former hasn't happened yet in the latter, and so we can
have a DECL_REALLY_EXTERN clone of a !DECL_REALLY_EXTERN constructor.
But since repo_emit_p doesn't actually depend on this at all, we can let
it slide.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 7966e7bfca2826ded6e8b2da75269d2e8316e7ee
Author: Jason Merrill <ja...@redhat.com>
Date: Wed Jan 28 17:09:44 2015 -0500
PR c++/64521
* repo.c (repo_emit_p): It's OK for a clone to be extern at this
point.
diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c
index 604d667..f417e4b 100644
--- a/gcc/cp/repo.c
+++ b/gcc/cp/repo.c
@@ -302,7 +302,11 @@ repo_emit_p (tree decl)
int ret = 0;
gcc_assert (TREE_PUBLIC (decl));
gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
- gcc_assert (!DECL_REALLY_EXTERN (decl));
+ gcc_assert (!DECL_REALLY_EXTERN (decl)
+ /* A clone might not have its linkage flags updated yet
+ because we call import_export_decl before
+ maybe_clone_body. */
+ || DECL_ABSTRACT_ORIGIN (decl));
/* When not using the repository, emit everything. */
if (!flag_use_repository)
diff --git a/gcc/testsuite/g++.dg/template/repo11.C b/gcc/testsuite/g++.dg/template/repo11.C
new file mode 100644
index 0000000..5cabfd4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/repo11.C
@@ -0,0 +1,31 @@
+// PR c++/64521
+// { dg-options "-frepo -std=c++11" }
+// { dg-require-host-local "" }
+// { dg-skip-if "dkms are not final links" { vxworks_kernel } }
+// { dg-final cleanup-repo-files }
+
+template <typename H> struct J { J(H) {} };
+template <unsigned long, typename...> struct K;
+template <unsigned long I> struct K<I> {};
+template <unsigned long I, typename H, typename... T>
+struct K<I, H, T...> : K<I + 1, T...>, J<H> {
+ K(const H &p1, const T &... p2) : K<I + 1, T...>(p2...), J<H>(p1) {}
+};
+template <typename... E> struct C : K<0, E...> {
+ C(const E &... p1) : K<0, E...>(p1...) {}
+};
+template <typename> struct A {
+ A() = default;
+};
+struct M;
+template <typename> struct L {
+ struct B {
+ template <typename> static M *__test(...);
+ typedef A<int> _Del;
+ typedef decltype(__test<_Del>()) type;
+ };
+ C<typename B::type, A<M>> _M_t;
+ L(typename B::type) : _M_t(0, A<M>()) {}
+};
+struct M {};
+int main() { L<int>(new M); }