aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2004-09-10 14:42:00 -0700
committerRichard Henderson <rth@gcc.gnu.org>2004-09-10 14:42:00 -0700
commit981c353ef5e0af5f0a7766d6458b67c38ba95b4f (patch)
tree01b5fc23b14cf877549458bcf476b9498c62d4fc /gcc/cp
parent80aa8340eb9eefbbf55ba9150abec353500573d5 (diff)
downloadgcc-981c353ef5e0af5f0a7766d6458b67c38ba95b4f.zip
gcc-981c353ef5e0af5f0a7766d6458b67c38ba95b4f.tar.gz
gcc-981c353ef5e0af5f0a7766d6458b67c38ba95b4f.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/call.c17
-rw-r--r--gcc/cp/class.c57
-rw-r--r--gcc/cp/typeck.c7
4 files changed, 50 insertions, 42 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2de9a9f..42660e8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+2004-09-10 Richard Henderson <rth@redhat.com>
+
+ 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 <zlaski@apple.com>
* decl.c (objc_get_current_scope, objc_mark_locals_volatile):
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4e5b3d5..c08fb74 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 e15a38d..999551b 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 f4d1679..77fd20a 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);