89th Cygnus<->FSF quick merge
authorMike Stump <mrs@gcc.gnu.org>
Fri, 18 Oct 1996 18:33:44 +0000 (18:33 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Fri, 18 Oct 1996 18:33:44 +0000 (18:33 +0000)
From-SVN: r12978

gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/class.c
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/expr.c
gcc/cp/init.c
gcc/cp/pt.c
gcc/cp/typeck.c

index 136247a678b0993071f8180384a776b2a364593c..1c95b3b45c34393fb54942eb2b90a5f82a61e478 100644 (file)
@@ -1,3 +1,33 @@
+Thu Oct 17 11:31:59 1996  Mike Stump  <mrs@cygnus.com>
+
+       * cvt.c (convert_to_pointer_force): Add code to support pointer to
+       member function to pointer to function conversions.
+       * init.c (resolve_offset_ref): Add code to allow faked up objects,
+       ignoring them if they are not used, and giving an error, if they
+       are needed.
+       * typeck.c (get_member_function_from_ptrfunc): Fold e1 to improve
+       code, and so that we can give an error, if we needed an object,
+       and one was not provided.
+       (build_c_cast): Don't call default_conversion when we want to
+       convert to pointer to function from a METHOD_TYPE.
+
+Mon Oct 14 00:28:51 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * Make-lang.in (cplib2.ready): Fix logic.
+
+       * decl.c (shadow_tag): Only complain about non-artificial function
+       members.
+
+       * class.c (finish_struct_1): Add synthesized methods to TYPE_METHODS.
+
+Fri Oct 11 16:12:40 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * expr.c (cplus_expand_expr): Pre-tweak call_target like
+       expand_inline_function would.
+
+       * pt.c (mark_decl_instantiated): If extern_p, call
+       mark_inline_for_output.
+
 Thu Oct 10 15:58:08 1996  Mike Stump  <mrs@cygnus.com>
 
        * typeck.c (unary_complex_lvalue): Add code to handle intermediate
index f7265c961245fd041908e9fa4399125dcad998bf..b6b0105857c5e2ef5990822ad12b1a1b5d26845a 100644 (file)
@@ -146,7 +146,7 @@ cplib2.ready: $(GCC_PASSES) $(LIBGCC2_DEPS) stmp-int-hdrs
          else \
            echo "" > cplib2.new; \
          fi; \
-         if cmp -s cplib2.new cplib2.txt; then \
+         if cmp -s cplib2.new cplib2.txt; then true; else \
            touch cplib2.ready; \
          fi; \
          rm -f cplib2.new; \
index 304531586eb298b99dcc2a051e4cbbd331950b8a..60b2cffea7304961c2233870667f80770f8bcd14 100644 (file)
@@ -3635,6 +3635,7 @@ finish_struct_1 (t, warn_anon)
 
   if (fn_fields)
     {
+      TYPE_METHODS (t) = fn_fields;
       method_vec = finish_struct_methods (t, fn_fields, nonprivate_method);
 
       if (TYPE_HAS_CONSTRUCTOR (t)
index 84196a6b65fd2f38e66b0c853e82e6742968fd3e..cd40b9a0cec65782df7f775cdd22eaf1cc594d10 100644 (file)
@@ -282,6 +282,44 @@ convert_to_pointer_force (type, expr)
       form = TREE_CODE (intype);
     }
 
+  if (TREE_CODE (type) == POINTER_TYPE
+      && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+    {
+      /* Allow an implicit this pointer for pointer to member
+         functions.  */
+      if (TYPE_PTRMEMFUNC_P (intype))
+       {
+         tree decl, basebinfo;
+         tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype));
+         tree t = TYPE_METHOD_BASETYPE (fntype);
+
+         if (current_class_type == 0
+             || get_base_distance (t, current_class_type, 0, &basebinfo) == -1)
+           {
+             decl = build1 (NOP_EXPR, t, error_mark_node);
+           }
+         else if (current_class_ptr == 0)
+           decl = build1 (NOP_EXPR, t, error_mark_node);
+         else
+           decl = current_class_ref;
+
+         expr = build (OFFSET_REF, fntype, decl, expr);
+         intype = TREE_TYPE (expr);
+       }
+
+      if (TREE_CODE (expr) == OFFSET_REF && TREE_CODE (intype) == METHOD_TYPE)
+       expr = resolve_offset_ref (expr);
+      if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
+       expr = build_addr_func (expr);
+      if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
+       {
+         if (pedantic
+             && TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == METHOD_TYPE)
+           cp_pedwarn ("cannot convert `%T' to `%T'", intype, type);
+         return build1 (NOP_EXPR, type, expr);
+       }
+    }
+
   if (form == POINTER_TYPE)
     {
       intype = TYPE_MAIN_VARIANT (intype);
index 469b529ff58bb491910dd56a548e6a44d5e50407..7c8c28bda78e98dd59c199ced1d020072ae114a1 100644 (file)
@@ -5647,10 +5647,16 @@ shadow_tag (declspecs)
          || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
              && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))))
     {
+      tree fn;
+
       /* ANSI C++ June 5 1992 WP 9.5.3.  Anonymous unions may not have
         function members.  */
-      if (TYPE_METHODS (t))
-       error ("an anonymous union cannot have function members");
+      for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
+       if (! DECL_ARTIFICIAL (fn))
+         {
+           error ("an anonymous union cannot have function members");
+           break;
+         }
 
       if (TYPE_FIELDS (t))
        {
index 506d64c72842dcda953574f91a788acf8a3d3e1f..3351ccba7708b52eb5cb39aacfc0fdd36a5c341b 100644 (file)
@@ -137,6 +137,18 @@ cplus_expand_expr (exp, target, tmode, modifier)
               result.  The assumptions are true only if the address was
               valid to begin with.  */
            call_target = validize_mem (call_target);
+
+           /* If this is a reference to a symbol, expand_inline_function
+              will do this transformation and return a different target
+              than the one we gave it, though functionally equivalent.  Do
+              the transformation here to avoid confusion.  */
+           if (! cse_not_expected && GET_CODE (call_target) == MEM
+               && GET_CODE (XEXP (call_target, 0)) == SYMBOL_REF)
+             {
+               call_target = gen_rtx
+                 (MEM, mode, memory_address (mode, XEXP (call_target, 0)));
+               MEM_IN_STRUCT_P (call_target) = 1;
+             }
          }
 
        call_exp = build (CALL_EXPR, type, func, args, NULL_TREE);
index af629caf0510b46b588914372b290bd88782624a..84fd6a223658f285c20564f20eeced70d8ce9a42 100644 (file)
@@ -2082,14 +2082,27 @@ resolve_offset_ref (exp)
       my_friendly_abort (55);
     }
 
