[C++ PATCH] Fix constexpr related wrong-code (PR c++/46626)
Jakub Jelinek
jakub@redhat.com
Thu Dec 23 21:33:00 GMT 2010
Hi!
The testcase in the patch is miscompiled. The problem seems to be
that the B::B() ctor contains
{
<<cleanup_point <<< Unknown tree: expr_stmt
A::A (&((struct B *) this)->D.1396) >>>>>;
<<< Unknown tree: cleanup_stmt
<<cleanup_point <<< Unknown tree: expr_stmt
(void) (((struct B *) this)->D.1396._vptr.A = &_ZTV1B + 16) >>>>>;
A::~A ((struct A *) this)
>>>;
}
and build_data_member_initialization ignores CLEANUP_STMT, which means
the constexpr ctor is expanded as setting _vptr.A field to &_ZTV1A + 16
instead of &_ZTV1B + 16. The following patch ignores the cleanup (A::~A
dtor in this case), but handles CLEANUP_BODY.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2010-12-23 Jakub Jelinek <jakub@redhat.com>
PR c++/46626
* semantics.c (build_data_member_initialization): For CLEANUP_STMT
recurse into CLEANUP_BODY.
* g++.dg/cpp0x/constexpr-base4.C: New test.
--- gcc/cp/semantics.c.jj 2010-12-16 10:55:31.000000000 +0100
+++ gcc/cp/semantics.c 2010-12-23 13:02:11.000000000 +0100
@@ -5440,11 +5440,25 @@ build_data_member_initialization (tree t
if (t == error_mark_node)
return false;
if (TREE_CODE (t) == CLEANUP_STMT)
- /* We can't see a CLEANUP_STMT in a constructor for a literal class,
- but we can in a constexpr constructor for a non-literal class. Just
- ignore it; either all the initialization will be constant, in which
- case the cleanup can't run, or it can't be constexpr. */
- return true;
+ {
+ /* We can't see a CLEANUP_STMT in a constructor for a literal class,
+ but we can in a constexpr constructor for a non-literal class. Just
+ ignore it; either all the initialization will be constant, in which
+ case the cleanup can't run, or it can't be constexpr.
+ Still recurse into CLEANUP_BODY. */
+ t = CLEANUP_BODY (t);
+ if (TREE_CODE (t) == STATEMENT_LIST)
+ {
+ tree_stmt_iterator i;
+ for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+ {
+ if (! build_data_member_initialization (tsi_stmt (i), vec))
+ return false;
+ }
+ return true;
+ }
+ return build_data_member_initialization (t, vec);
+ }
if (TREE_CODE (t) == CONVERT_EXPR)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == INIT_EXPR
--- gcc/testsuite/g++.dg/cpp0x/constexpr-base4.C.jj 2010-12-23 13:04:46.000000000 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-base4.C 2010-12-23 13:03:48.000000000 +0100
@@ -0,0 +1,28 @@
+// PR c++/46626
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+struct A
+{
+ virtual void f () = 0;
+ virtual ~A () { }
+};
+
+struct B : A
+{
+ virtual void f () { }
+};
+
+static void
+foo (A *a)
+{
+ a->f ();
+}
+
+int
+main ()
+{
+ B b;
+ foo (&b);
+ return 0;
+}
Jakub
More information about the Gcc-patches
mailing list