cp-tree.h (PTRMEM_OK_P): New macro.
authorNathan Sidwell <nathan@codesourcery.com>
Fri, 18 Aug 2000 09:31:11 +0000 (09:31 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Fri, 18 Aug 2000 09:31:11 +0000 (09:31 +0000)
* cp-tree.h (PTRMEM_OK_P): New macro.
(itf_ptrmem_ok): New enumeration value.
* class.c (resolve_address_of_overloaded_function): Add PTRMEM
argument. Diagnose implicit pointer to member.
(instantiate_type): Don't diagnose implicit pointer to member
here. Pass itf_ptrmem_ok if ok. Adjust calls to
resolve_address_of_overloaded_function.
* init.c (build_offset_ref): Set PTRMEM_OK_P.
(resolve_offset_ref): Don't diagnose implicit pointer to member here.
* semantics.c (finish_parenthesized_expr): Clear OFFSET_REFs here.
* typeck.c (build_x_unary_op): Calculate PTRMEM_OK_P.
(build_unary_op): Deal with single non-static member in
microsoft-land.

From-SVN: r35777

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/semantics.c
gcc/cp/typeck.c

index 4e71a93ae724171c2defc976f2ab1d250436a088..35a206768876b581781679457d8ae9fc4b00b1bc 100644 (file)
@@ -1,3 +1,19 @@
+2000-08-18  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * cp-tree.h (PTRMEM_OK_P): New macro.
+       (itf_ptrmem_ok): New enumeration value.
+       * class.c (resolve_address_of_overloaded_function): Add PTRMEM
+       argument. Diagnose implicit pointer to member.
+       (instantiate_type): Don't diagnose implicit pointer to member
+       here. Pass itf_ptrmem_ok if ok. Adjust calls to
+       resolve_address_of_overloaded_function.
+       * init.c (build_offset_ref): Set PTRMEM_OK_P.
+       (resolve_offset_ref): Don't diagnose implicit pointer to member here.
+       * semantics.c (finish_parenthesized_expr): Clear OFFSET_REFs here.
+       * typeck.c (build_x_unary_op): Calculate PTRMEM_OK_P.
+       (build_unary_op): Deal with single non-static member in
+       microsoft-land.
+
 2000-08-18  Nathan Sidwell  <nathan@codesourcery.com>
 
        * decl2.c (arg_assoc_type): Cope with TYPENAME_TYPE.
index 08099c116b170628d698fbe8dc51941876112268..f749c74e6d836b9f0bacfd34a86b4ce41e0057bf 100644 (file)
@@ -132,7 +132,7 @@ static int method_name_cmp PARAMS ((const tree *, const tree *));
 static tree add_implicitly_declared_members PARAMS ((tree, int, int, int));
 static tree fixed_type_or_null PARAMS ((tree, int *));
 static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
-                                                         int, tree));
+                                                         int, int, tree));
 static void build_vtable_entry_ref PARAMS ((tree, tree, tree));
 static tree build_vtbl_initializer PARAMS ((tree, tree, tree, tree, int *));
 static int count_fields PARAMS ((tree));
@@ -5725,19 +5725,22 @@ pop_lang_context ()
 /* Given an OVERLOAD and a TARGET_TYPE, return the function that
    matches the TARGET_TYPE.  If there is no satisfactory match, return
    error_mark_node, and issue an error message if COMPLAIN is
-   non-zero.  If TEMPLATE_ONLY, the name of the overloaded function
+   non-zero.  Permit pointers to member function if PTRMEM is non-zero.
+   If TEMPLATE_ONLY, the name of the overloaded function
    was a template-id, and EXPLICIT_TARGS are the explicitly provided
    template arguments.  */
 
 static tree
 resolve_address_of_overloaded_function (target_type, 
                                        overload,
-                                       complain, 
+                                       complain,
+                                       ptrmem,
                                        template_only,
                                        explicit_targs)
      tree target_type;
      tree overload;
      int complain;
