Patchwork [C++] Fix constexpr tree sharing problem (PR c++/46526)

login
register
mail settings
Submitter Jakub Jelinek
Date Nov. 19, 2010, 7:17 p.m.
Message ID <20101119191716.GI29412@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/72299/
State New
Headers show

Comments

Jakub Jelinek - Nov. 19, 2010, 7:17 p.m.
Hi!

As mentioned in the PR, this testcase is miscompiled because of a tree
sharing problem.  cxx_eval_call_expression always returns the same result
(CONSTRUCTOR in this case) and cxx_eval_bare_aggregate modifies it in place,
which means on this testcase that Base's CONSTRUCTOR is first changed
to have _ZTV1A + 16 value in the first element and then to _ZTV1B + 16,
so a (with A type) ends up _ZTV1B + 16 instead of _ZTV1A + 16 pointer.

It seems that cxx_eval_constant_expression and its helpers mostly have
unsharing semantics (usually they build new trees from the old ones), so
unsharing in cxx_eval_call_expression looks best to me.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2010-11-19  Jakub Jelinek  <jakub@redhat.com>

	PR c++/46526
	* semantics.c (cxx_eval_call_expression): Unshare the result.

	* g++.dg/cpp0x/constexpr-base3.C: New test.


	Jakub
Jason Merrill - Nov. 19, 2010, 8:44 p.m.
OK.

Jason

Patch

--- gcc/cp/semantics.c.jj	2010-11-11 09:04:25.000000000 +0100
+++ gcc/cp/semantics.c	2010-11-19 10:29:03.018372763 +0100
@@ -6042,7 +6042,7 @@  cxx_eval_call_expression (const constexp
     }
 
   pop_cx_call_context ();
-  return result;
+  return unshare_expr (result);
 }
 
 /* FIXME speed this up, it's taking 16% of compile time on sieve testcase.  */
--- gcc/testsuite/g++.dg/cpp0x/constexpr-base3.C.jj	2010-11-19 10:34:23.231529194 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-base3.C	2010-11-19 10:32:22.000000000 +0100
@@ -0,0 +1,27 @@ 
+// PR c++/46526
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+struct Base
+{
+  virtual int getid () = 0;
+};
+
+struct A : public Base
+{
+  virtual int getid () { return 1; }
+};
+
+struct B : public Base
+{
+  virtual int getid () { throw "here"; }
+};
+
+int
+main ()
+{
+  A a;
+  B b;
+  Base& ar = a;
+  ar.getid ();
+}