]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fold-const.c (force_fit_type): Handle OFFSET_TYPE.
authorMark Mitchell <mark@codesourcery.com>
Tue, 22 Jul 2003 23:30:22 +0000 (23:30 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 22 Jul 2003 23:30:22 +0000 (23:30 +0000)
* fold-const.c (force_fit_type): Handle OFFSET_TYPE.
* varasam.c (output_constant): Likewise.

2003-07-22  Mark Mitchell  <mark@codesourcery.com>

Eliminate use of POINTER_TYPE for pointers-to-members.
* call.c (standard_conversion): Rework pointer-to-member handling.
Add comments.
(add_builtin_candidate): Likewise.
(resolve_scoped_fn_name): Remove.
(build_conditional_expr): Rework pointer-to-member handling.
(compare_ics): Likewise.
* class.c (check_field_decls): Use TYPE_PTR_P.
* cp-lang.c (cp_var_mod_type_p): Rework pointer-to-member
handling.
* cp-tree.h (SCALAR_TYPE_P): Use TYPE_PTR_TO_MEMBER_P.
(TYPE_PTRMEM_P): Add comment.
(TYPE_PTR_P): Simplify.
(TYPE_PTROB_P): Correct definition.
(TYPE_PTR_TO_MEMBER_P): New macro.
(TYPE_PTRMEM_CLASS_TYPE): Adjust.
(TYPE_PTRMEM_POINTED_TO_TYPE): Likewise.
(resolved_scoped_fn_name): Remove declaration.
(build_offset_ref): Change prototype.
(resolve_offset_ref): Remove.
(comp_target_types): Remove.
* cvt.c (cp_convert_to_pointer): Rework pointer-to-member
handling.
(convert_to_reference): Use can_convert.
(ocp_convert): Improve error handling.  Rework pointer-to-member
handling.
(perform_qualification_conversions): Rework pointer-to-member
handling.
* decl.c (build_ptrmem_type): Handle functions too.
(create_array_type_for_decl): Remove OFFSET_TYPE error message.
(grokdeclarator): Use OFFSET_TYPE for pointers to data members.
(grokparms): Remove OFFSET_TYPE error message.
* dump.c (cp_dump_tree): Rework pointer-to-member handling.
* error.c (dump_type_prefix): Likewise.
* expr.c (cplus_expand_constant): Use build_nop.
* init.c (build_offset_ref): Add address_p parameter.  Fold in
necessary bits from resolve_offset_ref.
(resolve_offset_ref): Remove.
* parser.c (cp_parser_postfix_expression): Remove special case
code for OFFSET_TYPE.
* pt.c (convert_nontype_argument): Rework pointer-to-member
handling.
(convert_template_argument): Likewise.
(unify): Likewise.
(invalid_nontype_parm_type_p): Likewise.
(dependent_type_p_r): Likewise.
* rtti.c (get_tinfo_decl): Remove OFFSET_TYPE special case.
(target_incomplete_p_): Rework pointer-to-member
handling.
(get_pseudo_ti_init): Likewise.
(get_pseudo_ti_desc): Likewise.
* semantics.c (finish_qualified_id_expr): Adjust call to
build_offset_ref.  Remove use of resolve_offset_ref.
* tree.c (pod_type_p): Use TYPE_PTR_TO_MEMBER_P.
* typeck.c (target_type): Use TYPE_PTRMEM_P.
(type_unknown_p): Remove obsolete code about the time before
non-dependent expressions were handled correctly.
(qualify_type_recursive): Remove.
(composite_pointer_type_r): New function.
(composite_pointer_type): Use it.
(merge_types): Remove dead comments.
(comp_cv_target_types): Remove.
(comp_target_types): Likewise.
(comp_target_parms): Likewise.
(cxx_sizeof_or_alignof_type): Remove OFFSET_TYPE error.
(build_indirect_ref): Use TYPE_PTR_TO_MEMBER_P.
(build_binary_op): Do not use of comp_target_types.
(pointer_diff): Remove OFFSET_TYPE case.
(build_unary_op): Adjust pointer-to-member handling.
(unary_complex_lvalue): Likewise.
(check_for_casting_away_constness): Add description parameter.
(build_static_cast): Pass it.
(build_reinterpret_cast): Use check_for_casting_away_constness.
(build_const_cast): Adjust pointer-to-member handling.
(build_c_cast): Likewise.
(convert_for_assignment): Remove OFFSET_TYPE error message.
(comp_ptr_ttypes_real): Adjust pointer-to-member handling.
(comp_ptr_ttypes_reinterpret): Remove.
(casts_away_constness_r): Adjust pointer-to-member handling.
(casts_away_constness): Liekwise.
(strip_all_pointer_quals): Remove.
* typeck2.c (digest_init): Adjust pointer-to-member handling.
(build_m_component_ref): Likewise.

From-SVN: r69691

21 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-lang.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/dump.c
gcc/cp/error.c
gcc/cp/expr.c
gcc/cp/init.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/rtti.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/fold-const.c
gcc/varasm.c

index 15ca3e520b0497f53d2e1c7ff85ba7cf768353ba..74f3eea3844a0b7ff634f8641112e5683df84603 100644 (file)
@@ -1,3 +1,8 @@
+2003-07-22  Mark Mitchell  <mark@codesourcery.com>
+
+       * fold-const.c (force_fit_type): Handle OFFSET_TYPE.
+       * varasam.c (output_constant): Likewise.
+
 2003-07-22  Kazu Hirata  <kazu@cs.umass.edu>
 
        * alias.c: Fix comment formatting.
index 55e3127a91eac8d09b298a8f21d4a7865840924d..982799147532ac0dbf2019fe6cde2843c724e452 100644 (file)
@@ -1,3 +1,89 @@
+2003-07-22  Mark Mitchell  <mark@codesourcery.com>
+
+       Eliminate use of POINTER_TYPE for pointers-to-members.
+       * call.c (standard_conversion): Rework pointer-to-member handling.
+       Add comments.
+       (add_builtin_candidate): Likewise.
+       (resolve_scoped_fn_name): Remove.
+       (build_conditional_expr): Rework pointer-to-member handling.
+       (compare_ics): Likewise.
+       * class.c (check_field_decls): Use TYPE_PTR_P.
+       * cp-lang.c (cp_var_mod_type_p): Rework pointer-to-member
+       handling.
+       * cp-tree.h (SCALAR_TYPE_P): Use TYPE_PTR_TO_MEMBER_P.
+       (TYPE_PTRMEM_P): Add comment.
+       (TYPE_PTR_P): Simplify.
+       (TYPE_PTROB_P): Correct definition.
+       (TYPE_PTR_TO_MEMBER_P): New macro.
+       (TYPE_PTRMEM_CLASS_TYPE): Adjust.
+       (TYPE_PTRMEM_POINTED_TO_TYPE): Likewise.
+       (resolved_scoped_fn_name): Remove declaration.
+       (build_offset_ref): Change prototype.
+       (resolve_offset_ref): Remove.
+       (comp_target_types): Remove.
+       * cvt.c (cp_convert_to_pointer): Rework pointer-to-member
+       handling.
+       (convert_to_reference): Use can_convert.
+       (ocp_convert): Improve error handling.  Rework pointer-to-member
+       handling.
+       (perform_qualification_conversions): Rework pointer-to-member
+       handling.
+       * decl.c (build_ptrmem_type): Handle functions too.
+       (create_array_type_for_decl): Remove OFFSET_TYPE error message.
+       (grokdeclarator): Use OFFSET_TYPE for pointers to data members.
+       (grokparms): Remove OFFSET_TYPE error message.
+       * dump.c (cp_dump_tree): Rework pointer-to-member handling.
+       * error.c (dump_type_prefix): Likewise.
+       * expr.c (cplus_expand_constant): Use build_nop.
+       * init.c (build_offset_ref): Add address_p parameter.  Fold in
+       necessary bits from resolve_offset_ref.
+       (resolve_offset_ref): Remove.
+       * parser.c (cp_parser_postfix_expression): Remove special case
+       code for OFFSET_TYPE.
+       * pt.c (convert_nontype_argument): Rework pointer-to-member
+       handling.
+       (convert_template_argument): Likewise.
+       (unify): Likewise.
+       (invalid_nontype_parm_type_p): Likewise.
+       (dependent_type_p_r): Likewise.
+       * rtti.c (get_tinfo_decl): Remove OFFSET_TYPE special case.
+       (target_incomplete_p_): Rework pointer-to-member
+       handling.
+       (get_pseudo_ti_init): Likewise.
+       (get_pseudo_ti_desc): Likewise.
+       * semantics.c (finish_qualified_id_expr): Adjust call to
+       build_offset_ref.  Remove use of resolve_offset_ref.
+       * tree.c (pod_type_p): Use TYPE_PTR_TO_MEMBER_P.
+       * typeck.c (target_type): Use TYPE_PTRMEM_P.
+       (type_unknown_p): Remove obsolete code about the time before
+       non-dependent expressions were handled correctly.
+       (qualify_type_recursive): Remove.
+       (composite_pointer_type_r): New function.
+       (composite_pointer_type): Use it.
+       (merge_types): Remove dead comments.
+       (comp_cv_target_types): Remove.
+       (comp_target_types): Likewise.
+       (comp_target_parms): Likewise.
+       (cxx_sizeof_or_alignof_type): Remove OFFSET_TYPE error.
+       (build_indirect_ref): Use TYPE_PTR_TO_MEMBER_P.
+       (build_binary_op): Do not use of comp_target_types.
+       (pointer_diff): Remove OFFSET_TYPE case.
+       (build_unary_op): Adjust pointer-to-member handling.
+       (unary_complex_lvalue): Likewise.
+       (check_for_casting_away_constness): Add description parameter.
+       (build_static_cast): Pass it.
+       (build_reinterpret_cast): Use check_for_casting_away_constness.
+       (build_const_cast): Adjust pointer-to-member handling.
+       (build_c_cast): Likewise.
+       (convert_for_assignment): Remove OFFSET_TYPE error message.
+       (comp_ptr_ttypes_real): Adjust pointer-to-member handling.
+       (comp_ptr_ttypes_reinterpret): Remove.
+       (casts_away_constness_r): Adjust pointer-to-member handling.
+       (casts_away_constness): Liekwise.
+       (strip_all_pointer_quals): Remove.
+       * typeck2.c (digest_init): Adjust pointer-to-member handling.
+       (build_m_component_ref): Likewise.
+       
 2003-07-22  Wolfgang Bangerth  <bangerth@dealii.org>
 
        * lex.c (unqualified_fn_lookup_error): Mention that the error
index 022ac78add6044d0ef3e7560bca31ea50d261369..cbfc5c389d4f76971d5d7bc4c343efb4d489b9e7 100644 (file)
@@ -642,11 +642,9 @@ standard_conversion (tree to, tree from, tree expr)
   if (same_type_p (from, to))
     return conv;
 
-  if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to))
+  if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to))
       && expr && null_ptr_cst_p (expr))
-    {
-      conv = build_conv (STD_CONV, to, conv);
-    }
+    conv = build_conv (STD_CONV, to, conv);
   else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE)
           || (tcode == POINTER_TYPE && fcode == INTEGER_TYPE))
     {
@@ -663,33 +661,37 @@ standard_conversion (tree to, tree from, tree expr)
       conv = build_conv (STD_CONV, to, conv);
       ICS_BAD_FLAG (conv) = 1;
     }
-  else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE)
+  else if ((tcode == POINTER_TYPE && fcode == POINTER_TYPE)
+          || (TYPE_PTRMEM_P (to) && TYPE_PTRMEM_P (from)))
     {
-      enum tree_code ufcode = TREE_CODE (TREE_TYPE (from));
-      enum tree_code utcode = TREE_CODE (TREE_TYPE (to));
+      tree to_pointee;
+      tree from_pointee;
 
-      if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),
-                                                    TREE_TYPE (to)))
+      if (tcode == POINTER_TYPE
+         && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),
+                                                       TREE_TYPE (to)))
        ;
-      else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE
-              && ufcode != FUNCTION_TYPE)
+      else if (VOID_TYPE_P (TREE_TYPE (to))
+              && !TYPE_PTRMEM_P (from)
+              && TREE_CODE (TREE_TYPE (from)) != FUNCTION_TYPE)
        {
          from = build_pointer_type
            (cp_build_qualified_type (void_type_node, 
                                      cp_type_quals (TREE_TYPE (from))));
          conv = build_conv (PTR_CONV, from, conv);
        }
-      else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
+      else if (TYPE_PTRMEM_P (from))
        {
-         tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from));
-         tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to));
+         tree fbase = TYPE_PTRMEM_CLASS_TYPE (from);
+         tree tbase = TYPE_PTRMEM_CLASS_TYPE (to);
 
          if (DERIVED_FROM_P (fbase, tbase)
              && (same_type_ignoring_top_level_qualifiers_p
-                 (TREE_TYPE (TREE_TYPE (from)),
-                  TREE_TYPE (TREE_TYPE (to)))))
+                 (TYPE_PTRMEM_POINTED_TO_TYPE (from),
+                  TYPE_PTRMEM_POINTED_TO_TYPE (to))))
            {
-             from = build_ptrmem_type (tbase, TREE_TYPE (TREE_TYPE (from)));
+             from = build_ptrmem_type (tbase, 
+                                       TYPE_PTRMEM_POINTED_TO_TYPE (from));
              conv = build_conv (PMEM_CONV, from, conv);
            }
        }