-  /* If this is a reference to a member function, then return
-     the address of the member function (which may involve going
-     through the object's vtable), otherwise, return an expression
-     for the dereferenced pointer-to-member construct.  */
-  addr = build_unary_op (ADDR_EXPR, base, 0);
+  /* Ensure that we have an object.  */
+  if (TREE_CODE (base) == NOP_EXPR
+      && TREE_OPERAND (base, 0) == error_mark_node)
+    addr = error_mark_node;
+  else
+    {
+      /* If this is a reference to a member function, then return the
+        address of the member function (which may involve going
+        through the object's vtable), otherwise, return an expression
+        for the dereferenced pointer-to-member construct.  */
+      addr = build_unary_op (ADDR_EXPR, base, 0);
+    }
 
   if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE)
     {
+      if (addr == error_mark_node)
+       {
+         cp_error ("object missing in `%E'", exp);
+         return error_mark_node;
+       }
+
       basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (member));
       addr = convert_pointer_to (basetype, addr);
       member = convert (ptrdiff_type_node,
index 99943e22f0be9a925f497a699b2a33e6a45f839f..f5f502dbfd0b3ecb5ad60ba9dc9bcf8e1e7d91d6 100644 (file)
@@ -2858,6 +2858,8 @@ mark_decl_instantiated (result, extern_p)
       DECL_INTERFACE_KNOWN (result) = 1;
       DECL_NOT_REALLY_EXTERN (result) = 1;
     }
+  else if (TREE_CODE (result) == FUNCTION_DECL)
+    mark_inline_for_output (result);
 }
 
 /* Given two function templates PAT1 and PAT2, return:
index dfcc28f2b3ea8f10a3336ccb506d03645e23b7c9..1e09c28e0aa1e032bbc5822390ffa93f4fb857b9 100644 (file)
@@ -2463,8 +2463,8 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
       idx = save_expr (build_component_ref (function,
                                            index_identifier,
                                            NULL_TREE, 0));
-      e1 = build (GT_EXPR, boolean_type_node, idx,
-                 convert (delta_type_node, integer_zero_node));
+      e1 = fold (build (GT_EXPR, boolean_type_node, idx,
+                       convert (delta_type_node, integer_zero_node)));
       delta = convert (ptrdiff_type_node,
                       build_component_ref (function, delta_identifier, NULL_TREE, 0));
       delta2 = DELTA2_FROM_PTRMEMFUNC (function);
@@ -2473,7 +2473,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
       instance
        = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
                                   instance_ptr);
-      if (instance == error_mark_node)
+      if (instance == error_mark_node && instance_ptr != error_mark_node)
        return instance;
 
       vtbl = convert_pointer_to (ptr_type_node, instance);
@@ -2503,7 +2503,14 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
 
       e3 = PFN_FROM_PTRMEMFUNC (function);
       TREE_TYPE (e2) = TREE_TYPE (e3);
-      function = build_conditional_expr (e1, e2, e3);
+      e1 = build_conditional_expr (e1, e2, e3);
+
+      if (instance_ptr == error_mark_node
+         && TREE_CODE (e1) != ADDR_EXPR
+         && TREE_CODE (TREE_OPERAND (e1, 0)) != FUNCTION_DECL)
+       cp_error ("object missing in `%E'", function);
+
+      function = e1;
 
       /* Make sure this doesn't get evaluated first inside one of the
          branches of the COND_EXPR.  */
@@ -5408,7 +5415,11 @@ build_c_cast (type, expr, allow_nonconverting)
         convert references to their expanded types,
         but don't convert any other types.  */
       if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
-         || TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE
+         || (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE
+             /* Don't do the default conversion if we want a
+                pointer to a function.  */
+             && TREE_CODE (type) != POINTER_TYPE
+             && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
          || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
          || TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
        value = default_conversion (value);