cp-tree.h (language_lvalue_valid): Remove.
authorMark Mitchell <mark@markmitchell.com>
Thu, 24 Sep 1998 23:53:37 +0000 (23:53 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 24 Sep 1998 23:53:37 +0000 (23:53 +0000)
* cp-tree.h (language_lvalue_valid): Remove.
* decl.c (grokdeclarator): Don't disallow references to functions.
* tree.c (lvalue_p_1): New function, combining duplicated
code from ...
(lvalue_p): Use it.
(real_lvalue_p): Likewise.
* typeck.c (language_lvalue_valid): Remove.
(build_modify_expr): Treat FUNCTION_TYPEs as readonly, even though
they don't have TREE_READONLY set.
* typeck2.c (readonly_error): Add case for FUNCTION_DECLs.

From-SVN: r22583

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/g++.old-deja/g++.bugs/900519_05.C
gcc/testsuite/g++.old-deja/g++.jason/ref4.C
gcc/testsuite/g++.old-deja/g++.law/arm2.C

index 26aad5f7dd080cf605d83c76123b1375ac07b6e2..548bed8dd71f43bbbfe7cafc405dd896356eb981 100644 (file)
@@ -1,3 +1,16 @@
+1998-09-24  Mark Mitchell  <mark@markmitchell.com>
+
+       * cp-tree.h (language_lvalue_valid): Remove.
+       * decl.c (grokdeclarator): Don't disallow references to functions.
+       * tree.c (lvalue_p_1): New function, combining duplicated
+       code from ...
+       (lvalue_p): Use it.
+       (real_lvalue_p): Likewise.
+       * typeck.c (language_lvalue_valid): Remove.
+       (build_modify_expr): Treat FUNCTION_TYPEs as readonly, even though
+       they don't have TREE_READONLY set.
+       * typeck2.c (readonly_error): Add case for FUNCTION_DECLs.
+       
 1998-09-24  Benjamin Kosnik  <bkoz@loony.cygnus.com>
 
        * spew.c (yylex): Give diagnostic.
index 1f4bc0e2774c5a53d116fe7cf97ad0a560ceac34..d77bb82c381114638a19abb06fe2ae575ef5dd7c 100644 (file)
@@ -3101,7 +3101,6 @@ extern tree build_const_cast                      PROTO((tree, tree));
 extern tree build_c_cast                       PROTO((tree, tree));
 extern tree build_x_modify_expr                        PROTO((tree, enum tree_code, tree));
 extern tree build_modify_expr                  PROTO((tree, enum tree_code, tree));
-extern int language_lvalue_valid               PROTO((tree));
 extern void warn_for_assignment                        PROTO((char *, char *, char *, tree, int, int));
 extern tree convert_for_initialization         PROTO((tree, tree, tree, int, char *, tree, int));
 extern void c_expand_asm_operands              PROTO((tree, tree, tree, tree, int, char *, int));
index a8317cc698c1133ab4adf42551ccf90fbc47fa57..87a391f03503bc3bba3a01f6c41085887e09d267 100644 (file)
@@ -9744,18 +9744,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            }
          else if (TREE_CODE (declarator) == ADDR_EXPR)
            {
-             if (TREE_CODE (type) == FUNCTION_TYPE)
-               {
-                 error ("cannot declare references to functions; use pointer to function instead");
-                 type = build_pointer_type (type);
-               }
+             if (TREE_CODE (type) == VOID_TYPE)
+               error ("invalid type: `void &'");
              else
-               {
-                 if (TREE_CODE (type) == VOID_TYPE)
-                   error ("invalid type: `void &'");
-                 else
-                   type = build_reference_type (type);
-               }
+               type = build_reference_type (type);
            }
          else if (TREE_CODE (type) == METHOD_TYPE)
            {
index 41475b5f46782f29b6c1c8f56fb5c434a64128c8..1a87a5128e1b6cee0b3a9246964c553099327145 100644 (file)
@@ -40,20 +40,19 @@ static tree list_hash_lookup PROTO((int, int, int, int, tree, tree,
                                    tree));
 static void propagate_binfo_offsets PROTO((tree, tree));
 static int avoid_overlap PROTO((tree, tree));
+static int lvalue_p_1 PROTO((tree, int));
 
 #define CEIL(x,y) (((x) + (y) - 1) / (y))
 
-/* Return nonzero if REF is an lvalue valid for this language.
-   Lvalues can be assigned, unless they have TREE_READONLY.
-   Lvalues can have their address taken, unless they have DECL_REGISTER.  */
+/* Returns non-zero if REF is an lvalue.  If
+   TREAT_CLASS_RVALUES_AS_LVALUES is non-zero, rvalues of class type
+   are considered lvalues.  */
 
-int
-real_lvalue_p (ref)
+static int
+lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
      tree ref;
+     int treat_class_rvalues_as_lvalues;
 {
-  if (! language_lvalue_valid (ref))
-    return 0;
-  
   if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
     return 1;
 
@@ -71,7 +70,10 @@ real_lvalue_p (ref)
     case UNSAVE_EXPR:
     case TRY_CATCH_EXPR:
     case WITH_CLEANUP_EXPR:
-      return real_lvalue_p (TREE_OPERAND (ref, 0));
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+      return lvalue_p_1 (TREE_OPERAND (ref, 0),
+                        treat_class_rvalues_as_lvalues);
 
     case STRING_CST:
       return 1;
@@ -85,7 +87,6 @@ real_lvalue_p (ref)
     case ARRAY_REF:
     case PARM_DECL:
     case RESULT_DECL:
-    case ERROR_MARK:
       if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
          && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
        return 1;
@@ -97,24 +98,43 @@ real_lvalue_p (ref)
     case OFFSET_REF:
       if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
        return 1;
-      return real_lvalue_p (TREE_OPERAND (ref, 0))
-       && real_lvalue_p (TREE_OPERAND (ref, 1));
+      return (lvalue_p_1 (TREE_OPERAND (ref, 0),
+                         treat_class_rvalues_as_lvalues)
+             && lvalue_p_1 (TREE_OPERAND (ref, 1),
+                            treat_class_rvalues_as_lvalues));
       break;
 
     case COND_EXPR:
-      return (real_lvalue_p (TREE_OPERAND (ref, 1))
-             && real_lvalue_p (TREE_OPERAND (ref, 2)));
+      return (lvalue_p_1 (TREE_OPERAND (ref, 1),
+                         treat_class_rvalues_as_lvalues)
+             && lvalue_p_1 (TREE_OPERAND (ref, 2),
+                            treat_class_rvalues_as_lvalues));
 
     case MODIFY_EXPR:
       return 1;
 
     case COMPOUND_EXPR:
-      return real_lvalue_p (TREE_OPERAND (ref, 1));
+      return lvalue_p_1 (TREE_OPERAND (ref, 1),
+                           treat_class_rvalues_as_lvalues);
 
     case MAX_EXPR:
     case MIN_EXPR:
-      return (real_lvalue_p (TREE_OPERAND (ref, 0))
-             && real_lvalue_p (TREE_OPERAND (ref, 1)));
+      return (lvalue_p_1 (TREE_OPERAND (ref, 0),
+                         treat_class_rvalues_as_lvalues)
+             && lvalue_p_1 (TREE_OPERAND (ref, 1),
+                            treat_class_rvalues_as_lvalues));
+
+    case TARGET_EXPR:
+      return treat_class_rvalues_as_lvalues;
+
+    case CALL_EXPR:
+      return (treat_class_rvalues_as_lvalues
+             && IS_AGGR_TYPE (TREE_TYPE (ref)));
+
+    case FUNCTION_DECL:
+      /* All functions (except non-static-member functions) are
+        lvalues.  */
+      return !DECL_NONSTATIC_MEMBER_FUNCTION_P (ref);
 
     default:
       break;
@@ -123,92 +143,26 @@ real_lvalue_p (ref)
   return 0;
 }
 
+/* Return nonzero if REF is an lvalue valid for this language.
+   Lvalues can be assigned, unless they have TREE_READONLY, or unless
+   they are FUNCTION_DECLs.  Lvalues can have their address taken,
+   unless they have DECL_REGISTER.  */
+
+int
+real_lvalue_p (ref)
+     tree ref;
+{
+  return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
+}
+
 /* This differs from real_lvalue_p in that class rvalues are considered
    lvalues.  */
+
 int
 lvalue_p (ref)
      tree ref;
 {
-  if (! language_lvalue_valid (ref))
-    return 0;
-  
-  if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
-    return 1;
-
-  if (ref == current_class_ptr && flag_this_is_variable <= 0)
-    return 0;
-
-  switch (TREE_CODE (ref))
-    {
-      /* preincrements and predecrements are valid lvals, provided
-        what they refer to are valid lvals.  */
-    case PREINCREMENT_EXPR:
-    case PREDECREMENT_EXPR:
-    case REALPART_EXPR:
-    case IMAGPART_EXPR:
-    case COMPONENT_REF:
-    case SAVE_EXPR:
-    case UNSAVE_EXPR:
-    case TRY_CATCH_EXPR:
-    case WITH_CLEANUP_EXPR:
-      return lvalue_p (TREE_OPERAND (ref, 0));
-
-    case STRING_CST:
-      return 1;
-
-    case VAR_DECL:
-      if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
-         && DECL_LANG_SPECIFIC (ref)
-         && DECL_IN_AGGR_P (ref))
-       return 0;
-    case INDIRECT_REF:
-    case ARRAY_REF:
-    case PARM_DECL:
-    case RESULT_DECL:
-    case ERROR_MARK:
-      if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
-         && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
-       return 1;
-      break;
-
-    case TARGET_EXPR:
-      return 1;
-
-    case CALL_EXPR:
-      if (IS_AGGR_TYPE (TREE_TYPE (ref)))
-       return 1;
-      break;
-
-      /* A currently unresolved scope ref.  */
-    case SCOPE_REF:
-      my_friendly_abort (103);
-    case OFFSET_REF:
-      if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
-       return 1;
-      return lvalue_p (TREE_OPERAND (ref, 0))
-       && lvalue_p (TREE_OPERAND (ref, 1));
-      break;
-
-    case COND_EXPR:
-      return (lvalue_p (TREE_OPERAND (ref, 1))
-             && lvalue_p (TREE_OPERAND (ref, 2)));
-
-    case MODIFY_EXPR:
-      return 1;
-
-    case COMPOUND_EXPR:
-      return lvalue_p (TREE_OPERAND (ref, 1));
-
-    case MAX_EXPR:
-    case MIN_EXPR:
-      return (lvalue_p (TREE_OPERAND (ref, 0))
-             && lvalue_p (TREE_OPERAND (ref, 1)));
-
-    default:
-      break;
-    }
-
-  return 0;
+  return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1);
 }
 
 /* Return nonzero if REF is an lvalue valid for this language;
index 6fc3707160e31dd0aa9682bd9a9ef86b29949194..72481750d7672628272abbae7b1b029e11d9efec 100644 (file)
@@ -6106,6 +6106,9 @@ build_modify_expr (lhs, modifycode, rhs)
            && (IS_SIGNATURE_POINTER (TREE_TYPE (TREE_OPERAND (lhs, 0)))
                || IS_SIGNATURE_REFERENCE (TREE_TYPE (TREE_OPERAND (lhs, 0)))))
       && (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
+         /* Functions are not modifiable, even though they are
+            lvalues.  */
+         || TREE_CODE (TREE_TYPE (lhs)) == FUNCTION_TYPE
          || ((TREE_CODE (lhstype) == RECORD_TYPE
               || TREE_CODE (lhstype) == UNION_TYPE)
              && C_TYPE_FIELDS_READONLY (lhstype))