@@ -706,14 +708,25 @@ standard_conversion (tree to, tree from, tree expr)
            }
        }
 
+      if (tcode == POINTER_TYPE)
+       {
+         to_pointee = TREE_TYPE (to);
+         from_pointee = TREE_TYPE (from);
+       }
+      else
+       {
+         to_pointee = to;
+         from_pointee = from;
+       }
+
       if (same_type_p (from, to))
        /* OK */;
-      else if (comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from)))
+      else if (comp_ptr_ttypes (to_pointee, from_pointee))
        conv = build_conv (QUAL_CONV, to, conv);
       else if (expr && string_conv_p (to, expr, 0))
        /* converting from string constant to char *.  */
        conv = build_conv (QUAL_CONV, to, conv);
-      else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from)))
+      else if (ptr_reasonably_similar (to_pointee, from_pointee))
        {
          conv = build_conv (PTR_CONV, to, conv);
          ICS_BAD_FLAG (conv) = 1;
@@ -745,14 +758,25 @@ standard_conversion (tree to, tree from, tree expr)
     }
   else if (tcode == BOOLEAN_TYPE)
     {
-      if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE
-            || fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from)))
-       return 0;
+      /* [conv.bool]
 
-      conv = build_conv (STD_CONV, to, conv);
-      if (fcode == POINTER_TYPE
-         || (TYPE_PTRMEMFUNC_P (from) && ICS_STD_RANK (conv) < PBOOL_RANK))
-       ICS_STD_RANK (conv) = PBOOL_RANK;
+          An rvalue of arithmetic, enumeration, pointer, or pointer to
+         member type can be converted to an rvalue of type bool.  */
+      if (ARITHMETIC_TYPE_P (from)
+         || fcode == ENUMERAL_TYPE
+         || fcode == POINTER_TYPE
+         || TYPE_PTR_TO_MEMBER_P (from))
+       {
+         conv = build_conv (STD_CONV, to, conv);
+         if (fcode == POINTER_TYPE
+             || TYPE_PTRMEM_P (from)
+             || (TYPE_PTRMEMFUNC_P (from) 
+                 && ICS_STD_RANK (conv) < PBOOL_RANK))
+           ICS_STD_RANK (conv) = PBOOL_RANK;
+         return conv;
+       }
+      
+      return NULL_TREE;
     }
   /* We don't check for ENUMERAL_TYPE here because there are no standard
      conversions to enum type.  */
@@ -1592,8 +1616,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
             T       operator-(T);  */
 
     case CONVERT_EXPR: /* unary + */
-      if (TREE_CODE (type1) == POINTER_TYPE
-         && TREE_CODE (TREE_TYPE (type1)) != OFFSET_TYPE)
+      if (TREE_CODE (type1) == POINTER_TYPE)
        break;
     case NEGATE_EXPR:
       if (ARITHMETIC_TYPE_P (type1))
@@ -1618,12 +1641,10 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
 
     case MEMBER_REF:
       if (TREE_CODE (type1) == POINTER_TYPE
-         && (TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2)))
+         && TYPE_PTR_TO_MEMBER_P (type2))
        {
          tree c1 = TREE_TYPE (type1);
-         tree c2 = (TYPE_PTRMEMFUNC_P (type2)
-                    ? TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type2)))
-                    : TYPE_OFFSET_BASETYPE (TREE_TYPE (type2)));
+         tree c2 = TYPE_PTRMEM_CLASS_TYPE (type2);
 
          if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1)
              && (TYPE_PTRMEMFUNC_P (type2)
@@ -1693,14 +1714,12 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
       if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2))
          || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)))
        break;
-      if ((TYPE_PTRMEMFUNC_P (type1) || TYPE_PTRMEM_P (type1))
-         && null_ptr_cst_p (args[1]))
+      if (TYPE_PTR_TO_MEMBER_P (type1) && null_ptr_cst_p (args[1]))
        {
          type2 = type1;
          break;
        }
-      if ((TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2))
-         && null_ptr_cst_p (args[0]))
+      if (TYPE_PTR_TO_MEMBER_P (type2) && null_ptr_cst_p (args[0]))
        {
          type1 = type2;
          break;
@@ -1871,12 +1890,8 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
        break;
 
       /* Otherwise, the types should be pointers.  */
-      if (!(TREE_CODE (type1) == POINTER_TYPE
-           || TYPE_PTRMEM_P (type1)
-           || TYPE_PTRMEMFUNC_P (type1))
-         || !(TREE_CODE (type2) == POINTER_TYPE
-              || TYPE_PTRMEM_P (type2)
-              || TYPE_PTRMEMFUNC_P (type2)))
+      if (!(TYPE_PTR_P (type1) || TYPE_PTR_TO_MEMBER_P (type1))
+         || !(TYPE_PTR_P (type2) || TYPE_PTR_TO_MEMBER_P (type2)))
        return;
       
       /* We don't check that the two types are the same; the logic
@@ -1894,8 +1909,8 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
   if (type2 && !same_type_p (type1, type2)
       && TREE_CODE (type1) == TREE_CODE (type2)
       && (TREE_CODE (type1) == REFERENCE_TYPE
-         || (TREE_CODE (type1) == POINTER_TYPE
-             && TYPE_PTRMEM_P (type1) == TYPE_PTRMEM_P (type2))
+         || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
+         || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2))
          || TYPE_PTRMEMFUNC_P (type1)
          || IS_AGGR_TYPE (type1)
          || TREE_CODE (type1) == ENUMERAL_TYPE))
@@ -2605,76 +2620,6 @@ build_user_type_conversion (tree totype, tree expr, int flags)
   return NULL_TREE;
 }
 
-/* Find the possibly overloaded set of functions corresponding to a
-   call of the form SCOPE::NAME (...). NAME might be a
-   TEMPLATE_ID_EXPR, OVERLOAD, _DECL, or IDENTIFIER_NODE.  */
-
-tree
-resolve_scoped_fn_name (tree scope, tree name)
-{
-  tree fn = NULL_TREE;
-  tree template_args = NULL_TREE;
-  bool is_template_id = TREE_CODE (name) == TEMPLATE_ID_EXPR;
-  
-  if (is_template_id)
-    {
-      template_args = TREE_OPERAND (name, 1);
-      name = TREE_OPERAND (name, 0);
-    }
-  if (TREE_CODE (name) == OVERLOAD)
-    name = DECL_NAME (get_first_fn (name));
-  
-  if (TREE_CODE (scope) == NAMESPACE_DECL)
-    fn = lookup_namespace_name (scope, name);
-  else if (!CLASS_TYPE_P (scope))
-    {
-      error ("`%T' is not a class type", scope);
-      return error_mark_node;
-    }
-  else
-    {
-      if (!TYPE_BEING_DEFINED (scope)
-         && !COMPLETE_TYPE_P (complete_type (scope)))
-       {
-         error ("incomplete type '%T' cannot be used to name a scope",
-                scope);
-         return error_mark_node;
-       }
-      
-      if (BASELINK_P (name))
-       fn = name;
-      else
-       fn = lookup_member (scope, name, /*protect=*/1, /*want_type=*/false);
-      if (fn && current_class_type)
-       fn = (adjust_result_of_qualified_name_lookup 
-             (fn, scope, current_class_type));
-
-      /* It might be the name of a function pointer member.  */
-      if (fn && TREE_CODE (fn) == FIELD_DECL)
-       fn = finish_non_static_data_member (fn, current_class_ref, scope);
-    }
-  
-  if (!fn)
-    {
-      error ("'%D' has no member named '%E'", scope, name);
-      return error_mark_node;
-    }
-  if (is_template_id)
-    {
-      tree fns = fn;
-
-      if (BASELINK_P (fn))
-       fns = BASELINK_FUNCTIONS (fns);
-      fns = build_nt (TEMPLATE_ID_EXPR, fns, template_args);
-      if (BASELINK_P (fn))
-       BASELINK_FUNCTIONS (fn) = fns;
-      else
-       fn = fns;
-    }
-  
-  return fn;
-}
-
 /* Do any initial processing on the arguments to a function call.  */
 
 static tree
@@ -3379,15 +3324,12 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
        cv-qualification of either the second or the third operand.
        The result is of the common type.  */
   else if ((null_ptr_cst_p (arg2) 
-           && (TYPE_PTR_P (arg3_type) || TYPE_PTRMEM_P (arg3_type)
-               || TYPE_PTRMEMFUNC_P (arg3_type)))
+           && (TYPE_PTR_P (arg3_type) || TYPE_PTR_TO_MEMBER_P (arg3_type)))
           || (null_ptr_cst_p (arg3) 
-              && (TYPE_PTR_P (arg2_type) || TYPE_PTRMEM_P (arg2_type)
-               || TYPE_PTRMEMFUNC_P (arg2_type)))
+              && (TYPE_PTR_P (arg2_type) || TYPE_PTR_TO_MEMBER_P (arg2_type)))
           || (TYPE_PTR_P (arg2_type) && TYPE_PTR_P (arg3_type))
           || (TYPE_PTRMEM_P (arg2_type) && TYPE_PTRMEM_P (arg3_type))
-          || (TYPE_PTRMEMFUNC_P (arg2_type) 
-              && TYPE_PTRMEMFUNC_P (arg3_type)))
+          || (TYPE_PTRMEMFUNC_P (arg2_type) && TYPE_PTRMEMFUNC_P (arg3_type)))
     {
       result_type = composite_pointer_type (arg2_type, arg3_type, arg2,
                                            arg3, "conditional expression");
@@ -5401,25 +5343,17 @@ compare_ics (tree ics1, tree ics2)
      for pointers A*, except opposite: if B is derived from A then
      A::* converts to B::*, not vice versa.  For that reason, we
      switch the from_ and to_ variables here.  */
-  else if (TYPE_PTRMEM_P (from_type1)
-          && TYPE_PTRMEM_P (from_type2)
-          && TYPE_PTRMEM_P (to_type1)
-          && TYPE_PTRMEM_P (to_type2))
-    {
-      deref_to_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type1));
-      deref_to_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type2));
-      deref_from_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type1));
-      deref_from_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type2));
-    }
-  else if (TYPE_PTRMEMFUNC_P (from_type1)
-          && TYPE_PTRMEMFUNC_P (from_type2)
-          && TYPE_PTRMEMFUNC_P (to_type1)
-          && TYPE_PTRMEMFUNC_P (to_type2))
-    {
-      deref_to_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type1);
-      deref_to_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type2);
-      deref_from_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type1);
-      deref_from_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type2);
+  else if ((TYPE_PTRMEM_P (from_type1) && TYPE_PTRMEM_P (from_type2)
+           && TYPE_PTRMEM_P (to_type1) && TYPE_PTRMEM_P (to_type2))
+          || (TYPE_PTRMEMFUNC_P (from_type1)
+              && TYPE_PTRMEMFUNC_P (from_type2)
+              && TYPE_PTRMEMFUNC_P (to_type1)
+              && TYPE_PTRMEMFUNC_P (to_type2)))
+    {
+      deref_to_type1 = TYPE_PTRMEM_CLASS_TYPE (from_type1);
+      deref_to_type2 = TYPE_PTRMEM_CLASS_TYPE (from_type2);
+      deref_from_type1 = TYPE_PTRMEM_CLASS_TYPE (to_type1);
+      deref_from_type2 = TYPE_PTRMEM_CLASS_TYPE (to_type2);
     }
 
   if (deref_from_type1 != NULL_TREE
index 06cb635671949afe9bf47e45b2aed9c2dafa466c..4c46d1c9c66aceb70f3fbe0b1bd3b4a145cce1ae 100644 (file)
@@ -3078,7 +3078,7 @@ check_field_decls (tree t, tree *access_decls,
 
       type = strip_array_types (type);
       
-      if (TREE_CODE (type) == POINTER_TYPE)
+      if (TYPE_PTR_P (type))
        has_pointers = 1;
 
       if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))
index 3c687113b951c5365f1c624b5a4468ecf1147d78..adf670596d4510c26e5ac5ff6bc957f26b59eb55 100644 (file)
@@ -364,7 +364,7 @@ cp_var_mod_type_p (tree type)
 {
   /* If TYPE is a pointer-to-member, it is variably modified if either
      the class or the member are variably modified.  */
-  if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
+  if (TYPE_PTR_TO_MEMBER_P (type))
     return (variably_modified_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
            || variably_modified_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type)));
 
