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

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

From-SVN: r231781

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

index 1e030b033819858c0fb3082690c1fc78a9731705..34e1ea241a66d5ad359ae903c89e2cadc8cc3e98 100644 (file)
@@ -1,5 +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.
+
        PR c++/67557
        * call.c (is_base_field_ref): New.
        (unsafe_copy_elision_p): New.
index a8e6d25c844428dbb7156d5aec07cc4c8147c5cf..ac5a6fb82b356ff58bab8a4f353efd32e9740938 100644 (file)
@@ -335,7 +335,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
+}