diff mbox

[C++,Patch/RFC] PR 67576 ("[4.9/5/6 Regression] expression of typeid( expression ) is evaluated twice")

Message ID 55FABF0E.3060503@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Sept. 17, 2015, 1:24 p.m. UTC
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.

//////////////////
diff mbox

Patch

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();
+}