index 8fef2deb96d1bd09e75ce1a99a2588e93a3016e2..b46675272871fb63ece42f9345a4e205997f79a2 100644 (file)
@@ -2421,8 +2421,7 @@ struct lang_decl GTY(())
   (ARITHMETIC_TYPE_P (TYPE)                    \
    || TREE_CODE (TYPE) == ENUMERAL_TYPE                \
    || TYPE_PTR_P (TYPE)                                \
-   || TYPE_PTRMEM_P (TYPE)                     \
-   || TYPE_PTRMEMFUNC_P (TYPE))
+   || TYPE_PTR_TO_MEMBER_P (TYPE))
 
 /* [dcl.init.aggr]
 
@@ -2508,14 +2507,15 @@ struct lang_decl GTY(())
 #define TYPE_HAS_TRIVIAL_ASSIGN_REF(NODE) \
   (TYPE_HAS_ASSIGN_REF (NODE) && ! TYPE_HAS_COMPLEX_ASSIGN_REF (NODE))
 
-#define TYPE_PTRMEM_P(NODE)                                    \
-  (TREE_CODE (NODE) == POINTER_TYPE                            \
-   && TREE_CODE (TREE_TYPE (NODE)) == OFFSET_TYPE)
-#define TYPE_PTR_P(NODE)                               \
-  (TREE_CODE (NODE) == POINTER_TYPE                    \
-   && TREE_CODE (TREE_TYPE (NODE)) != OFFSET_TYPE)
-#define TYPE_PTROB_P(NODE)                                             \
-  (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE  \
+/* Returns true if NODE is a pointer-to-data-member.  */
+#define TYPE_PTRMEM_P(NODE)                    \
+  (TREE_CODE (NODE) == OFFSET_TYPE)
+#define TYPE_PTR_P(NODE)                       \
+  (TREE_CODE (NODE) == POINTER_TYPE)
+#define TYPE_PTROB_P(NODE)                             \
+  (TYPE_PTR_P (NODE)                                   \
+   && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE    \
+   && TREE_CODE (TREE_TYPE (NODE)) != METHOD_TYPE      \
    && TREE_CODE (TREE_TYPE (NODE)) != VOID_TYPE)
 #define TYPE_PTROBV_P(NODE)                                            \
   (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE)
@@ -2536,6 +2536,10 @@ struct lang_decl GTY(())
 #define TYPE_PTRMEMFUNC_FLAG(NODE) \
   (LANG_TYPE_CLASS_CHECK (NODE)->ptrmemfunc_flag)
 
+/* Returns true if NODE is a pointer-to-member.  */
+#define TYPE_PTR_TO_MEMBER_P(NODE) \
+  (TYPE_PTRMEM_P (NODE) || TYPE_PTRMEMFUNC_P (NODE))
+
 /* Indicates when overload resolution may resolve to a pointer to
    member function. [expr.unary.op]/3 */
 #define PTRMEM_OK_P(NODE) TREE_LANG_FLAG_0 (NODE)
@@ -2574,13 +2578,13 @@ struct lang_decl GTY(())
    type `const X*'.  */
 #define TYPE_PTRMEM_CLASS_TYPE(NODE)                   \
   (TYPE_PTRMEM_P (NODE)                                        \
-   ? TYPE_OFFSET_BASETYPE (TREE_TYPE (NODE))           \
+   ? TYPE_OFFSET_BASETYPE (NODE)               \
    : TYPE_PTRMEMFUNC_OBJECT_TYPE (NODE))
 
 /* For a pointer-to-member type of the form `T X::*', this is `T'.  */
 #define TYPE_PTRMEM_POINTED_TO_TYPE(NODE)              \
    (TYPE_PTRMEM_P (NODE)                               \
-    ? TREE_TYPE (TREE_TYPE (NODE))                     \
+    ? TREE_TYPE (NODE)                                 \
     : TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (NODE)))
 
 /* For a pointer-to-member constant `X::Y' this is the RECORD_TYPE for
@@ -3527,7 +3531,6 @@ extern tree build_method_call (tree, tree, tree, tree, int);
 extern bool null_ptr_cst_p (tree);
 extern bool sufficient_parms_p (tree);
 extern tree type_decays_to (tree);
-extern tree resolve_scoped_fn_name (tree, tree);
 extern tree build_user_type_conversion (tree, tree, int);
 extern tree build_new_function_call (tree, tree);
 extern tree build_operator_new_call (tree, tree, tree *, tree *);
@@ -3876,8 +3879,7 @@ extern int is_aggr_type                           (tree, int);
 extern tree get_aggr_from_typedef              (tree, int);
 extern tree get_type_value                     (tree);
 extern tree build_zero_init                    (tree, tree, bool);
-extern tree build_offset_ref                   (tree, tree);
-extern tree resolve_offset_ref                 (tree);
+extern tree build_offset_ref                   (tree, tree, bool);
 extern tree build_new                          (tree, tree, tree, int);
 extern tree build_vec_init                     (tree, tree, tree, int);
 extern tree build_x_delete                     (tree, int, tree);
@@ -4272,7 +4274,6 @@ extern tree commonparms                           (tree, tree);
 extern tree original_type                      (tree);
 extern bool comp_except_specs                  (tree, tree, bool);
 extern bool comptypes                          (tree, tree, int);
-extern int comp_target_types                   (tree, tree, int);
 extern bool compparms                          (tree, tree);
 extern int comp_cv_qualification                (tree, tree);
 extern int comp_cv_qual_signature               (tree, tree);
index bc9b309fa25e1f95bee9a2c54a4324eea9254968..2cdf39535349221ecd2c2e8a4a8400d4afe3c755 100644 (file)
@@ -180,55 +180,57 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
            }
        }
 
-      if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+      if (TYPE_PTRMEMFUNC_P (type))
        {
-         tree b1; 
-         tree b2;
-         tree binfo;
-         enum tree_code code = PLUS_EXPR;
-         base_kind bk;
+         error ("cannot convert `%E' from type `%T' to type `%T'",
+                   expr, intype, type);
+         return error_mark_node;
+       }
 
-         b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
-         b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype));
-         binfo = lookup_base (b1, b2, ba_check, &bk);
-         if (!binfo)
-           {
-             binfo = lookup_base (b2, b1, ba_check, &bk);
-             code = MINUS_EXPR;
-           }
-         if (binfo == error_mark_node)
-           return error_mark_node;
+      return build_nop (type, expr);
+    }
+  else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+    {
+      tree b1; 
+      tree b2;
+      tree binfo;
+      enum tree_code code = PLUS_EXPR;
+      base_kind bk;
+
+      b1 = TYPE_PTRMEM_CLASS_TYPE (type);
+      b2 = TYPE_PTRMEM_CLASS_TYPE (intype);
+      binfo = lookup_base (b1, b2, ba_check, &bk);
+      if (!binfo)
+       {
+         binfo = lookup_base (b2, b1, ba_check, &bk);
+         code = MINUS_EXPR;
+       }
+      if (binfo == error_mark_node)
+       return error_mark_node;
 
-          if (bk == bk_via_virtual)
+      if (bk == bk_via_virtual)
+       {
+         if (force)
+           warning ("pointer to member cast from `%T' to `%T' is via virtual base",
+                    intype, type);
+         else
            {
-             if (force)
-               warning ("pointer to member cast from `%T' to `%T' is via virtual base",
-                           TREE_TYPE (intype), TREE_TYPE (type));
-              else
-                {
-                 error ("pointer to member cast from `%T' to `%T' is via virtual base",
-                           TREE_TYPE (intype), TREE_TYPE (type));
-                 return error_mark_node;
-               }
-             /* This is a reinterpret cast, whose result is unspecified.
-                We choose to do nothing.  */
-             return build1 (NOP_EXPR, type, expr);
+             error ("pointer to member cast from `%T' to `%T' is via virtual base",
+                    intype, type);
+             return error_mark_node;
            }
-             
-         if (TREE_CODE (expr) == PTRMEM_CST)
-           expr = cplus_expand_constant (expr);
-
-         if (binfo)
-           expr = size_binop (code, convert (sizetype, expr),
-                              BINFO_OFFSET (binfo));
-       }
-      else if (TYPE_PTRMEMFUNC_P (type))
-       {
-         error ("cannot convert `%E' from type `%T' to type `%T'",
-                   expr, intype, type);
-         return error_mark_node;
+         /* This is a reinterpret cast, whose result is unspecified.
+            We choose to do nothing.  */
+         return build1 (NOP_EXPR, type, expr);
        }
 
+      if (TREE_CODE (expr) == PTRMEM_CST)
+       expr = cplus_expand_constant (expr);
+
+      if (binfo && !integer_zerop (BINFO_OFFSET (binfo)))
+       expr = size_binop (code, 
+                          build_nop (sizetype, expr),
+                          BINFO_OFFSET (binfo));
       return build_nop (type, expr);
     }
   else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
@@ -253,8 +255,6 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
       return error_mark_node;
     }
 
-  my_friendly_assert (form != OFFSET_TYPE, 186);
-
   if (integer_zerop (expr))
     {
       if (TYPE_PTRMEMFUNC_P (type))
@@ -271,8 +271,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
       force_fit_type (expr, 0);
       return expr;
     }
-  else if ((TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
-          && INTEGRAL_CODE_P (form))
+  else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form))
     {
       error ("invalid conversion from '%T' to '%T'", intype, type);
       return error_mark_node;
@@ -454,7 +453,7 @@ convert_to_reference (tree reftype, tree expr, int convtype,
   register tree intype;
   tree rval = NULL_TREE;
   tree rval_as_conversion = NULL_TREE;
-  int i;
+  bool can_convert_intype_to_type;
 
   if (TREE_CODE (type) == FUNCTION_TYPE 
       && TREE_TYPE (expr) == unknown_type_node)
@@ -473,9 +472,9 @@ convert_to_reference (tree reftype, tree expr, int convtype,
 
   intype = TYPE_MAIN_VARIANT (intype);
 
-  i = comp_target_types (type, intype, 0);
-
-  if (i <= 0 && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype)
+  can_convert_intype_to_type = can_convert (type, intype);
+  if (!can_convert_intype_to_type
+      && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype)
       && ! (flags & LOOKUP_NO_CONVERSION))
     {
       /* Look for a user-defined conversion to lvalue that we can use.  */
@@ -489,12 +488,12 @@ convert_to_reference (tree reftype, tree expr, int convtype,
          expr = rval_as_conversion;
          rval_as_conversion = NULL_TREE;
          intype = type;
-         i = 1;
+         can_convert_intype_to_type = 1;
        }
     }
 
-  if (((convtype & CONV_STATIC) && i == -1)
-      || ((convtype & CONV_IMPLICIT) && i == 1))
+  if (((convtype & CONV_STATIC) && can_convert (intype, type))
+      || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type))
     {
       if (flags & LOOKUP_COMPLAIN)
        {
@@ -550,8 +549,6 @@ convert_to_reference (tree reftype, tree expr, int convtype,
       return rval;
     }
 
-  my_friendly_assert (TREE_CODE (intype) != OFFSET_TYPE, 189);
-
   if (flags & LOOKUP_COMPLAIN)
     error ("cannot convert type `%T' to type `%T'", intype, reftype);
 
@@ -618,8 +615,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
   register tree e = expr;
   register enum tree_code code = TREE_CODE (type);
 
-  if (e == error_mark_node
-      || TREE_TYPE (e) == error_mark_node)
+  if (error_operand_p (e) || type == error_mark_node)
     return error_mark_node;
 
   complete_type (type);
@@ -671,13 +667,6 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
       return e;
     }
 
-  /* Just convert to the type of the member.  */
-  if (code == OFFSET_TYPE)
-    {
-      type = TREE_TYPE (type);
-      code = TREE_CODE (type);
-    }
-
   if (INTEGRAL_CODE_P (code))
     {
       tree intype = TREE_TYPE (e);
@@ -721,8 +710,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
        }
       return fold (convert_to_integer (type, e));
     }
-  if (code == POINTER_TYPE || code == REFERENCE_TYPE
-      || TYPE_PTRMEMFUNC_P (type))
+  if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))
     return fold (cp_convert_to_pointer (type, e, false));
   if (code == VECTOR_TYPE)
     return fold (convert_to_vector (type, e));
@@ -1178,10 +1166,20 @@ type_promotes_to (tree type)
 tree 
 perform_qualification_conversions (tree type, tree expr)
 {
-  if (TREE_CODE (type) == POINTER_TYPE
-      && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
-      && comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (expr))))
-    return build1 (NOP_EXPR, type, expr);
+  tree expr_type;
+
+  expr_type = TREE_TYPE (expr);
+
+  if (TYPE_PTR_P (type) && TYPE_PTR_P (expr_type)
+      && comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (expr_type)))
+    return build_nop (type, expr);
+  else if (TYPE_PTR_TO_MEMBER_P (type)
+          && TYPE_PTR_TO_MEMBER_P (expr_type)
+          && same_type_p (TYPE_PTRMEM_CLASS_TYPE (type),
+                          TYPE_PTRMEM_CLASS_TYPE (expr_type))
+          && comp_ptr_ttypes (TYPE_PTRMEM_POINTED_TO_TYPE (type),
+                              TYPE_PTRMEM_POINTED_TO_TYPE (expr_type)))
+    return build_nop (type, expr);
   else
     return error_mark_node;
 }