+     int ptrmem;
      int template_only;
      tree explicit_targs;
 {
@@ -5960,6 +5963,14 @@ resolve_address_of_overloaded_function (target_type,
   /* Good, exactly one match.  Now, convert it to the correct type.  */
   fn = TREE_PURPOSE (matches);
 
+  if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
+      && !ptrmem && !flag_ms_extensions)
+    {
+      if (!complain)
+        return error_mark_node;
+
+      cp_pedwarn ("assuming pointer to member `%D'", fn);
+    }
   mark_used (fn);
 
   if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
@@ -5993,7 +6004,9 @@ instantiate_type (lhstype, rhs, flags)
   int complain = (flags & itf_complain);
   int strict = (flags & itf_no_attributes)
                ? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
-  tree r;
+  int allow_ptrmem = flags & itf_ptrmem_ok;
+  
+  flags &= ~itf_ptrmem_ok;
   
   if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
     {
@@ -6053,36 +6066,13 @@ instantiate_type (lhstype, rhs, flags)
       return instantiate_type (lhstype, rhs, flags);
 
     case COMPONENT_REF:
-      {
-       r = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
-
-      comp:
-       if (r != error_mark_node && TYPE_PTRMEMFUNC_P (lhstype)
-           && complain && !flag_ms_extensions)
-         {
-           /* Note: we check this after the recursive call to avoid
-              complaining about cases where overload resolution fails.  */
-
-           tree t = TREE_TYPE (TREE_OPERAND (rhs, 0));
-           tree fn = PTRMEM_CST_MEMBER (r);
-
-           my_friendly_assert (TREE_CODE (r) == PTRMEM_CST, 990811);
-
-           cp_pedwarn
-             ("object-dependent reference to `%E' can only be used in a call",
-              DECL_NAME (fn));
-           cp_pedwarn
-             ("  to form a pointer to member function, say `&%T::%E'",
-              t, DECL_NAME (fn));
-         }
-
-       return r;
-      }
+      return instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
 
     case OFFSET_REF:
       rhs = TREE_OPERAND (rhs, 1);
       if (BASELINK_P (rhs))
-       return instantiate_type (lhstype, TREE_VALUE (rhs), flags);
+       return instantiate_type (lhstype, TREE_VALUE (rhs),
+                                flags | allow_ptrmem);
 
       /* This can happen if we are forming a pointer-to-member for a
         member template.  */
@@ -6095,18 +6085,13 @@ instantiate_type (lhstype, rhs, flags)
        tree fns = TREE_OPERAND (rhs, 0);
        tree args = TREE_OPERAND (rhs, 1);
 
-       r =
+       return
          resolve_address_of_overloaded_function (lhstype,
                                                  fns,
                                                  complain,
+                                                 allow_ptrmem,
                                                  /*template_only=*/1,
                                                  args);
-       if (TREE_CODE (fns) == COMPONENT_REF)
-         {
-           rhs = fns;
-           goto comp;
-         }
-       return r;
       }
 
     case OVERLOAD:
@@ -6114,6 +6099,7 @@ instantiate_type (lhstype, rhs, flags)
        resolve_address_of_overloaded_function (lhstype, 
                                                rhs,
                                                complain,
+                                               allow_ptrmem,
                                                /*template_only=*/0,
                                                /*explicit_targs=*/NULL_TREE);
 
@@ -6225,8 +6211,12 @@ instantiate_type (lhstype, rhs, flags)
       return rhs;
       
     case ADDR_EXPR:
+    {
+      if (PTRMEM_OK_P (rhs))
+        flags |= itf_ptrmem_ok;
+      
       return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
-
+    }
     case ENTRY_VALUE_EXPR:
       my_friendly_abort (184);
       return error_mark_node;
index 5dba2e394724a56b944b3b873355629ec06cfac9..af39281b1363ae311c52451b6c3012b75d343f23 100644 (file)
@@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA.  */
       AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
       CTOR_BEGIN_P (in CTOR_STMT)
       BV_USE_VCALL_INDEX_P (in the BINFO_VIRTUALS TREE_LIST)
+      PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
    1: IDENTIFIER_VIRTUAL_P.
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -2666,6 +2667,10 @@ extern int flag_new_for_scope;
 #define TYPE_PTRMEMFUNC_FLAG(NODE) \
   (TYPE_LANG_SPECIFIC(NODE)->ptrmemfunc_flag)
 
+/* 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)
+
 /* A pointer-to-function member type looks like:
 
    struct {
@@ -3208,7 +3213,8 @@ typedef enum special_function_kind {
 typedef enum instantiate_type_flags {
   itf_none = 0,               /* nothing special */
   itf_complain = 1 << 0,      /* complain about errors */
-  itf_no_attributes = 1 << 1  /* ignore attributes on comparisons */
+  itf_no_attributes = 1 << 1, /* ignore attributes on comparisons */
+  itf_ptrmem_ok = 1 << 2,     /* pointers to member ok (internal use) */
 } instantiate_type_flags;
 
 /* Non-zero means that if a label exists, and no other identifier
index c35babb1a3db00531eb662c73ec0cb8f7dcb2c2f..097deb7028b483b755c94f27aef7c663895b408c 100644 (file)
@@ -1710,13 +1710,13 @@ build_offset_ref (type, name)
               expects to encounter OVERLOADs, not raw functions.  */
            t = ovl_cons (t, NULL_TREE);
 
