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