index 22137be5967924bd7c2036d5ddde75d90d7d1faf..7f36c99e28aca7b759702fdcc7790a7686e733ae 100644 (file)
@@ -9284,7 +9284,26 @@ build_ptrmemfunc_type (tree type)
 tree
 build_ptrmem_type (tree class_type, tree member_type)
 {
-  return build_pointer_type (build_offset_type (class_type, member_type));
+  if (TREE_CODE (member_type) == METHOD_TYPE)
+    {
+      tree arg_types;
+
+      arg_types = TYPE_ARG_TYPES (member_type);
+      class_type = (cp_build_qualified_type 
+                   (class_type,
+                    cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types)))));
+      member_type 
+       = build_cplus_method_type (class_type, 
+                                  TREE_TYPE (member_type),
+                                  TREE_CHAIN (arg_types));
+      return build_ptrmemfunc_type (build_pointer_type (member_type));
+    }
+  else
+    {
+      my_friendly_assert (TREE_CODE (member_type) != FUNCTION_TYPE,
+                         20030716);
+      return build_offset_type (class_type, member_type);
+    }
 }
 
 /* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
@@ -9521,10 +9540,6 @@ create_array_type_for_decl (tree name, tree type, tree size)
       error_msg = "array of references";
       break;
 
-    case OFFSET_TYPE:
-      error_msg = "array of data members";
-      break;
-
     case METHOD_TYPE:
       error_msg = "array of function members";
       break;
@@ -11360,8 +11375,6 @@ grokdeclarator (tree declarator,
        }
       else if (TREE_CODE (type) == FUNCTION_TYPE)
        type = build_pointer_type (type);
-      else if (TREE_CODE (type) == OFFSET_TYPE)
-       type = build_pointer_type (type);
     }
 
   {
@@ -11991,12 +12004,6 @@ grokparms (tree first_parm)
              type = build_pointer_type (type);
              TREE_TYPE (decl) = type;
            }
-         else if (TREE_CODE (type) == OFFSET_TYPE)
-           {
-             error ("parameter `%D' invalidly declared offset type", decl);
-             type = build_pointer_type (type);
-             TREE_TYPE (decl) = type;
-           }
          else if (abstract_virtuals_error (decl, type))
            any_error = 1;  /* Seems like a good idea.  */
          else if (POINTER_TYPE_P (type))
index c8091892cb7465b22f50283f26ded6bec72822ce..b48f25b7752bf0af510776adc763b39bfbe2f5d2 100644 (file)
@@ -237,18 +237,13 @@ cp_dump_tree (void* dump_info, tree t)
        }
       break;
 
-    case POINTER_TYPE:
-      if (TYPE_PTRMEM_P (t))
-       {
-         dump_string (di, "ptrmem");
-         dump_child ("ptd", TYPE_PTRMEM_POINTED_TO_TYPE (t));
-         dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t));
-         return true;
-       }
-      break;
+    case OFFSET_TYPE:
+      dump_string (di, "ptrmem");
+      dump_child ("ptd", TYPE_PTRMEM_POINTED_TO_TYPE (t));
+      dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t));
+      return true;
 
     case RECORD_TYPE:
-    case UNION_TYPE:
       if (TYPE_PTRMEMFUNC_P (t))
        {
          dump_string (di, "ptrmem");
@@ -256,7 +251,9 @@ cp_dump_tree (void* dump_info, tree t)
          dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t));
          return true;
        }
+      /* Fall through.  */
 
+    case UNION_TYPE:
       /* Is it a type used as a base? */
       if (TYPE_CONTEXT (t) && TREE_CODE (TYPE_CONTEXT (t)) == TREE_CODE (t)
          && CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t)
index c547d672bc61c24fd9363b0dc9edaf2a96188f1d..11a548bd1fe80994f1c7de02be2b6270c0387235 100644 (file)
@@ -587,19 +587,14 @@ dump_type_prefix (tree t, int flags)
        tree sub = TREE_TYPE (t);
 
        padding = dump_type_prefix (sub, flags);
-       /* A tree for a member pointer looks like pointer to offset,
-          so let the OFFSET_TYPE case handle it.  */
-       if (!TYPE_PTRMEM_P (t))
+       if (TREE_CODE (sub) == ARRAY_TYPE)
          {
-           if (TREE_CODE (sub) == ARRAY_TYPE)
-              {
-                output_add_space (scratch_buffer);
-                print_left_paren (scratch_buffer);
-              }
-            output_add_character
-              (scratch_buffer, "&*"[TREE_CODE (t) == POINTER_TYPE]);
-           padding = dump_qualifiers (t, before);
+           output_add_space (scratch_buffer);
+           print_left_paren (scratch_buffer);
          }
+       output_add_character
+         (scratch_buffer, "&*"[TREE_CODE (t) == POINTER_TYPE]);
+       padding = dump_qualifiers (t, before);
       }
       break;
 
index 160a946ef9a7cfd51fa35258eaed544f54d15c42..630f0789073abc2a1e284daff5739121fc8425ba 100644 (file)
@@ -51,11 +51,8 @@ cplus_expand_constant (tree cst)
        member = PTRMEM_CST_MEMBER (cst);
 
        if (TREE_CODE (member) == FIELD_DECL) 
-         {
-           /* Find the offset for the field.  */
-           tree offset = byte_position (member);
-           cst = fold (build1 (NOP_EXPR, type, offset));
-         }
+         /* Find the offset for the field.  */
+         cst = fold (build_nop (type, byte_position (member)));
        else
          {
            tree delta;
index dad52284e6377995cbf5aff22d9677edc1d8e83b..fc10a24940b7ed5e494ca7346337f373fb4b145a 100644 (file)
@@ -1337,10 +1337,11 @@ get_type_value (tree name)
     return NULL_TREE;
 }
 
-/* Build a reference to a member of an aggregate.  This is not a
-   C++ `&', but really something which can have its address taken,
-   and then act as a pointer to member, for example TYPE :: FIELD
-   can have its address taken by saying & TYPE :: FIELD.
+/* Build a reference to a member of an aggregate.  This is not a C++
+   `&', but really something which can have its address taken, and
+   then act as a pointer to member, for example TYPE :: FIELD can have
+   its address taken by saying & TYPE :: FIELD.  ADDRESS_P is true if
+   this expression is the operand of "&".
 
    @@ Prints out lousy diagnostics for operator <typename>
    @@ fields.
@@ -1348,7 +1349,7 @@ get_type_value (tree name)
    @@ This function should be rewritten and placed in search.c.  */
 
 tree
-build_offset_ref (tree type, tree name)
+build_offset_ref (tree type, tree name, bool address_p)
 {
   tree decl;
   tree member;
@@ -1435,8 +1436,33 @@ build_offset_ref (tree type, tree name)
        return error_mark_node;
     }
 
+  if (!member)
+    {
+      error ("`%D' is not a member of type `%T'", name, type);
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (member) == TYPE_DECL)
+    {
+      TREE_USED (member) = 1;
+      return member;
+    }
+  /* static class members and class-specific enum
+     values can be returned without further ado.  */
+  if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL)
+    {
+      mark_used (member);
+      return convert_from_reference (member);
+    }
+
+  if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member))
+    {
+      error ("invalid pointer to bit-field `%D'", member);
+      return error_mark_node;
+    }
+
   /* A lot of this logic is now handled in lookup_member.  */
-  if (member && BASELINK_P (member))
+  if (BASELINK_P (member))
     {
       /* Go from the TREE_BASELINK to the member function info.  */
       tree fnfields = member;
@@ -1475,104 +1501,63 @@ build_offset_ref (tree type, tree name)
          mark_used (t);
          if (DECL_STATIC_FUNCTION_P (t))
            return t;
-         t = build (OFFSET_REF, TREE_TYPE (t), decl, t);
-         PTRMEM_OK_P (t) = 1;
-         return t;
+         member = t;
+       }
+      else
+       {
+         TREE_TYPE (fnfields) = unknown_type_node;
+         member = fnfields;
        }
-
-      TREE_TYPE (fnfields) = unknown_type_node;
-      
-      t = build (OFFSET_REF, unknown_type_node, decl, fnfields);
-      PTRMEM_OK_P (t) = 1;
-      return t;
     }
 
-  if (member == NULL_TREE)
+  if (!address_p)
     {
-      error ("`%D' is not a member of type `%T'", name, type);
-      return error_mark_node;
-    }
+      /* If MEMBER is non-static, then the program has fallen afoul of
+        [expr.prim]:
 
-  if (TREE_CODE (member) == TYPE_DECL)
-    {
-      TREE_USED (member) = 1;
-      return member;
-    }
-  /* static class members and class-specific enum
-     values can be returned without further ado.  */
-  if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL)
-    {
-      mark_used (member);
-      return convert_from_reference (member);
-    }
+          An id-expression that denotes a nonstatic data member or
+          nonstatic member function of a class can only be used:
 
-  if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member))
-    {
-      error ("invalid pointer to bit-field `%D'", member);
-      return error_mark_node;
-    }
+          -- as part of a class member access (_expr.ref_) in which the
+          object-expression refers to the member's class or a class
+          derived from that class, or
 
-  /* static class functions too.  */
-  if (TREE_CODE (member) == FUNCTION_DECL
-      && TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE)
-    abort ();
+          -- to form a pointer to member (_expr.unary.op_), or
+
+          -- in the body of a nonstatic member function of that class or
+          of a class derived from that class (_class.mfct.nonstatic_), or
+
+          -- in a mem-initializer for a constructor for that class or for
+          a class derived from that class (_class.base.init_).  */
+      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member))
+       {
+         /* In Microsoft mode, treat a non-static member function as if
+            it were a pointer-to-member.  */
+         if (flag_ms_extensions)
+           {
+             member = build (OFFSET_REF, TREE_TYPE (member), decl, member);
+             PTRMEM_OK_P (member) = 1;
+             return build_unary_op (ADDR_EXPR, member, 0);
+           }
+         error ("invalid use of non-static member function `%D'", member);
+         return error_mark_node;
+       }
+      else if (TREE_CODE (member) == FIELD_DECL)
+       {
+         error ("invalid use of non-static data member `%D'", member);
+         return error_mark_node;
+       }
+      return member;
+    }
 
   /* In member functions, the form `type::name' is no longer
      equivalent to `this->type::name', at least not until
      resolve_offset_ref.  */
-  member = build (OFFSET_REF, build_offset_type (type, TREE_TYPE (member)), 
-                 decl, member);
+  member = build (OFFSET_REF, TREE_TYPE (member), decl, member);
   PTRMEM_OK_P (member) = 1;
   return member;
 }
 
-/* If a OFFSET_REF made it through to here, then it did
-   not have its address taken.  */
-
-tree
-resolve_offset_ref (tree exp)
-{
-  tree member;
-
-  my_friendly_assert (TREE_CODE (exp) == OFFSET_REF, 20030703);
-
-  member = TREE_OPERAND (exp, 1);
-
-  /* If MEMBER is non-static, then the program has fallen afoul of
-     [expr.prim]:
-
-       An id-expression that denotes a nonstatic data member or
-       nonstatic member function of a class can only be used:
-
-       -- as part of a class member access (_expr.ref_) in which the
-       object-expression refers to the member's class or a class
-       derived from that class, or
-
-       -- to form a pointer to member (_expr.unary.op_), or
-
-       -- in the body of a nonstatic member function of that class or
-       of a class derived from that class (_class.mfct.nonstatic_), or
-
-       -- in a mem-initializer for a constructor for that class or for
-       a class derived from that class (_class.base.init_).  */
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member))
-    {
-      /* In Microsoft mode, treat a non-static member function as if
-        it were a pointer-to-member.  */
-      if (flag_ms_extensions)
-       return build_unary_op (ADDR_EXPR, exp, 0);
-      error ("invalid use of non-static member function `%D'", member);
-      return error_mark_node;
-    }
-  else if (TREE_CODE (member) == FIELD_DECL)
-    {
-      error ("invalid use of non-static data member `%D'", member);
-      return error_mark_node;
-    }
-
-  return member;
-}
-
 /* If DECL is a `const' declaration, and its value is a known
    constant, then return that value.  */
 
index df45bb60b57347149c4870eda37d8e567148eb98..3cef2e2257f755723ad8ac6607023bbf5ff43d46 100644 (file)
@@ -3581,17 +3581,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                   it does not.  Therefore, we have to manually obtain
                   the underlying type here.  */
                scope = non_reference (scope);
