backport: class.c (build_vtbl_ref_1): Use fixed_type_or_null.

* Backport from mainline:
	2002-05-13  Jason Merrill  <jason@redhat.com>

	* class.c (build_vtbl_ref_1): Use fixed_type_or_null.
	(fixed_type_or_null): See through reference vars.
	(build_base_path): Vtable contents are constant.

	* g++.dg/opt/rtti1.C: New test.

From-SVN: r64786
This commit is contained in:
Jakub Jelinek 2003-03-24 12:33:50 +01:00 committed by Jakub Jelinek
parent 355806ef42
commit 743b738128
4 changed files with 61 additions and 60 deletions

View File

@ -1,3 +1,12 @@
2003-03-24 Jakub Jelinek <jakub@redhat.com>
* Backport from mainline:
2002-05-13 Jason Merrill <jason@redhat.com>
* class.c (build_vtbl_ref_1): Use fixed_type_or_null.
(fixed_type_or_null): See through reference vars.
(build_base_path): Vtable contents are constant.
2003-03-19 Jason Merrill <jason@redhat.com>
PR c++/8316, c++/9315, c++/10136

View File

@ -315,7 +315,8 @@ build_base_path (code, expr, binfo, nonnull)
build_pointer_type (ptrdiff_type_node),
v_offset);
v_offset = build_indirect_ref (v_offset, NULL);
TREE_CONSTANT (v_offset) = 1;
offset = cp_convert (ptrdiff_type_node,
size_diffop (offset, BINFO_OFFSET (v_binfo)));
@ -400,75 +401,36 @@ static tree
build_vtbl_ref_1 (instance, idx)
tree instance, idx;
{
tree vtbl, aref;
tree basetype = TREE_TYPE (instance);
tree aref;
tree vtbl = NULL_TREE;
/* Try to figure out what a reference refers to, and
access its virtual function table directly. */
int cdtorp = 0;
tree fixed_type = fixed_type_or_null (instance, NULL, &cdtorp);
tree basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
if (instance == current_class_ref)
vtbl = build_vfield_ref (instance, basetype);
else
if (fixed_type && !cdtorp)
{
if (optimize)
{
/* Try to figure out what a reference refers to, and
access its virtual function table directly. */
tree ref = NULL_TREE;
tree binfo = lookup_base (fixed_type, basetype,
ba_ignore|ba_quiet, NULL);
if (binfo)
vtbl = BINFO_VTABLE (binfo);
}
if (TREE_CODE (instance) == INDIRECT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (instance, 0))) == REFERENCE_TYPE)
ref = TREE_OPERAND (instance, 0);
else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
ref = instance;
if (ref && TREE_CODE (ref) == VAR_DECL
&& DECL_INITIAL (ref))
{
tree init = DECL_INITIAL (ref);
while (TREE_CODE (init) == NOP_EXPR
|| TREE_CODE (init) == NON_LVALUE_EXPR)
init = TREE_OPERAND (init, 0);
if (TREE_CODE (init) == ADDR_EXPR)
{
init = TREE_OPERAND (init, 0);
if (IS_AGGR_TYPE (TREE_TYPE (init))
&& (TREE_CODE (init) == PARM_DECL
|| TREE_CODE (init) == VAR_DECL))
instance = init;
}
}
}
if (IS_AGGR_TYPE (TREE_TYPE (instance))
&& (TREE_CODE (instance) == RESULT_DECL
|| TREE_CODE (instance) == PARM_DECL
|| TREE_CODE (instance) == VAR_DECL))
{
vtbl = TYPE_BINFO_VTABLE (basetype);
/* Knowing the dynamic type of INSTANCE we can easily obtain
the correct vtable entry. We resolve this back to be in
terms of the primary vtable. */
if (TREE_CODE (vtbl) == PLUS_EXPR)
{
idx = fold (build (PLUS_EXPR,
TREE_TYPE (idx),
idx,
build (EXACT_DIV_EXPR,
TREE_TYPE (idx),
TREE_OPERAND (vtbl, 1),
TYPE_SIZE_UNIT (vtable_entry_type))));
vtbl = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
}
}
else
vtbl = build_vfield_ref (instance, basetype);
if (!vtbl)
{
vtbl = build_vfield_ref (instance, basetype);
}
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
TREE_CONSTANT (aref) = 1;
return aref;
}
@ -5370,7 +5332,7 @@ fixed_type_or_null (instance, nonnull, cdtorp)
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST)
/* Propagate nonnull. */
fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
return NULL_TREE;
case NOP_EXPR:
@ -5397,6 +5359,7 @@ fixed_type_or_null (instance, nonnull, cdtorp)
/* fall through... */
case TARGET_EXPR:
case PARM_DECL:
case RESULT_DECL:
if (IS_AGGR_TYPE (TREE_TYPE (instance)))
{
if (nonnull)
@ -5423,6 +5386,11 @@ fixed_type_or_null (instance, nonnull, cdtorp)
/* Reference variables should be references to objects. */
if (nonnull)
*nonnull = 1;
if (TREE_CODE (instance) == VAR_DECL
&& DECL_INITIAL (instance))
return fixed_type_or_null (DECL_INITIAL (instance),
nonnull, cdtorp);
}
return NULL_TREE;

View File

@ -1,3 +1,7 @@
2003-03-24 Jakub Jelinek <jakub@redhat.com>
* g++.dg/opt/rtti1.C: New test.
2003-03-23 Daniel Jacobowitz <drow@mvista.com>
* gcc.c-torture/execute/20030224-2.c: New test.

View File

@ -0,0 +1,20 @@
// Test that typeid sees through references even when optimizing.
// { dg-do run }
// { dg-options "-O2" }
#include <typeinfo>
struct A
{
virtual ~A() { }
};
class B : public A { };
int main ()
{
B b;
A &aref = b;
return typeid (aref) != typeid (b);
}