-         return build (OFFSET_REF, 
-                       unknown_type_node,
-                       decl,
-                       build (TEMPLATE_ID_EXPR, 
-                              TREE_TYPE (t),
-                              t,
-                              TREE_OPERAND (orig_name, 1)));
+          t = build (TEMPLATE_ID_EXPR, TREE_TYPE (t), t,
+                    TREE_OPERAND (orig_name, 1));
+         t = build (OFFSET_REF, unknown_type_node, decl, t);
+          
+          PTRMEM_OK_P (t) = 1;
+                 
+         return t;
        }
 
       if (!really_overloaded_fn (t))
@@ -1730,11 +1730,16 @@ build_offset_ref (type, name)
          mark_used (t);
          if (DECL_STATIC_FUNCTION_P (t))
            return t;
-         return build (OFFSET_REF, TREE_TYPE (t), decl, t);
+         t = build (OFFSET_REF, TREE_TYPE (t), decl, t);
+         PTRMEM_OK_P (t) = 1;
+         return t;
        }
 
       TREE_TYPE (fnfields) = unknown_type_node;
-      return build (OFFSET_REF, unknown_type_node, decl, fnfields);
+      
+      t = build (OFFSET_REF, unknown_type_node, decl, fnfields);
+      PTRMEM_OK_P (t) = 1;
+      return t;
     }
 
   t = member;
@@ -1772,7 +1777,9 @@ build_offset_ref (type, name)
   /* In member functions, the form `type::name' is no longer
      equivalent to `this->type::name', at least not until
      resolve_offset_ref.  */
-  return build (OFFSET_REF, build_offset_type (type, TREE_TYPE (t)), decl, t);
+  t = build (OFFSET_REF, build_offset_type (type, TREE_TYPE (t)), decl, t);
+  PTRMEM_OK_P (t) = 1;
+  return t;
 }
 
 /* If a OFFSET_REF made it through to here, then it did
@@ -1806,16 +1813,15 @@ resolve_offset_ref (exp)
     }
 
   if (BASELINK_P (member))
-    {
-      if (! flag_ms_extensions)
-       cp_pedwarn ("assuming & on overloaded member function");
-      return build_unary_op (ADDR_EXPR, exp, 0);
-    }
-
+    return build_unary_op (ADDR_EXPR, exp, 0);
+  
   if (TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
     {
-      if (! flag_ms_extensions)
-       cp_pedwarn ("assuming & on `%E'", member);
+      if (!flag_ms_extensions)
+        /* A single non-static member, make sure we don't allow a
+           pointer-to-member.  */
+        exp = ovl_cons (member, NULL_TREE);
+      
       return build_unary_op (ADDR_EXPR, exp, 0);
     }
 
index 9dc6bca5a81aba9dd1c801e30a8e1a9d631cf930..70ef712ca841d6be8654095cb6ae51d257a49a3c 100644 (file)
@@ -1331,6 +1331,10 @@ finish_parenthesized_expr (expr)
     /* This inhibits warnings in truthvalue_conversion.  */
     C_SET_EXP_ORIGINAL_CODE (expr, ERROR_MARK); 
 