-               /* If the SCOPE is an OFFSET_TYPE, then we grab the
-                  type of the field.  We get an OFFSET_TYPE for
-                  something like:
-
-                    S::T.a ...
-
-                  Probably, we should not get an OFFSET_TYPE here;
-                  that transformation should be made only if `&S::T'
-                  is written.  */
-               if (TREE_CODE (scope) == OFFSET_TYPE)
-                 scope = TREE_TYPE (scope);
                /* The type of the POSTFIX_EXPRESSION must be
                   complete.  */
                scope = complete_type_or_else (scope, NULL_TREE);
index 774d6d9150a6d0c8c93b5f3565bac989f15a131b..61d54b9efe2f2cc7a91ed0633ec81c200f1c7faa 100644 (file)
@@ -3004,8 +3004,7 @@ convert_nontype_argument (tree type, tree expr)
        Check this first since if expr_type is the unknown_type_node
        we would otherwise complain below.  */
     ;
-  else if (TYPE_PTRMEM_P (expr_type)
-          || TYPE_PTRMEMFUNC_P (expr_type))
+  else if (TYPE_PTR_TO_MEMBER_P (expr_type))
     {
       if (TREE_CODE (expr) != PTRMEM_CST)
        goto bad_argument;
@@ -3038,8 +3037,7 @@ convert_nontype_argument (tree type, tree expr)
                  else
                    error ("it must be the address of an object with external linkage");
                }
-             else if (TYPE_PTRMEM_P (expr_type)
-                      || TYPE_PTRMEMFUNC_P (expr_type))
+             else if (TYPE_PTR_TO_MEMBER_P (expr_type))
                error ("it must be a pointer-to-member of the form `&X::Y'");
 
              return NULL_TREE;
@@ -3070,9 +3068,7 @@ convert_nontype_argument (tree type, tree expr)
          return error_mark_node;
        }
     }
-  else if (INTEGRAL_TYPE_P (expr_type) 
-          || TYPE_PTRMEM_P (expr_type) 
-          || TYPE_PTRMEMFUNC_P (expr_type))
+  else if (INTEGRAL_TYPE_P (expr_type) || TYPE_PTR_TO_MEMBER_P (expr_type))
     {
       if (! TREE_CONSTANT (expr))
        {
@@ -3117,31 +3113,32 @@ convert_nontype_argument (tree type, tree expr)
        goto non_constant;
       
       return expr;
-       
+
+    case OFFSET_TYPE:
+      {
+       tree e;
+
+       /* For a non-type template-parameter of type pointer to data
+          member, qualification conversions (_conv.qual_) are
+          applied.  */
+       e = perform_qualification_conversions (type, expr);
+       if (TREE_CODE (e) == NOP_EXPR)
+         /* The call to perform_qualification_conversions will
+            insert a NOP_EXPR over EXPR to do express conversion,
+            if necessary.  But, that will confuse us if we use
+            this (converted) template parameter to instantiate
+            another template; then the thing will not look like a
+            valid template argument.  So, just make a new
+            constant, of the appropriate type.  */
+         e = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr));
+       return e;
+      }
+
     case POINTER_TYPE:
       {
        tree type_pointed_to = TREE_TYPE (type);
  
-       if (TYPE_PTRMEM_P (type))
-         {
-           tree e;
-
-           /* For a non-type template-parameter of type pointer to data
-              member, qualification conversions (_conv.qual_) are
-              applied.  */
-           e = perform_qualification_conversions (type, expr);
-           if (TREE_CODE (e) == NOP_EXPR)
-             /* The call to perform_qualification_conversions will
-                insert a NOP_EXPR over EXPR to do express conversion,
-                if necessary.  But, that will confuse us if we use
-                this (converted) template parameter to instantiate
-                another template; then the thing will not look like a
-                valid template argument.  So, just make a new
-                constant, of the appropriate type.  */
-             e = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr));
-           return e;
-         }
-       else if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE)
+       if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE)
          { 
            /* For a non-type template-parameter of type pointer to
               function, only the function-to-pointer conversion
@@ -3421,8 +3418,7 @@ convert_template_argument (tree parm,
   inner_args = INNERMOST_TEMPLATE_ARGS (args);
 
   if (TREE_CODE (arg) == TREE_LIST 
-      && TREE_TYPE (arg) != NULL_TREE
-      && TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
+      && TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
     {  
       /* The template argument was the name of some
         member function.  That's usually
@@ -6815,21 +6811,26 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          }
        my_friendly_assert (TREE_CODE (type) != METHOD_TYPE, 20011231);
        if (TREE_CODE (type) == FUNCTION_TYPE)
-         /* This is really a method type. The cv qualifiers of the
-            this pointer should _not_ be determined by the cv
-            qualifiers of the class type.  They should be held
-            somewhere in the FUNCTION_TYPE, but we don't do that at
-            the moment.  Consider
-               typedef void (Func) () const;
-
-               template <typename T1> void Foo (Func T1::*);
-
-             */
-         return build_cplus_method_type (TYPE_MAIN_VARIANT (r),
-                                         TREE_TYPE (type),
-                                         TYPE_ARG_TYPES (type));
+         {
+           /* This is really a method type. The cv qualifiers of the
+              this pointer should _not_ be determined by the cv
+              qualifiers of the class type.  They should be held
+              somewhere in the FUNCTION_TYPE, but we don't do that at
+              the moment.  Consider
+                 typedef void (Func) () const;
+
+                 template <typename T1> void Foo (Func T1::*);
+
+               */
+           tree method_type;
+
+           method_type = build_cplus_method_type (TYPE_MAIN_VARIANT (r),
+                                                  TREE_TYPE (type),
+                                                  TYPE_ARG_TYPES (type));
+           return build_ptrmemfunc_type (build_pointer_type (method_type));
+         }
        else
-         return build_offset_type (r, type);
+         return build_ptrmem_type (r, type);
       }
     case FUNCTION_TYPE:
     case METHOD_TYPE:
@@ -9511,12 +9512,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
        }
       else
        {
-         /* If ARG is an offset type, we're trying to unify '*T' with
-            'U C::*', which is ill-formed. See the comment in the
-            POINTER_TYPE case about this ugliness.  */
-         if (TREE_CODE (arg) == OFFSET_TYPE)
-           return 1;
-         
          /* If PARM is `const T' and ARG is only `int', we don't have
             a match unless we are allowing additional qualification.
             If ARG is `const int' and PARM is just `T' that's OK;
@@ -9617,18 +9612,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
             level of pointers.  */
          strict |= (strict_in & UNIFY_ALLOW_DERIVED);
 
-       if (TREE_CODE (TREE_TYPE (parm)) == OFFSET_TYPE
-           && TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
-         {
-           /* Avoid getting confused about cv-quals; don't recurse here.
-              Pointers to members should really be just OFFSET_TYPE, not
-              this two-level nonsense...  */
-
-           parm = TREE_TYPE (parm);
-           arg = TREE_TYPE (arg);
-           goto offset;
-         }
-
        return unify (tparms, targs, TREE_TYPE (parm), 
                      TREE_TYPE (arg), strict);
       }
@@ -9782,7 +9765,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
                                    DEDUCE_EXACT, 0, -1);
 
     case OFFSET_TYPE:
-    offset:
       if (TREE_CODE (arg) != OFFSET_TYPE)
        return 1;
       if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
@@ -11286,9 +11268,7 @@ invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain)
     return 0;
   else if (POINTER_TYPE_P (type))
     return 0;
-  else if (TYPE_PTRMEM_P (type))
-    return 0;
-  else if (TYPE_PTRMEMFUNC_P (type))
+  else if (TYPE_PTR_TO_MEMBER_P (type))
     return 0;
   else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
     return 0;
@@ -11325,7 +11305,7 @@ dependent_type_p_r (tree type)
         dependent.  */
   type = TYPE_MAIN_VARIANT (type);
   /* -- a compound type constructed from any dependent type.  */
-  if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
+  if (TYPE_PTR_TO_MEMBER_P (type))
     return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
            || dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE 
                                           (type)));
index 067ddee17737fd8e5810d71a3f9be34bd409da34..fdad47d9cc4ef05abde8c13c0c6be59ccd93a51e 100644 (file)
@@ -331,8 +331,6 @@ get_tinfo_decl (tree type)
       return error_mark_node;
     }
 
-  if (TREE_CODE (type) == OFFSET_TYPE)
-    type = TREE_TYPE (type);
   if (TREE_CODE (type) == METHOD_TYPE)
     type = build_function_type (TREE_TYPE (type),
                                TREE_CHAIN (TYPE_ARG_TYPES (type)));
@@ -715,19 +713,17 @@ qualifier_flags (tree type)
 static bool
 target_incomplete_p (tree type)
 {
-  while (TREE_CODE (type) == POINTER_TYPE)
+  while (true)
     if (TYPE_PTRMEM_P (type))
       {
-        if (!COMPLETE_TYPE_P (TYPE_PTRMEM_CLASS_TYPE (type)))
-          return true;
-        type = TYPE_PTRMEM_POINTED_TO_TYPE (type);
+       if (!COMPLETE_TYPE_P (TYPE_PTRMEM_CLASS_TYPE (type)))
+         return true;
+       type = TYPE_PTRMEM_POINTED_TO_TYPE (type);
       }
-    else
+    else if (TREE_CODE (type) == POINTER_TYPE)
       type = TREE_TYPE (type);
-  if (!COMPLETE_OR_VOID_TYPE_P (type))
-    return true;
-  
-  return false;
+    else
+      return !COMPLETE_OR_VOID_TYPE_P (type);
 }
 
 /* Return a CONSTRUCTOR for the common part of the type_info objects. This
@@ -999,12 +995,10 @@ get_pseudo_ti_init (tree type, tree var_desc, bool *non_public_p)
   my_friendly_assert (at_eof, 20021120);
   switch (TREE_CODE (type))
     {
+    case OFFSET_TYPE:
+      return ptm_initializer (var_desc, type, non_public_p);
     case POINTER_TYPE:
-      if (TYPE_PTRMEM_P (type))
-       return ptm_initializer (var_desc, type, non_public_p);
-      else
-       return ptr_initializer (var_desc, type, non_public_p);
-      break;
+      return ptr_initializer (var_desc, type, non_public_p);
     case ENUMERAL_TYPE:
       return generic_initializer (var_desc, type);
       break;
@@ -1164,8 +1158,10 @@ get_pseudo_ti_desc (tree type)
 {
   switch (TREE_CODE (type))
     {
+    case OFFSET_TYPE:
+      return ptm_desc_type_node;
     case POINTER_TYPE:
-      return TYPE_PTRMEM_P (type) ? ptm_desc_type_node : ptr_desc_type_node;
+      return ptr_desc_type_node;
     case ENUMERAL_TYPE:
       return enum_desc_type_node;
     case FUNCTION_TYPE:
index c490ab80c702051274bdf3789c86189bab6e3302..102653a338eb5e0bfbab2118746e7a30f69108be 100644 (file)
@@ -1367,7 +1367,8 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
     {
       if (TREE_CODE (expr) == SCOPE_REF)
        expr = TREE_OPERAND (expr, 1);
-      expr = build_offset_ref (qualifying_class, expr);
+      expr = build_offset_ref (qualifying_class, expr, 
+                              /*address_p=*/true);
       return expr;
     }
 
@@ -1396,13 +1397,9 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
                 BASELINK_ACCESS_BINFO (expr),
                 /*preserve_reference=*/false));
       else if (done)
-       {
-         /* The expression is a qualified name whose address is not
-            being taken.  */
-         expr = build_offset_ref (qualifying_class, expr);
-         if (TREE_CODE (expr) == OFFSET_REF)
-           expr = resolve_offset_ref (expr);
-       }
+       /* The expression is a qualified name whose address is not
+          being taken.  */
+       expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false);
     }
 
   return expr;
index 59722ac40866206977466305704d544427ea413b..0fcba63bbf1f6e665979bb225d52a00409ea8a97 100644 (file)
@@ -1775,10 +1775,8 @@ pod_type_p (tree t)
     return 1;
   if (TYPE_PTR_P (t))
     return 1; /* pointer to non-member */
-  if (TYPE_PTRMEM_P (t))
-    return 1; /* pointer to member object */
-  if (TYPE_PTRMEMFUNC_P (t))
-    return 1; /* pointer to member function */
+  if (TYPE_PTR_TO_MEMBER_P (t))
+    return 1; /* pointer to member */
   
   if (! CLASS_TYPE_P (t))
     return 0; /* other non-class type (reference or function) */
index 0f1011e76b999e20efb9623abe47749d9830ce86..0356cb7aada97dab2f893f72bf0ea38737c40fdf 100644 (file)
@@ -48,22 +48,17 @@ Boston, MA 02111-1307, USA.  */
 static tree convert_for_assignment (tree, tree, const char *, tree, int);
 static tree cp_pointer_int_sum (enum tree_code, tree, tree);
 static tree rationalize_conditional_expr (enum tree_code, tree);
-static int comp_target_parms (tree, tree);
 static int comp_ptr_ttypes_real (tree, tree, int);
 static int comp_ptr_ttypes_const (tree, tree);
