re PR c++/67576 (expression of typeid( expression ) is evaluated twice)
authorJason Merrill <jason@redhat.com>
Thu, 17 Dec 2015 16:51:52 +0000 (11:51 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 17 Dec 2015 16:51:52 +0000 (11:51 -0500)
PR c++/67576

PR c++/25466
* rtti.c (build_typeid): Use save_expr, not stabilize_reference.

From-SVN: r231776

gcc/cp/ChangeLog
gcc/cp/rtti.c
gcc/testsuite/g++.dg/rtti/typeid11.C [new file with mode: 0644]

index a192f00713d1a501c59872f76ec40ad35ed1c646..73906f3cb12bb7993c39062562d34d9d083378d1 100644 (file)
@@ -1,3 +1,9 @@
+2015-12-17  Jason Merrill  <jason@redhat.com>
+
+       PR c++/67576
+       PR c++/25466
+       * rtti.c (build_typeid): Use save_expr, not stabilize_reference.
+
 2015-12-16  Patrick Palka  <ppalka@gcc.gnu.org>
 
        PR c++/16333
index b397b55b78c85b29335dc76e3cb854dff87d2974..f42b1cbf9225ae2308a09de928e7d5f3c61eea0a 100644 (file)
@@ -332,7 +332,7 @@ build_typeid (tree exp, tsubst_flags_t complain)
       /* So we need to look into the vtable of the type of exp.
          Make sure it isn't a null lvalue.  */
       exp = cp_build_addr_expr (exp, complain);
-      exp = stabilize_reference (exp);
+      exp = save_expr (exp);
       cond = cp_convert (boolean_type_node, exp, complain);
       exp = cp_build_indirect_ref (exp, RO_NULL, complain);
     }
diff --git a/gcc/testsuite/g++.dg/rtti/typeid11.C b/gcc/testsuite/g++.dg/rtti/typeid11.C
new file mode 100644 (file)
index 0000000..384b0f4
--- /dev/null
@@ -0,0 +1,16 @@
+// { dg-do run }
+
+#include <typeinfo>
+
+struct Base { virtual void foo() {} }; // polymorphic
+
+int main()
+{
+  Base b;
+  Base *ary[] = { &b, &b, &b};
+
+  int iter = 0;
+  typeid(*ary[iter++]);
+  if (iter != 1)       // should be 1
+    __builtin_abort(); // but 2
+}