@@ -6354,15 +6357,6 @@ build_x_modify_expr (lhs, modifycode, rhs)
   return build_modify_expr (lhs, modifycode, rhs);
 }
 
-/* Return 0 if EXP is not a valid lvalue in this language
-   even though `lvalue_or_else' would accept it.  */
-
-int
-language_lvalue_valid (exp)
-     tree exp ATTRIBUTE_UNUSED;
-{
-  return 1;
-}
 \f
 /* Get difference in deltas for different pointer to member function
    types.  Return integer_zero_node, if FROM cannot be converted to a
index 265b387fd232585367ea4951b7c164018e250b14..a00a4f13ffc1904e8e50585eb0db618785edcfcf 100644 (file)
@@ -118,7 +118,9 @@ readonly_error (arg, string, soft)
     (*fn) ("%s of read-only reference `%D'", string, TREE_OPERAND (arg, 0));
   else if (TREE_CODE (arg) == RESULT_DECL)
     (*fn) ("%s of read-only named return value `%D'", string, arg);
-  else        
+  else if (TREE_CODE (arg) == FUNCTION_DECL)
+    (*fn) ("%s of function `%D'", string, arg);
+  else
     (*fn) ("%s of read-only location", string);
 }
 
index 05d2ea03d3d8926d1cf9376b7d9712ad0eebc8a5..9a2a4cffaa27f21ac36b6f17374319d77e914d8d 100644 (file)
@@ -7,12 +7,12 @@
 // keywords: function types, reference types
 
 typedef void (func_type) (int, int);
-typedef func_type& func_ref_type;              // gets bogus error, XFAIL *-*-*
+typedef func_type& func_ref_type;              
 
 void function (int arg1, int arg2)
 {
 }
 
-func_type& global_func_ref1 = function;                // gets bogus error, XFAIL *-*-*
+func_type& global_func_ref1 = function;                
 
 int main () { return 0; }
index 422c58cab7020f47201e00ae706fd97f7f012d46..5c62d6a10d2b405ac7cedddf301fad24e253f963 100644 (file)
@@ -1,4 +1,4 @@
 // Build don't link:
 
 void f ();
-void (&fr)() = f;              // gets bogus error - references to functions XFAIL *-*-*
+void (&fr)() = f;
index de8fe425bda15b85a3a5c33c3ba3c01dde827e5d..d2f43d76e8b4855ff10b5b68f3067ec2da0e5c59 100644 (file)
@@ -11,7 +11,7 @@ int f() {  return 1; }
 
 int main()
 {
-  int (&fr)() = f;  // g++ cannot compile it
+  int (&fr)() = f;
 
   return 0;
 }