-static int comp_ptr_ttypes_reinterpret (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 qualify_type_recursive (tree, tree);
 static tree get_delta_difference (tree, tree, int);
-static int comp_cv_target_types (tree, tree, int);
 static void casts_away_constness_r (tree *, tree *);
 static bool casts_away_constness (tree, tree);
 static void maybe_warn_about_returning_address_of_local (tree);
-static tree strip_all_pointer_quals (tree);
 static tree lookup_destructor (tree, tree, tree);
 
 /* Return the target type of TYPE, which means return T for:
@@ -77,7 +72,7 @@ target_type (tree type)
         || TREE_CODE (type) == ARRAY_TYPE
         || TREE_CODE (type) == FUNCTION_TYPE
         || TREE_CODE (type) == METHOD_TYPE
-        || TREE_CODE (type) == OFFSET_TYPE)
+        || TYPE_PTRMEM_P (type))
     type = TREE_TYPE (type);
   return type;
 }
@@ -169,56 +164,9 @@ type_unknown_p (tree exp)
 {
   return (TREE_CODE (exp) == OVERLOAD
           || TREE_CODE (exp) == TREE_LIST
-         || TREE_TYPE (exp) == unknown_type_node
-         /* Until we get the type of non type-dependent expressions
-            correct, we can have non-type dependent expressions with
-            no type.  */
-         || (TREE_TYPE (exp)
-             && TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE
-             && TREE_TYPE (TREE_TYPE (exp)) == unknown_type_node));
+         || TREE_TYPE (exp) == unknown_type_node);
 }
 
-/* Return a pointer or pointer to member type similar to T1, with a
-   cv-qualification signature that is the union of the cv-qualification
-   signatures of T1 and T2: [expr.rel], [expr.eq].  */
-
-static tree
-qualify_type_recursive (tree t1, tree t2)
-{
-  if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2))
-      || (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2)))
-    {
-      tree tt1;
-      tree tt2;
-      tree b1;
-      int type_quals;
-      tree tgt;
-      tree attributes = (*targetm.merge_type_attributes) (t1, t2);
-
-      if (TYPE_PTRMEM_P (t1))
-       {
-         b1 = TYPE_PTRMEM_CLASS_TYPE (t1);
-         tt1 = TYPE_PTRMEM_POINTED_TO_TYPE (t1);
-         tt2 = TYPE_PTRMEM_POINTED_TO_TYPE (t2);
-       }
-      else
-       {
-         b1 = NULL_TREE;
-         tt1 = TREE_TYPE (t1);
-         tt2 = TREE_TYPE (t2);
-       }
-
-      type_quals = (cp_type_quals (tt1) | cp_type_quals (tt2));
-      tgt = qualify_type_recursive (tt1, tt2);
-      tgt = cp_build_qualified_type (tgt, type_quals);
-      if (b1)
-       t1 = build_ptrmem_type (b1, tgt);
-      else
-       t1 = build_pointer_type (tgt);
-      t1 = build_type_attribute_variant (t1, attributes);
-    }
-  return t1;
-}
 \f
 /* Return the common type of two parameter lists.
    We assume that comptypes has already been done and returned 1;
@@ -447,16 +395,85 @@ type_after_usual_arithmetic_conversions (tree t1, tree t2)
     }
 }
 
+/* Subroutine of composite_pointer_type to implement the recursive
+   case.  See that function for documentation fo the parameters.  */
+
+static tree
+composite_pointer_type_r (tree t1, tree t2, const char* location)
+{
+  tree pointee1;
+  tree pointee2;
+  tree result_type;
+  tree attributes;
+
+  /* Determine the types pointed to by T1 and T2.  */
+  if (TREE_CODE (t1) == POINTER_TYPE)
+    {
+      pointee1 = TREE_TYPE (t1);
+      pointee2 = TREE_TYPE (t2);
+    }
+  else
+    {
+      pointee1 = TYPE_PTRMEM_POINTED_TO_TYPE (t1);
+      pointee2 = TYPE_PTRMEM_POINTED_TO_TYPE (t2);
+    }
+
+  /* [expr.rel]
+
+     Otherwise, the composite pointer type is a pointer type
+     similar (_conv.qual_) to the type of one of the operands,
+     with a cv-qualification signature (_conv.qual_) that is the
+     union of the cv-qualification signatures of the operand
+     types.  */
+  if (same_type_ignoring_top_level_qualifiers_p (pointee1, pointee2))
+    result_type = pointee1;
+  else if ((TREE_CODE (pointee1) == POINTER_TYPE
+           && TREE_CODE (pointee2) == POINTER_TYPE)
+          || (TYPE_PTR_TO_MEMBER_P (pointee1)
+              && TYPE_PTR_TO_MEMBER_P (pointee2)))
+    result_type = composite_pointer_type_r (pointee1, pointee2, location);
+  else
+    {
+      pedwarn ("%s between distinct pointer types `%T' and `%T' "
+              "lacks a cast",
+              location, t1, t2);
+      result_type = void_type_node;
+    }
+  result_type = cp_build_qualified_type (result_type,
+                                        (cp_type_quals (pointee1)
+                                         | cp_type_quals (pointee2)));
+  result_type = build_pointer_type (result_type);
+  /* If the original types were pointers to members, so is the
+     result.  */
+  if (TYPE_PTR_TO_MEMBER_P (t1))
+    {
+      if (!same_type_p (TYPE_PTRMEM_CLASS_TYPE (t1),
+                       TYPE_PTRMEM_CLASS_TYPE (t2)))
+       pedwarn ("%s between distinct pointer types `%T' and `%T' "
+                "lacks a cast",
+                location, t1, t2);
+      result_type = build_ptrmem_type (TYPE_PTRMEM_CLASS_TYPE (t1),
+                                      result_type);
+    }
+
+  /* Merge the attributes.  */
+  attributes = (*targetm.merge_type_attributes) (t1, t2);
+  return build_type_attribute_variant (result_type, attributes);
+}
+
 /* Return the composite pointer type (see [expr.rel]) for T1 and T2.
    ARG1 and ARG2 are the values with those types.  The LOCATION is a
-   string describing the current location, in case an error occurs.  */
+   string describing the current location, in case an error occurs. 
+
+   This routine also implements the computation of a common type for
+   pointers-to-members as per [expr.eq].  */
 
 tree 
 composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
                        const char* location)
 {
-  tree result_type;
-  tree attributes;
+  tree class1;
+  tree class2;
 
   /* [expr.rel]
 
@@ -467,16 +484,6 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
   if (null_ptr_cst_p (arg2))
     return t1;
  
-  /* Deal with pointer-to-member functions in the same way as we deal
-     with pointers to functions.  */
-  if (TYPE_PTRMEMFUNC_P (t1))
-    t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
-  if (TYPE_PTRMEMFUNC_P (t2))
-    t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
-  
-  /* Merge the attributes.  */
-  attributes = (*targetm.merge_type_attributes) (t1, t2);
-
   /* We have:
 
        [expr.rel]
@@ -487,45 +494,78 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
        and cv2.
 
     If either type is a pointer to void, make sure it is T1.  */
-  if (VOID_TYPE_P (TREE_TYPE (t2)))
+  if (TREE_CODE (t2) == POINTER_TYPE && VOID_TYPE_P (TREE_TYPE (t2)))
     {
       tree t;
       t = t1;
       t1 = t2;
       t2 = t;
     }
+
   /* Now, if T1 is a pointer to void, merge the qualifiers.  */
-  if (VOID_TYPE_P (TREE_TYPE (t1)))
+  if (TREE_CODE (t1) == POINTER_TYPE && VOID_TYPE_P (TREE_TYPE (t1)))
     {
+      tree attributes;
+      tree result_type;
+
       if (pedantic && TYPE_PTRFN_P (t2))
        pedwarn ("ISO C++ forbids %s between pointer of type `void *' and pointer-to-function", location);
-      t1 = TREE_TYPE (t1);
-      t2 = TREE_TYPE (t2);
-      result_type = cp_build_qualified_type (void_type_node,
-                                            (cp_type_quals (t1)
-                                             | cp_type_quals (t2)));
+      result_type 
+       = cp_build_qualified_type (void_type_node,
+                                  (cp_type_quals (TREE_TYPE (t1))
+                                   | cp_type_quals (TREE_TYPE (t2))));
       result_type = build_pointer_type (result_type);
+      /* Merge the attributes.  */
+      attributes = (*targetm.merge_type_attributes) (t1, t2);
+      return build_type_attribute_variant (result_type, attributes);
+    }
+
+  /* [expr.eq] permits the application of a pointer conversion to
+     bring the pointers to a common type.  */
+  if (TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE
+      && CLASS_TYPE_P (TREE_TYPE (t1))
+      && CLASS_TYPE_P (TREE_TYPE (t2))
+      && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (t1),
+                                                    TREE_TYPE (t2)))
+    {
+      class1 = TREE_TYPE (t1);
+      class2 = TREE_TYPE (t2);
+
+      if (DERIVED_FROM_P (class1, class2))
+       t2 = (build_pointer_type 
+             (cp_build_qualified_type (class1, TYPE_QUALS (class2))));
+      else if (DERIVED_FROM_P (class2, class1))
+       t1 = (build_pointer_type 
+             (cp_build_qualified_type (class2, TYPE_QUALS (class1))));
+      else
+       {
+         error ("%s between distinct pointer types `%T' and `%T' "
+                "lacks a cast", location, t1, t2);
+         return error_mark_node;
+       }
     }
-  else
+  /* [expr.eq] permits the application of a pointer-to-member
+     conversion to change the class type of one of the types.  */
+  else if (TYPE_PTR_TO_MEMBER_P (t1)
+          && !same_type_p (TYPE_PTRMEM_CLASS_TYPE (t1),
+                           TYPE_PTRMEM_CLASS_TYPE (t2)))
     {
-      tree full1 = qualify_type_recursive (t1, t2);
-      tree full2 = qualify_type_recursive (t2, t1);
+      class1 = TYPE_PTRMEM_CLASS_TYPE (t1);
+      class2 = TYPE_PTRMEM_CLASS_TYPE (t2);
 
-      int val = comp_target_types (full1, full2, 1);
-
-      if (val > 0)
-       result_type = full1;
-      else if (val < 0)
-       result_type = full2;
+      if (DERIVED_FROM_P (class1, class2))
+       t1 = build_ptrmem_type (class2, TYPE_PTRMEM_POINTED_TO_TYPE (t1));
+      else if (DERIVED_FROM_P (class2, class1))
+       t2 = build_ptrmem_type (class1, TYPE_PTRMEM_POINTED_TO_TYPE (t2));
       else
        {
-         pedwarn ("%s between distinct pointer types `%T' and `%T' lacks a cast",
-                     location, t1, t2);
-         result_type = ptr_type_node;
+         error ("%s between distinct pointer-to-member types `%T' and `%T' "
+                "lacks a cast", location, t1, t2);
+         return error_mark_node;
        }
     }
 
-  return build_type_attribute_variant (result_type, attributes);
+  return composite_pointer_type_r (t1, t2, location);
 }
 
 /* Return the merged type of two types.
@@ -557,8 +597,6 @@ merge_types (tree t1, tree t2)
   /* Merge the attributes.  */
   attributes = (*targetm.merge_type_attributes) (t1, t2);
 
-  /* Treat an enum type as the unsigned integer type of the same width.  */
-
   if (TYPE_PTRMEMFUNC_P (t1))
     t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
   if (TYPE_PTRMEMFUNC_P (t2))
@@ -706,7 +744,6 @@ common_type (tree t1, tree t2)
           || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2)))
     return composite_pointer_type (t1, t2, error_mark_node, error_mark_node,
                                   "conversion");
-
   else
     abort ();
 }
@@ -995,206 +1032,6 @@ comptypes (tree t1, tree t2, int strict)
   return false;
 }
 
