From: Richard Henderson Date: Fri, 10 Sep 2004 21:42:00 +0000 (-0700) Subject: re PR c++/17386 (libstdc++ iostreams miscompilation) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=981c353ef5e0af5f0a7766d6458b67c38ba95b4f;p=gcc.git re PR c++/17386 (libstdc++ iostreams miscompilation) PR c++/17386 * call.c (build_vfield_ref): Move... * class.c (build_vfield_ref): ... here. Convert datum to the primary base containing the vptr. (make_new_vtable): Simplify build_primary_vtable arguments. (finish_struct_1): Do not duplicate TYPE_VFIELD. * typeck.c (build_class_member_access_expr): Don't warn for null object access to base fields. From-SVN: r87322 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2de9a9f450f..42660e8d9f6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2004-09-10 Richard Henderson + + PR c++/17386 + * call.c (build_vfield_ref): Move... + * class.c (build_vfield_ref): ... here. Convert datum to the + primary base containing the vptr. + (make_new_vtable): Simplify build_primary_vtable arguments. + (finish_struct_1): Do not duplicate TYPE_VFIELD. + * typeck.c (build_class_member_access_expr): Don't warn for + null object access to base fields. + 2004-09-10 Ziemowit Laski * decl.c (objc_get_current_scope, objc_mark_locals_volatile): diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 4e5b3d590c1..c08fb744704 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -191,23 +191,6 @@ static bool magic_varargs_p (tree); static tree build_temp (tree, tree, int, void (**)(const char *, ...)); static void check_constructor_callable (tree, tree); -tree -build_vfield_ref (tree datum, tree type) -{ - if (datum == error_mark_node) - return error_mark_node; - - if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE) - datum = convert_from_reference (datum); - - if (TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type) - && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type)) - datum = convert_to_base (datum, type, /*check_access=*/false); - - return build3 (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)), - datum, TYPE_VFIELD (type), NULL_TREE); -} - /* Returns nonzero iff the destructor name specified in NAME (a BIT_NOT_EXPR) matches BASETYPE. The operand of NAME can take many forms... */ diff --git a/gcc/cp/class.c b/gcc/cp/class.c index e15a38d1721..999551b435d 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -483,6 +483,38 @@ convert_to_base_statically (tree expr, tree base) } +tree +build_vfield_ref (tree datum, tree type) +{ + tree vfield, vcontext; + + if (datum == error_mark_node) + return error_mark_node; + + if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE) + datum = convert_from_reference (datum); + + /* First, convert to the requested type. */ + if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type)) + datum = convert_to_base (datum, type, /*check_access=*/false); + + /* Second, the requested type may not be the owner of its own vptr. + If not, convert to the base class that owns it. We cannot use + convert_to_base here, because VCONTEXT may appear more than once + in the inheritence hierarchy of TYPE, and thus direct conversion + between the types may be ambiguous. Following the path back up + one step at a time via primary bases avoids the problem. */ + vfield = TYPE_VFIELD (type); + vcontext = DECL_CONTEXT (vfield); + while (!same_type_ignoring_top_level_qualifiers_p (vcontext, type)) + { + datum = build_simple_base_path (datum, CLASSTYPE_PRIMARY_BINFO (type)); + type = TREE_TYPE (datum); + } + + return build3 (COMPONENT_REF, TREE_TYPE (vfield), datum, vfield, NULL_TREE); +} + /* Given an object INSTANCE, return an expression which yields the vtable element corresponding to INDEX. There are many special cases for INSTANCE which we take care of here, mainly to avoid @@ -783,10 +815,7 @@ make_new_vtable (tree t, tree binfo) /* In this case, it is *type*'s vtable we are modifying. We start with the approximation that its vtable is that of the immediate base class. */ - /* ??? This actually passes TYPE_BINFO (t), not the primary base binfo, - since we've updated DECL_CONTEXT (TYPE_VFIELD (t)) by now. */ - return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))), - t); + return build_primary_vtable (binfo, t); else /* This is our very own copy of `basetype' to play with. Later, we will fill in all the virtual functions that override the @@ -4927,7 +4956,6 @@ finish_struct_1 (tree t) /* A TREE_LIST. The TREE_VALUE of each node is a FUNCTION_DECL. */ tree virtuals = NULL_TREE; int n_fields = 0; - tree vfield; if (COMPLETE_TYPE_P (t)) { @@ -4981,25 +5009,6 @@ finish_struct_1 (tree t) needs a mode. */ compute_record_mode (CLASSTYPE_AS_BASE (t)); - /* Make sure that we get our own copy of the vfield FIELD_DECL. */ - vfield = TYPE_VFIELD (t); - if (vfield && CLASSTYPE_HAS_PRIMARY_BASE_P (t)) - { - tree primary = CLASSTYPE_PRIMARY_BINFO (t); - - gcc_assert (same_type_p (DECL_FIELD_CONTEXT (vfield), - BINFO_TYPE (primary))); - /* The vtable better be at the start. */ - gcc_assert (integer_zerop (DECL_FIELD_OFFSET (vfield))); - gcc_assert (integer_zerop (BINFO_OFFSET (primary))); - - vfield = copy_decl (vfield); - DECL_FIELD_CONTEXT (vfield) = t; - TYPE_VFIELD (t) = vfield; - } - else - gcc_assert (!vfield || DECL_FIELD_CONTEXT (vfield) == t); - virtuals = modify_all_vtables (t, nreverse (virtuals)); /* If necessary, create the primary vtable for this class. */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index f4d1679557a..77fd20af6c9 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1711,9 +1711,14 @@ build_class_member_access_expr (tree object, tree member, give the right answer. Note that we complain whether or not they actually used the offsetof macro, since there's no way to know at this point. So we just give a warning, instead of a pedwarn. */ + /* Do not produce this warning for base class field references, because + we know for a fact that didn't come from offsetof. This does occur + in various testsuite cases where a null object is passed where a + vtable access is required. */ if (null_object_p && warn_invalid_offsetof && CLASSTYPE_NON_POD_P (object_type) - && ! skip_evaluation) + && !DECL_FIELD_IS_BASE (member) + && !skip_evaluation) { warning ("invalid access to non-static data member `%D' of NULL object", member);