+  if (TREE_CODE (expr) == OFFSET_REF)
+    /* [expr.unary.op]/3 The qualified id of a pointer-to-member must not be
+       enclosed in parentheses.  */
+    PTRMEM_OK_P (expr) = 0;
   return expr;
 }
 
index ddd827a96c7bb2a74c83418a969c757ec24d1a10..9ab9b87648536bbe75695d3a64e79673ee064c4f 100644 (file)
@@ -4260,6 +4260,9 @@ build_x_unary_op (code, xarg)
      enum tree_code code;
      tree xarg;
 {
+  tree exp;
+  int ptrmem = 0;
+  
   if (processing_template_decl)
     return build_min_nt (code, xarg, NULL_TREE);
 
@@ -4280,14 +4283,26 @@ build_x_unary_op (code, xarg)
       if (rval || code != ADDR_EXPR)
        return rval;
     }
-
   if (code == ADDR_EXPR)
     {
-      if (TREE_CODE (xarg) == TARGET_EXPR)
+      if (TREE_CODE (xarg) == OFFSET_REF)
+        {
+          ptrmem = PTRMEM_OK_P (xarg);
+          
+          if (!ptrmem && !flag_ms_extensions
+              && TREE_CODE (TREE_TYPE (TREE_OPERAND (xarg, 1))) == METHOD_TYPE)
+            /* A single non-static member, make sure we don't allow a
+               pointer-to-member.  */
+            xarg = ovl_cons (TREE_OPERAND (xarg, 1), NULL_TREE);
+        }
+      else if (TREE_CODE (xarg) == TARGET_EXPR)
        warning ("taking address of temporary");
     }
+  exp = build_unary_op (code, xarg, 0);
+  if (TREE_CODE (exp) == ADDR_EXPR)
+    PTRMEM_OK_P (exp) = ptrmem;
 
-  return build_unary_op (code, xarg, 0);
+  return exp;
 }
 
 /* Just like truthvalue_conversion, but we want a CLEANUP_POINT_EXPR.  */
@@ -4635,35 +4650,21 @@ build_unary_op (code, xarg, noconvert)
          return build1 (ADDR_EXPR, unknown_type_node, arg);
        }
 
-      if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
-         && OVL_NEXT (TREE_OPERAND (arg, 1)) == NULL_TREE)
-       {
+      if (TREE_CODE (arg) == COMPONENT_REF && flag_ms_extensions
+          && type_unknown_p (arg)
+          && OVL_NEXT (TREE_OPERAND (arg, 1)) == NULL_TREE)
+        {
          /* They're trying to take the address of a unique non-static
-            member function.  This is ill-formed, but let's try to DTRT.
-            Note: We only handle unique functions here because we don't
-            want to complain if there's a static overload; non-unique
-            cases will be handled by instantiate_type.  But we need to
-            handle this case here to allow casts on the resulting PMF.  */
+            member function.  This is ill-formed, except in microsoft-land.  */
 
          tree base = TREE_TYPE (TREE_OPERAND (arg, 0));
          tree name = DECL_NAME (OVL_CURRENT (TREE_OPERAND (arg, 1)));
-
-         if (! flag_ms_extensions)
-           {
-             if (current_class_type
-                 && TREE_OPERAND (arg, 0) == current_class_ref)
-               /* An expression like &memfn.  */
-               cp_pedwarn ("ISO C++ forbids taking the address of a non-static member function to form a pointer to member function.  Say `&%T::%D'", base, name);
-             else
-               cp_pedwarn ("ISO C++ forbids taking the address of a bound member function to form a pointer to member function", base, name);
-           }
-
          arg = build_offset_ref (base, name);
-       }
-
+        }
+        
       if (type_unknown_p (arg))
        return build1 (ADDR_EXPR, unknown_type_node, arg);
-
+       
       /* Handle complex lvalues (when permitted)
         by reduction to simpler cases.  */
       val = unary_complex_lvalue (code, arg);