-/* Subroutine of comp_target-types.  Make sure that the cv-quals change
-   only in the same direction as the target type.  */
-
-static int
-comp_cv_target_types (tree ttl, tree ttr, int nptrs)
-{
-  int t;
-
-  if (!at_least_as_qualified_p (ttl, ttr)
-      && !at_least_as_qualified_p (ttr, ttl))
-    /* The qualifications are incomparable.  */
-    return 0;
-
-  if (TYPE_MAIN_VARIANT (ttl) == TYPE_MAIN_VARIANT (ttr))
-    return more_qualified_p (ttr, ttl) ? -1 : 1;
-
-  t = comp_target_types (ttl, ttr, nptrs);
-  if ((t == 1 && at_least_as_qualified_p (ttl, ttr)) 
-      || (t == -1 && at_least_as_qualified_p (ttr, ttl)))
-    return t;
-
-  return 0;
-}
-
-/* Return 1 or -1 if TTL and TTR are pointers to types that are equivalent,
-   ignoring their qualifiers, 0 if not. Return 1 means that TTR can be
-   converted to TTL. Return -1 means that TTL can be converted to TTR but
-   not vice versa.
-
-   NPTRS is the number of pointers we can strip off and keep cool.
-   This is used to permit (for aggr A, aggr B) A, B* to convert to A*,
-   but to not permit B** to convert to A**.
-
-   This should go away.  Callers should use can_convert or something
-   similar instead.  (jason 17 Apr 1997)  */
-
-int
-comp_target_types (tree ttl, tree ttr, int nptrs)
-{
-  ttl = TYPE_MAIN_VARIANT (ttl);
-  ttr = TYPE_MAIN_VARIANT (ttr);
-  if (same_type_p (ttl, ttr))
-    return 1;
-
-  if (TREE_CODE (ttr) != TREE_CODE (ttl))
-    return 0;
-
-  if ((TREE_CODE (ttr) == POINTER_TYPE
-       || TREE_CODE (ttr) == REFERENCE_TYPE)
-      /* If we get a pointer with nptrs == 0, we don't allow any tweaking
-        of the type pointed to.  This is necessary for reference init
-        semantics.  We won't get here from a previous call with nptrs == 1;
-        for multi-level pointers we end up in comp_ptr_ttypes.  */
-      && nptrs > 0)
-    {
-      int is_ptr = TREE_CODE (ttr) == POINTER_TYPE;
-
-      ttl = TREE_TYPE (ttl);
-      ttr = TREE_TYPE (ttr);
-
-      if (is_ptr)
-       {
-         if (TREE_CODE (ttl) == UNKNOWN_TYPE
-             || TREE_CODE (ttr) == UNKNOWN_TYPE)
-           return 1;
-         else if (TREE_CODE (ttl) == VOID_TYPE
-                  && TREE_CODE (ttr) != FUNCTION_TYPE
-                  && TREE_CODE (ttr) != METHOD_TYPE
-                  && TREE_CODE (ttr) != OFFSET_TYPE)
-           return 1;
-         else if (TREE_CODE (ttr) == VOID_TYPE
-                  && TREE_CODE (ttl) != FUNCTION_TYPE
-                  && TREE_CODE (ttl) != METHOD_TYPE
-                  && TREE_CODE (ttl) != OFFSET_TYPE)
-           return -1;
-         else if (TREE_CODE (ttl) == POINTER_TYPE
-                  || TREE_CODE (ttl) == ARRAY_TYPE)
-           {
-             if (comp_ptr_ttypes (ttl, ttr))
-               return 1;
-             else if (comp_ptr_ttypes (ttr, ttl))
-               return -1;
-             return 0;
-           }
-       }
-
-      /* Const and volatile mean something different for function types,
-        so the usual checks are not appropriate.  */
-      if (TREE_CODE (ttl) == FUNCTION_TYPE || TREE_CODE (ttl) == METHOD_TYPE)
-       return comp_target_types (ttl, ttr, nptrs - 1);
-
-      return comp_cv_target_types (ttl, ttr, nptrs - 1);
-    }
-
-  my_friendly_assert (TREE_CODE (ttr) != ARRAY_TYPE, 20030617);
-  if (TREE_CODE (ttr) == FUNCTION_TYPE || TREE_CODE (ttr) == METHOD_TYPE)
-    {
-      tree argsl, argsr;
-      int saw_contra = 0;
-
-      if (pedantic)
-       {
-         if (!same_type_p (TREE_TYPE (ttl), TREE_TYPE (ttr)))
-           return 0;
-       }
-      else
-       {
-         switch (comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), -1))
-           {
-           case 0:
-             return 0;
-           case -1:
-             saw_contra = 1;
-           }
-       }
-
-      argsl = TYPE_ARG_TYPES (ttl);
-      argsr = TYPE_ARG_TYPES (ttr);
-
-      /* Compare 'this' here, not in comp_target_parms.  */
-      if (TREE_CODE (ttr) == METHOD_TYPE)
-       {
-         tree tl = TYPE_METHOD_BASETYPE (ttl);
-         tree tr = TYPE_METHOD_BASETYPE (ttr);
-
-         if (!same_or_base_type_p (tr, tl))
-           {
-             if (same_or_base_type_p (tl, tr))
-               saw_contra = 1;
-             else
-               return 0;
-           }
-
-         argsl = TREE_CHAIN (argsl);
-         argsr = TREE_CHAIN (argsr);
-       }
-
-       switch (comp_target_parms (argsl, argsr))
-         {
-         case 0:
-           return 0;
-         case -1:
-           saw_contra = 1;
-         }
-
-       return saw_contra ? -1 : 1;
-    }
-  /* for C++ */
-  else if (TREE_CODE (ttr) == OFFSET_TYPE)
-    {
-      int base;
-
-      /* Contravariance: we can assign a pointer to base member to a pointer
-        to derived member.  Note difference from simple pointer case, where
-        we can pass a pointer to derived to a pointer to base.  */
-      if (same_or_base_type_p (TYPE_OFFSET_BASETYPE (ttr),
-                              TYPE_OFFSET_BASETYPE (ttl)))
-       base = 1;
-      else if (same_or_base_type_p (TYPE_OFFSET_BASETYPE (ttl),
-                                   TYPE_OFFSET_BASETYPE (ttr)))
-       {
-         tree tmp = ttl;
-         ttl = ttr;
-         ttr = tmp;
-         base = -1;
-       }
-      else
-       return 0;
-
-      ttl = TREE_TYPE (ttl);
-      ttr = TREE_TYPE (ttr);
-
-      if (TREE_CODE (ttl) == POINTER_TYPE
-         || TREE_CODE (ttl) == ARRAY_TYPE)
-       {
-         if (comp_ptr_ttypes (ttl, ttr))
-           return base;
-         return 0;
-       }
-      else
-       {
-         if (comp_cv_target_types (ttl, ttr, nptrs) == 1)
-           return base;
-         return 0;
-       }
-    }
-  else if (IS_AGGR_TYPE (ttl))
-    {
-      if (nptrs < 0)
-       return 0;
-      if (same_or_base_type_p (ttl, ttr))
-       return 1;
-      if (same_or_base_type_p (ttr, ttl))
-       return -1;
-      return 0;
-    }
-
-  return 0;
-}
-
 /* Returns 1 if TYPE1 is at least as qualified as TYPE2.  */
 
 bool
@@ -1333,80 +1170,6 @@ compparms (tree parms1, tree parms2)
   return true;
 }
 
-/* This really wants return whether or not parameter type lists
-   would make their owning functions assignment compatible or not.
-
-   The return value is like for comp_target_types.
-
-   This should go away, possibly with the exception of the empty parmlist
-   conversion; there are no conversions between function types in C++.
-   (jason 17 Apr 1997)  */
-
-static int
-comp_target_parms (tree parms1, tree parms2)
-{
-  register tree t1 = parms1, t2 = parms2;
-  int warn_contravariance = 0;
-
-  /* In C, an unspecified parmlist matches any specified parmlist
-     whose argument types don't need default promotions.  This is not
-     true for C++, but let's do it anyway for unfixed headers.  */
-
-  if (t1 == 0 && t2 != 0)
-    {
-      pedwarn ("ISO C++ prohibits conversion from `%#T' to `(...)'",
-                 parms2);
-      return self_promoting_args_p (t2);
-    }
-  if (t2 == 0)
-    return self_promoting_args_p (t1);
-
-  for (; t1 || t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
-    {
-      tree p1, p2;
-
-      /* If one parmlist is shorter than the other, they fail to match.  */
-      if (!t1 || !t2)
-       return 0;
-      p1 = TREE_VALUE (t1);
-      p2 = TREE_VALUE (t2);
-      if (same_type_p (p1, p2))
-       continue;
-
-      if (pedantic)
-       return 0;
-
-      if ((TREE_CODE (p1) == POINTER_TYPE && TREE_CODE (p2) == POINTER_TYPE)
-         || (TREE_CODE (p1) == REFERENCE_TYPE
-             && TREE_CODE (p2) == REFERENCE_TYPE))
-       {
-         /* The following is wrong for contravariance,
-            but many programs depend on it.  */
-         if (TREE_TYPE (p1) == void_type_node)
-           continue;
-         if (TREE_TYPE (p2) == void_type_node)
-           {
-             warn_contravariance = 1;
-             continue;
-           }
-         if (IS_AGGR_TYPE (TREE_TYPE (p1))
-             && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (p1),
-                                                            TREE_TYPE (p2)))
-           return 0;
-       }
-      /* Note backwards order due to contravariance.  */
-      if (comp_target_types (p2, p1, 1) <= 0)
-       {
-         if (comp_target_types (p1, p2, 1) > 0)
-           {
-             warn_contravariance = 1;
-             continue;
-           }
-         return 0;
-       }
-    }
-  return warn_contravariance ? -1 : 1;
-}
 \f
 tree
 cxx_sizeof_or_alignof_type (tree type, enum tree_code op, int complain)
@@ -1430,12 +1193,6 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, int complain)
        pedwarn ("invalid application of `%s' to a member function", op_name);
       value = size_one_node;
     }
-  else if (type_code == OFFSET_TYPE)
-    {
-      if (complain)
-       error ("invalid application of `%s' to non-static member", op_name);
-      value = size_zero_node;
-    }
   else
     value = c_sizeof_or_alignof_type (complete_type (type), op, complain);
 
@@ -2277,7 +2034,7 @@ build_indirect_ref (tree ptr, const char *errorstring)
     }
   /* `pointer' won't be an error_mark_node if we were given a
      pointer to member, so it's cool to check for this here.  */
-  else if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
+  else if (TYPE_PTR_TO_MEMBER_P (type))
     error ("invalid use of `%s' on pointer to member", errorstring);
   else if (pointer != error_mark_node)
     {
@@ -3010,7 +2767,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       /* Subtraction of two similar pointers.
         We must subtract them as integers, then divide by object size.  */
       if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
-         && comp_target_types (type0, type1, 1))
+         && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0),
+                                                       TREE_TYPE (type1)))
        return pointer_diff (op0, op1, common_type (type0, type1));
       /* Handle pointer minus int.  Just like pointer plus int.  */
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
@@ -3172,12 +2930,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
              || code1 == COMPLEX_TYPE))
        short_compare = 1;
-      else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
+      else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE)
+              || (TYPE_PTRMEM_P (type0) && TYPE_PTRMEM_P (type1)))
        result_type = composite_pointer_type (type0, type1, op0, op1,
                                              "comparison");
-      else if (code0 == POINTER_TYPE && null_ptr_cst_p (op1))
+      else if ((code0 == POINTER_TYPE || TYPE_PTRMEM_P (type0))
+              && null_ptr_cst_p (op1))
        result_type = type0;
-      else if (code1 == POINTER_TYPE && null_ptr_cst_p (op0))
+      else if ((code1 == POINTER_TYPE || TYPE_PTRMEM_P (type1))
+              && null_ptr_cst_p (op0))
        result_type = type1;
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
@@ -3656,8 +3417,6 @@ pointer_diff (register tree op0, register tree op1, register tree ptrtype)
        pedwarn ("ISO C++ forbids using pointer to a function in subtraction");
       if (TREE_CODE (target_type) == METHOD_TYPE)
        pedwarn ("ISO C++ forbids using pointer to a method in subtraction");
-      if (TREE_CODE (target_type) == OFFSET_TYPE)
-       pedwarn ("ISO C++ forbids using pointer to a member in subtraction");
     }
 
   /* First do the subtraction as integers;
@@ -3671,12 +3430,9 @@ pointer_diff (register tree op0, register tree op1, register tree ptrtype)
   if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (op1))))
     error ("invalid use of a pointer to an incomplete type in pointer arithmetic");
 
-  op1 = ((TREE_CODE (target_type) == VOID_TYPE
-         || TREE_CODE (target_type) == FUNCTION_TYPE
-         || TREE_CODE (target_type) == METHOD_TYPE
-         || TREE_CODE (target_type) == OFFSET_TYPE)
-        ? integer_one_node
-        : size_in_bytes (target_type));
+  op1 = (TYPE_PTROB_P (ptrtype) 
+        ? size_in_bytes (target_type)
+        : integer_one_node);
 
   /* Do the division.  */
 
@@ -3999,7 +3755,6 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
 
        if (TREE_CODE (argtype) == POINTER_TYPE)
          {
-           enum tree_code tmp = TREE_CODE (TREE_TYPE (argtype));
            tree type = complete_type (TREE_TYPE (argtype));
            
            if (!COMPLETE_OR_VOID_TYPE_P (type))
@@ -4008,8 +3763,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
                          || code == POSTINCREMENT_EXPR)
                         ? "increment" : "decrement"), TREE_TYPE (argtype));
            else if ((pedantic || warn_pointer_arith)
-                    && (tmp == FUNCTION_TYPE || tmp == METHOD_TYPE
-                        || tmp == VOID_TYPE || tmp == OFFSET_TYPE))
+                    && !TYPE_PTROB_P (argtype))
              pedwarn ("ISO C++ forbids %sing a pointer of type `%T'",
                          ((code == PREINCREMENT_EXPR
                            || code == POSTINCREMENT_EXPR)
@@ -4072,13 +3826,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
                error ("invalid use of `--' on bool variable `%D'", arg);
                return error_mark_node;
              }
-#if 0
-           /* This will only work if someone can convince Kenner to accept
-              my patch to expand_increment. (jason)  */
-           val = build (code, TREE_TYPE (arg), arg, inc);
-#else
            val = boolean_increment (code, arg);
-#endif
          }
        else
          val = build (code, TREE_TYPE (arg), arg, inc);
