This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix -frepo (PR c++/36364, take 2)
On Tue, Jun 24, 2008 at 03:53:46PM -0700, Mark Mitchell wrote:
> Jakub Jelinek wrote:
>
> >No. The problem is const static data member, for which:
> > /* Const static data members initialized by constant expressions must
> > be processed where needed so that their definitions are
> > available. */
> > if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)
> > && DECL_CLASS_SCOPE_P (decl))
> > return 2;
> >Returning 2 from repo_emit_p means thatg it is handled as in -fno-repo
> >compilation - it never makes it into the *.rpo file, neither
> >as O _Z...terminal, nor as C _Z...terminal. But as -frepo implies
> >-fno-implicit-templates, in this case it works as in
> >-fno-implicit-templates
> >compilation - which means explicit instantiation is required.
>
> Right, that is why I suggested using both the DECL_REPO_AVAILABLE and
> the IDENTIFIER_REPO_CHOSEN logic. Of course, you have to use
> DECL_REPO_AVAILABLE to let collect2 know about it. But, once you do
> that, it should assign it to an object file, and then
> IDENTIFIER_REPO_CHOSEN will tell you to write it out by returning 1 from
> that function.
Did you mean something like this, or have I completely misunderstood?
Works on RUNTESTFLAGS=dg.exp=repo*.C, will run a full x86_64-linux
bootstrap/regtest tonight.
Ok for trunk/4.3?
2008-06-27 Jakub Jelinek <jakub@redhat.com>
PR c++/36364
* repo.c (repo_emit_p): Put const static data members initialized
by const expr into *.rpo file, just return 2 if IDENTIFIER_REPO_CHOSEN
for it is 0.
* g++.dg/template/repo9.C: New test.
--- gcc/cp/repo.c.jj 2008-02-11 14:45:57.000000000 +0100
+++ gcc/cp/repo.c 2008-06-27 17:16:23.000000000 +0200
@@ -280,6 +280,7 @@ finish_repo (void)
int
repo_emit_p (tree decl)
{
+ int ret = 0;
gcc_assert (TREE_PUBLIC (decl));
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL);
@@ -306,10 +307,12 @@ repo_emit_p (tree decl)
return 2;
/* Const static data members initialized by constant expressions must
be processed where needed so that their definitions are
- available. */
+ available. Still record them into *.rpo files, so if they
+ weren't actually emitted and collect2 requests them, they can
+ be provided. */
if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)
&& DECL_CLASS_SCOPE_P (decl))
- return 2;
+ ret = 2;
}
else if (!DECL_TEMPLATE_INSTANTIATION (decl))
return 2;
@@ -343,7 +346,7 @@ repo_emit_p (tree decl)
pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
}
- return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl));
+ return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl)) ? 1 : ret;
}
/* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
--- gcc/testsuite/g++.dg/template/repo9.C.jj 2008-06-27 16:56:42.000000000 +0200
+++ gcc/testsuite/g++.dg/template/repo9.C 2008-06-27 16:56:42.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');
+}
Jakub