re PR c++/15471 (Incorrect member pointer offsets in anonymous structs/unions)
authorMark Mitchell <mark@codesourcery.com>
Fri, 28 May 2004 23:34:39 +0000 (23:34 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 28 May 2004 23:34:39 +0000 (23:34 +0000)
PR c++/15471
* typeck.c (unary_complex_lvalue): Use context_for_name_lookup
when determining the scope to use for a pointer to member.
(lookup_anon_field): Give it external linkage.
* cp-tree.h (lookup_anon_field): Declare it.
* expr.c (cplus_expand_constant): Use it.

From-SVN: r82401

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/expr.c
gcc/cp/typeck.c

index 6fe851774a5cce90eebeda04c88a0c2f6ffa32e0..73d34b8c1ebcee1fff7950f909e46aa4929af8e0 100644 (file)
@@ -16,6 +16,9 @@
        PR c++/15471
        * typeck.c (unary_complex_lvalue): Use context_for_name_lookup
        when determining the scope to use for a pointer to member.
+       (lookup_anon_field): Give it external linkage.
+       * cp-tree.h (lookup_anon_field): Declare it.
+       * expr.c (cplus_expand_constant): Use it.
 
 2004-05-28  Mark Mitchell  <mark@codesourcery.com>
 
index 9fc83d56bce7c8e78b0e20cb9335037418acc4c1..8b4e7f7af15870bc0c296372b71ccdd995e8ad31 100644 (file)
@@ -4243,6 +4243,7 @@ extern tree build_ptrmemfunc_access_expr       (tree, tree);
 extern tree build_address                       (tree);
 extern tree build_nop                           (tree, tree);
 extern tree non_reference                       (tree);
+extern tree lookup_anon_field                   (tree, tree);
 
 /* in typeck2.c */
 extern void require_complete_eh_spec_types     (tree, tree);
index e12c6a4a64fff356f72a4b26a2a477788c92a572..466d984642b9bb887689b35ca9753a2cf161f2ba 100644 (file)
@@ -51,8 +51,21 @@ cplus_expand_constant (tree cst)
        member = PTRMEM_CST_MEMBER (cst);
 
        if (TREE_CODE (member) == FIELD_DECL) 
-         /* Find the offset for the field.  */
-         cst = fold (build_nop (type, byte_position (member)));
+         {
+           /* Find the offset for the field.  */
+           cst = byte_position (member);
+           while (!same_type_p (DECL_CONTEXT (member),
+                                TYPE_PTRMEM_CLASS_TYPE (type)))
+             {
+               /* The MEMBER must have been nestled within an
+                  anonymous aggregate contained in TYPE.  Find the
+                  anonymous aggregate.  */
+               member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type),
+                                           DECL_CONTEXT (member));
+               cst = size_binop (PLUS_EXPR, cst, byte_position (member));
+             }
+           cst = fold (build_nop (type, cst));
+         }
        else
          {
            tree delta;
index 2570868f56c99b12e73e4cad476f42f316c6c8bf..527134d1493ae56f8356757bef37f346be22d123 100644 (file)
@@ -54,7 +54,6 @@ static int comp_ptr_ttypes_const (tree, tree);
 static bool comp_except_types (tree, tree, bool);
 static bool comp_array_types (tree, tree, bool);
 static tree common_base_type (tree, tree);
-static tree lookup_anon_field (tree, tree);
 static tree pointer_diff (tree, tree, tree);
 static tree get_delta_difference (tree, tree, int);
 static void casts_away_constness_r (tree *, tree *);
@@ -1517,7 +1516,7 @@ rationalize_conditional_expr (enum tree_code code, tree t)
    anonymous unions can nest, we must also search all anonymous unions
    that are directly reachable.  */
 
-static tree
+tree
 lookup_anon_field (tree t, tree type)
 {
   tree field;