[C++ PATCH] Fix -frepo (PR c++/36364)
Jakub Jelinek
jakub@redhat.com
Mon Jun 23 16:07:00 GMT 2008
Hi!
The following testcase distilled from:
#include <string>
#include <ext/mt_allocator.h>
//workaround:
//template class std::basic_string <char, std::char_traits <char>, __gnu_cxx::__mt_alloc <char> >;
int main ()
{
std::basic_string <char, std::char_traits <char>, __gnu_cxx::__mt_alloc <char> > s;
s.push_back ('a');
}
doesn't link with -frepo. The problem is a static const data member with
initializer, which repo_emit_p returns 2 for (to make sure it is properly
optimized out when possible), but then import_export_decl sees the
-frepo implied -fno-implicit-templates and doesn't emit it at all.
Saying this is invalid and requires user to explicitly instantiate it is
difficult, as that IMHO doesn't play well with the -frepo model.
Attached are two alternative patches. One stops implying
-fno-implicit-templates for -frepo in c-opts.c, only implies that
in import_export_class and in import_export_decl for VTABLE/VTT, the other in
the second spot in import_export_decl basically implies -fimplicit-templates
for the cases where repo_emit_p returned 2.
The first one will require explicit instantiation for terminal
if -frepo -fno-implicit-templates, the second one will not, otherwise
they are the same.
The second line in
if ((flag_implicit_templates
&& !flag_use_repository)
I've added in December last year doesn't make sense, in current
SVN flag_use_repository != 0 implies flag_implicit_templates = 0.
Is this ok for 4.4/4.3, or do you prefer doing something else?
Jakub
-------------- next part --------------
2008-06-23 Jakub Jelinek <jakub@redhat.com>
PR c++/36364
* c-opts.c (c_common_handle_option): Don't clear
flag_implicit_templates for -frepo.
* decl2.c (import_export_class): Adjust for -frepo
not implying flag_implicit_templates = 0.
(import_export_decl): Likewise.
* g++.dg/template/repo9.C: New test.
--- gcc/c-opts.c.jj 2008-06-19 12:22:29.000000000 +0200
+++ gcc/c-opts.c 2008-06-23 16:44:10.000000000 +0200
@@ -755,8 +755,6 @@ c_common_handle_option (size_t scode, co
case OPT_frepo:
flag_use_repository = value;
- if (value)
- flag_implicit_templates = 0;
break;
case OPT_frtti:
--- gcc/cp/decl2.c.jj 2008-06-23 08:40:29.000000000 +0200
+++ gcc/cp/decl2.c 2008-06-23 16:45:41.000000000 +0200
@@ -1589,7 +1589,7 @@ import_export_class (tree ctype)
else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
import_export = 1;
else if (CLASSTYPE_IMPLICIT_INSTANTIATION (ctype)
- && !flag_implicit_templates)
+ && (!flag_implicit_templates || flag_use_repository))
/* For a template class, without -fimplicit-templates, check the
repository. If the virtual table is assigned to this
translation unit, then export the class; otherwise, import
@@ -2282,7 +2282,7 @@ import_export_decl (tree decl)
}
}
}
- else if (!flag_implicit_templates
+ else if ((!flag_implicit_templates || flag_use_repository)
&& CLASSTYPE_IMPLICIT_INSTANTIATION (class_type))
import_p = true;
else
@@ -2331,8 +2331,7 @@ import_export_decl (tree decl)
{
/* DECL is an implicit instantiation of a function or static
data member. */
- if ((flag_implicit_templates
- && !flag_use_repository)
+ if (flag_implicit_templates
|| (flag_implicit_inline_templates
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)))
--- gcc/testsuite/g++.dg/template/repo9.C.jj 2008-06-23 16:54:25.000000000 +0200
+++ gcc/testsuite/g++.dg/template/repo9.C 2008-06-23 16:54:14.000000000 +0200
@@ -0,0 +1,48 @@
+// PR c++/36364
+// { dg-options "-frepo" }
+// { dg-final { cleanup-repo-files } }
+// { dg-require-host-local "" }
+
+template <typename C> struct A
+{
+ static void assign (C &c1, const C &c2) { c1 = c2; }
+};
+
+template <typename C, typename T> struct B
+{
+ struct D
+ {
+ static const C terminal;
+ static unsigned long stor[];
+ static D &empty_rep ()
+ {
+ void *p = reinterpret_cast <void *>(&stor);
+ return *reinterpret_cast <D *>(p);
+ }
+ void test (unsigned long n)
+ {
+ T::assign (this->refdata ()[n], terminal);
+ }
+ C *refdata () throw ()
+ {
+ return reinterpret_cast <C *>(this + 1);
+ }
+ };
+ C *dataplus;
+ C *data () const { return dataplus; }
+ D *rep () const { return &((reinterpret_cast < D * >(data ()))[-1]); }
+ static D & empty_rep () { return D::empty_rep (); }
+ B () : dataplus (empty_rep ().refdata ()) { }
+ ~B () { }
+ void push_back (C c) { rep ()->test (10); }
+};
+
+template <typename C, typename T> const C B <C, T>::D::terminal = C ();
+template <typename C, typename T> unsigned long B <C, T>::D::stor[64];
+
+int
+main ()
+{
+ B <char, A <char> > s;
+ s.push_back ('a');
+}
-------------- next part --------------
2008-06-23 Jakub Jelinek <jakub@redhat.com>
PR c++/36364
* decl2.c (import_export_decl): Set comdat_p whenever -frepo.
* g++.dg/template/repo9.C: New test.
--- gcc/cp/decl2.c.jj 2008-06-23 08:40:29.000000000 +0200
+++ gcc/cp/decl2.c 2008-06-23 17:33:53.000000000 +0200
@@ -2331,8 +2331,8 @@ import_export_decl (tree decl)
{
/* DECL is an implicit instantiation of a function or static
data member. */
- if ((flag_implicit_templates
- && !flag_use_repository)
+ if (flag_implicit_templates
+ || flag_use_repository
|| (flag_implicit_inline_templates
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)))
--- gcc/testsuite/g++.dg/template/repo9.C.jj 2008-06-23 16:54:25.000000000 +0200
+++ gcc/testsuite/g++.dg/template/repo9.C 2008-06-23 16:54:14.000000000 +0200
@@ -0,0 +1,48 @@
+// PR c++/36364
+// { dg-options "-frepo" }
+// { dg-final { cleanup-repo-files } }
+// { dg-require-host-local "" }
+
+template <typename C> struct A
+{
+ static void assign (C &c1, const C &c2) { c1 = c2; }
+};
+
+template <typename C, typename T> struct B
+{
+ struct D
+ {
+ static const C terminal;
+ static unsigned long stor[];
+ static D &empty_rep ()
+ {
+ void *p = reinterpret_cast <void *>(&stor);
+ return *reinterpret_cast <D *>(p);
+ }
+ void test (unsigned long n)
+ {
+ T::assign (this->refdata ()[n], terminal);
+ }
+ C *refdata () throw ()
+ {
+ return reinterpret_cast <C *>(this + 1);
+ }
+ };
+ C *dataplus;
+ C *data () const { return dataplus; }
+ D *rep () const { return &((reinterpret_cast < D * >(data ()))[-1]); }
+ static D & empty_rep () { return D::empty_rep (); }
+ B () : dataplus (empty_rep ().refdata ()) { }
+ ~B () { }
+ void push_back (C c) { rep ()->test (10); }
+};
+
+template <typename C, typename T> const C B <C, T>::D::terminal = C ();
+template <typename C, typename T> unsigned long B <C, T>::D::stor[64];
+
+int
+main ()
+{
+ B <char, A <char> > s;
+ s.push_back ('a');
+}
More information about the Gcc-patches
mailing list