@@ -4092,6 +3840,10 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
         regardless of NOCONVERT.  */
 
       argtype = lvalue_type (arg);
+
+      if (TREE_CODE (arg) == OFFSET_REF)
+       goto offset_ref;
+
       if (TREE_CODE (argtype) == REFERENCE_TYPE)
        {
          arg = build1
@@ -4183,9 +3935,10 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
                         "  Say `&%T::%D'",
                         base, name);
            }
-         arg = build_offset_ref (base, name);
+         arg = build_offset_ref (base, name, /*address_p=*/true);
         }
-        
+
+    offset_ref:        
       if (type_unknown_p (arg))
        return build1 (ADDR_EXPR, unknown_type_node, arg);
        
@@ -4338,11 +4091,8 @@ unary_complex_lvalue (enum tree_code code, tree arg)
 
   if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
       || TREE_CODE (TREE_TYPE (arg)) == METHOD_TYPE
-      || TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
+      || TREE_CODE (arg) == OFFSET_REF)
     {
-      /* The representation of something of type OFFSET_TYPE
-        is really the representation of a pointer to it.
-        Here give the representation its true type.  */
       tree t;
 
       my_friendly_assert (TREE_CODE (arg) != SCOPE_REF, 313);
@@ -4599,14 +4349,16 @@ build_compound_expr (tree list)
 }
 
 /* Issue an error message if casting from SRC_TYPE to DEST_TYPE casts
-   away constness.  */
+   away constness.  DESCRIPTION explains what operation is taking
+   place.  */
 
 static void
-check_for_casting_away_constness (tree src_type, tree dest_type)
+check_for_casting_away_constness (tree src_type, tree dest_type,
+                                 const char *description)
 {
   if (casts_away_constness (src_type, dest_type))
-    error ("static_cast from type `%T' to type `%T' casts away constness",
-          src_type, dest_type);
+    error ("%s from type `%T' to type `%T' casts away constness",
+          description, src_type, dest_type);
 }
 
 /* Return an expression representing static_cast<TYPE>(EXPR).  */
@@ -4726,7 +4478,7 @@ build_static_cast (tree type, tree expr)
     {
       tree base;
 
-      check_for_casting_away_constness (intype, type);
+      check_for_casting_away_constness (intype, type, "static_cast");
       base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), 
                          ba_check | ba_quiet, NULL);
       return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
@@ -4758,15 +4510,18 @@ build_static_cast (tree type, tree expr)
        }
       if (can_convert (t1, t2))
        {
-         check_for_casting_away_constness (intype, type);
+         check_for_casting_away_constness (intype, type, "static_cast");
          if (TYPE_PTRMEM_P (type))
            {
+             tree delta;
+
              if (TREE_CODE (expr) == PTRMEM_CST)
                expr = cplus_expand_constant (expr);
-             expr = cp_build_binary_op (PLUS_EXPR, 
-                                        cp_convert (ptrdiff_type_node, expr),
-                                        get_delta_difference (c1, c2, 
-                                                              /*force=*/1));
+             delta = get_delta_difference (c1, c2, /*force=*/1);
+             if (!integer_zerop (delta))
+               expr = cp_build_binary_op (PLUS_EXPR, 
+                                          build_nop (ptrdiff_type_node, expr),
+                                          delta);
              return build_nop (type, expr);
            }
          else
@@ -4785,7 +4540,7 @@ build_static_cast (tree type, tree expr)
       && VOID_TYPE_P (TREE_TYPE (intype))
       && TYPE_PTROB_P (type))
     {
-      check_for_casting_away_constness (intype, type);
+      check_for_casting_away_constness (intype, type, "static_cast");
       return build_nop (type, expr);
     }
 
@@ -4856,10 +4611,7 @@ build_reinterpret_cast (tree type, tree expr)
   else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
           || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
     {
-      if (! comp_ptr_ttypes_reinterpret (TREE_TYPE (type), TREE_TYPE (intype)))
-       pedwarn ("reinterpret_cast from `%T' to `%T' casts away const (or volatile)",
-                   intype, type);
-
+      check_for_casting_away_constness (intype, type, "reinterpret_cast");
       expr = decl_constant_value (expr);
       return fold (build1 (NOP_EXPR, type, expr));
     }
@@ -4932,8 +4684,9 @@ build_const_cast (tree type, tree expr)
          return convert_from_reference (expr);
        }
     }
-  else if (TREE_CODE (type) == POINTER_TYPE
-          && TREE_CODE (intype) == POINTER_TYPE
+  else if (((TREE_CODE (type) == POINTER_TYPE
+            && TREE_CODE (intype) == POINTER_TYPE)
+           || (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)))
           && comp_ptr_ttypes_const (TREE_TYPE (type), TREE_TYPE (intype)))
     return cp_convert (type, expr);
 
@@ -5048,11 +4801,11 @@ build_c_cast (tree type, tree expr)
                 otype, type);
 
   if (TREE_CODE (type) == INTEGER_TYPE
-      && TREE_CODE (otype) == POINTER_TYPE
+      && TYPE_PTR_P (otype)
       && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
     warning ("cast from pointer to integer of different size");
 
-  if (TREE_CODE (type) == POINTER_TYPE
+  if (TYPE_PTR_P (type)
       && TREE_CODE (otype) == INTEGER_TYPE
       && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
       /* Don't warn about converting any constant.  */
@@ -5785,13 +5538,9 @@ static tree
 convert_for_assignment (tree type, tree rhs,
                        const char *errtype, tree fndecl, int parmnum)
 {
-  register enum tree_code codel = TREE_CODE (type);
   register tree rhstype;
   register enum tree_code coder;
 
-  if (codel == OFFSET_TYPE)
-    abort ();
-
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
     rhs = TREE_OPERAND (rhs, 0);
@@ -6266,7 +6015,7 @@ check_return_expr (tree retval)
 static int
 comp_ptr_ttypes_real (tree to, tree from, int constp)
 {
-  int to_more_cv_qualified = 0;
+  bool to_more_cv_qualified = false;
 
   for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
     {
@@ -6289,8 +6038,7 @@ comp_ptr_ttypes_real (tree to, tree from, int constp)
            {
              if (constp == 0)
                return 0;
-             else
-               ++to_more_cv_qualified;
+             to_more_cv_qualified = true;
            }
 
          if (constp > 0)
@@ -6369,40 +6117,6 @@ comp_ptr_ttypes_const (tree to, tree from)
     }
 }
 
-/* Like comp_ptr_ttypes, for reinterpret_cast.  */
-
-static int
-comp_ptr_ttypes_reinterpret (tree to, tree from)
-{
-  int constp = 1;
-
-  for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
-    {
-      if (TREE_CODE (from) == OFFSET_TYPE)
-       from = TREE_TYPE (from);
-      if (TREE_CODE (to) == OFFSET_TYPE)
-       to = TREE_TYPE (to);
-
-      /* Const and volatile mean something different for function types,
-        so the usual checks are not appropriate.  */
-      if (TREE_CODE (from) != FUNCTION_TYPE && TREE_CODE (from) != METHOD_TYPE
-         && TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
-       {
-         if (!at_least_as_qualified_p (to, from))
-           return 0;
-
-         if (! constp
-             && !at_least_as_qualified_p (from, to))
-           return 0;
-         constp &= TYPE_READONLY (to);
-       }
-
-      if (TREE_CODE (from) != POINTER_TYPE
-         || TREE_CODE (to) != POINTER_TYPE)
-       return 1;
-    }
-}
-
 /* Returns the type qualifiers for this type, including the qualifiers on the
    elements for an array type.  */
 
@@ -6442,9 +6156,9 @@ casts_away_constness_r (tree *t1, tree *t2)
      pointer to member level is ignored when determining if a const
      cv-qualifier has been cast away.  */
   if (TYPE_PTRMEM_P (*t1))
-    *t1 = build_pointer_type (TREE_TYPE (TREE_TYPE (*t1)));
+    *t1 = build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (*t1));
   if (TYPE_PTRMEM_P (*t2))
-    *t2 = build_pointer_type (TREE_TYPE (TREE_TYPE (*t2)));
+    *t2 = build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (*t2));
 
   /* [expr.const.cast]
 
@@ -6513,8 +6227,8 @@ casts_away_constness (tree t1, tree t2)
        "pointer to T1" to the type "pointer to T2" casts away
        constness.  */
     return casts_away_constness
-      (build_pointer_type (TREE_TYPE (TREE_TYPE (t1))),
-       build_pointer_type (TREE_TYPE (TREE_TYPE (t2))));
+      (build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (t1)),
+       build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (t2)));
 
   /* Casting away constness is only something that makes sense for
      pointer or reference types.  */
@@ -6532,23 +6246,6 @@ casts_away_constness (tree t1, tree t2)
   return false;
 }
 
-/* Returns TYPE with its cv qualifiers removed
-   TYPE is T cv* .. *cv where T is not a pointer type,
-   returns T * .. *. (If T is an array type, then the cv qualifiers
-   above are those of the array members.)  */
-
-static tree
-strip_all_pointer_quals (tree type)
-{
-  if (TREE_CODE (type) == POINTER_TYPE)
-    return build_pointer_type (strip_all_pointer_quals (TREE_TYPE (type)));
-  else if (TREE_CODE (type) == OFFSET_TYPE)
-    return build_offset_type (TYPE_OFFSET_BASETYPE (type),
-                             strip_all_pointer_quals (TREE_TYPE (type)));
-  else
-    return TYPE_MAIN_VARIANT (type);
-}
-
 /* If T is a REFERENCE_TYPE return the type to which T refers.
    Otherwise, return T itself.  */
 
index 6a14fecb4a99f51c7ba8661cb75c2c4184f88092..8d1209c998c8cdcec01e6fb81e051ebeb05231bd 100644 (file)
@@ -506,7 +506,7 @@ digest_init (tree type, tree init, tree* tail)
   if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
       || code == ENUMERAL_TYPE || code == REFERENCE_TYPE
       || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
-      || TYPE_PTRMEMFUNC_P (type))
+      || TYPE_PTR_TO_MEMBER_P (type))
     {
       if (raw_constructor)
        {
@@ -1070,8 +1070,7 @@ build_m_component_ref (tree datum, tree component)
     return error_mark_node;
 
   ptrmem_type = TREE_TYPE (component);
-  if (!TYPE_PTRMEM_P (ptrmem_type) 
-      && !TYPE_PTRMEMFUNC_P (ptrmem_type))
+  if (!TYPE_PTR_TO_MEMBER_P (ptrmem_type))
     {
       error ("`%E' cannot be used as a member pointer, since it is of type `%T'", 
             component, ptrmem_type);
@@ -1107,10 +1106,12 @@ build_m_component_ref (tree datum, tree component)
       type = cp_build_qualified_type (type,
                                      (cp_type_quals (type)  
                                       | cp_type_quals (TREE_TYPE (datum))));
-
-      datum = build_base_path (PLUS_EXPR, build_address (datum), binfo, 1);
-      component = cp_convert (ptrdiff_type_node, component);
-      datum = build (PLUS_EXPR, build_pointer_type (type), datum, component);
+      /* Build an expression for "object + offset" where offset is the
+        value stored in the pointer-to-data-member.  */
+      datum = build (PLUS_EXPR, build_pointer_type (type),
+                    build_base_path (PLUS_EXPR, build_address (datum), 
+                                     binfo, 1),
+                    build_nop (ptrdiff_type_node, component));
       return build_indirect_ref (datum, 0);
     }
   else
index fd9cb3d5cfb59a1a32cbad14c5a697fcf3fa8232..114aaae44c8a1992b2ef954e3e3c395c5724f918 100644 (file)
@@ -193,7 +193,8 @@ force_fit_type (tree t, int overflow)
   low = TREE_INT_CST_LOW (t);
   high = TREE_INT_CST_HIGH (t);
 
-  if (POINTER_TYPE_P (TREE_TYPE (t)))
+  if (POINTER_TYPE_P (TREE_TYPE (t))
+      || TREE_CODE (TREE_TYPE (t)) == OFFSET_TYPE)
     prec = POINTER_SIZE;
   else
     prec = TYPE_PRECISION (TREE_TYPE (t));
index 073fcdf375401415e958323bff88c2080c8d7996..847cf7719f9007ced7b92288854d1019fd194b7b 100644 (file)
@@ -3695,6 +3695,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
     case ENUMERAL_TYPE:
     case POINTER_TYPE:
     case REFERENCE_TYPE:
+    case OFFSET_TYPE:
       if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
                                           EXPAND_INITIALIZER),
                              size, align, 0))