Hi,
submitter noticed that the fix for c++/25466:
https://gcc.gnu.org/ml/gcc-patches/2013-04/msg00553.html
caused a double evaluation of the typeid, at least in some cases. I had
a quick look and wondered if it could make sense to just use the new
code when we are outside the straightforward INDIRECT_REF cases which we
already handled correctly... The below passes testing, anyway.
Thanks,
Paolo.
//////////////////
Index: cp/rtti.c
===================================================================
--- cp/rtti.c (revision 227849)
+++ cp/rtti.c (working copy)
@@ -336,10 +336,25 @@ 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);
- cond = cp_convert (boolean_type_node, exp, complain);
- exp = cp_build_indirect_ref (exp, RO_NULL, complain);
+ if (INDIRECT_REF_P (exp)
+ && TYPE_PTR_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
+ {
+ exp = mark_lvalue_use (exp);
+ exp = stabilize_reference (exp);
+ cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0),
+ complain);
+ }
+ else
+ {
+ /* The standard is somewhat unclear here, but makes sense
+ to always check whether the address is null rather than
+ confine the check to when the immediate operand of typeid
+ is an INDIRECT_REF. */
+ exp = cp_build_addr_expr (exp, complain);
+ exp = stabilize_reference (exp);
+ cond = cp_convert (boolean_type_node, exp, complain);
+ exp = cp_build_indirect_ref (exp, RO_NULL, complain);
+ }
}
exp = get_tinfo_decl_dynamic (exp, complain);
Index: testsuite/g++.dg/rtti/typeid11.C
===================================================================
--- testsuite/g++.dg/rtti/typeid11.C (revision 0)
+++ testsuite/g++.dg/rtti/typeid11.C (working copy)
@@ -0,0 +1,17 @@
+// PR c++/67576
+// { dg-do run }
+
+#include <typeinfo>
+
+struct Base { virtual void foo() {} };
+
+int main()
+{
+ Base b;
+ Base *ary[] = { &b, &b, &b };
+
+ int iter = 0;
+ typeid(*ary[iter++]);
+ if (iter != 1)
+ __builtin_abort();
+}