tree.c (lvalue_p_1): Add argument for whether casts of lvalues are allowable.
authorMatt Austern <austern@apple.com>
Sun, 25 Aug 2002 04:57:16 +0000 (04:57 +0000)
committerStan Shebs <shebs@gcc.gnu.org>
Sun, 25 Aug 2002 04:57:16 +0000 (04:57 +0000)
2002-08-24  Matt Austern  <austern@apple.com>

        * tree.c (lvalue_p_1): Add argument for whether casts of lvalues
        are allowable.
        (real_lvalue_p): Update caller.
        (lvalue_p): Ditto.
        (non_cast_lvalue_or_else): New.
        * tree.h: Declare it.
        * typeck.c (build_unary_op): Use non_cast_lvalue_or_else.

2002-08-24  Matt Austern  <austern@apple.com>

        * g++.dg/ext/lvaddr.C: New test.
        * g++.dg/ext/lvcast.C: New test.

From-SVN: r56560

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/lvaddr.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/lvcast.C [new file with mode: 0644]

index cb95b6d33b79cb2397786196edd7547eca7fccbc..def395ea1264666f9eda5a1c09d8544b9231e6fc 100644 (file)
@@ -1,3 +1,13 @@
+2002-08-24  Matt Austern  <austern@apple.com>
+
+       * tree.c (lvalue_p_1): Add argument for whether casts of lvalues
+       are allowable.
+       (real_lvalue_p): Update caller.
+       (lvalue_p): Ditto.
+       (non_cast_lvalue_or_else): New.
+       * tree.h: Declare it.
+        * typeck.c (build_unary_op): Use non_cast_lvalue_or_else.
+
 2002-08-22  Mark Mitchell  <mark@codesourcery.com>
 
        * typeck.c (build_class_member_access_expr): Handle COMPOUND_EXPR
index 44a52fc8e78e760cbb045b4885bf87948ee27614..ef4f171829bc0124d318e68e28b1519523509604 100644 (file)
@@ -4184,6 +4184,7 @@ extern tree canonical_type_variant              PARAMS ((tree));
 extern void unshare_base_binfos                        PARAMS ((tree));
 extern int member_p                            PARAMS ((tree));
 extern cp_lvalue_kind real_lvalue_p            PARAMS ((tree));
+extern int non_cast_lvalue_or_else             PARAMS ((tree, const char *));
 extern tree build_min                          PARAMS ((enum tree_code, tree,
                                                         ...));
 extern tree build_min_nt                       PARAMS ((enum tree_code, ...));
index 3630566037256a9bd04db46d1662c1898e3f7b75..6e092850762cf3cf78dde7ac21f520dd50d73212 100644 (file)
@@ -39,7 +39,7 @@ static tree build_cplus_array_type_1 PARAMS ((tree, tree));
 static int list_hash_eq PARAMS ((const void *, const void *));
 static hashval_t list_hash_pieces PARAMS ((tree, tree, tree));
 static hashval_t list_hash PARAMS ((const void *));
-static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int));
+static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int, int));
 static tree no_linkage_helper PARAMS ((tree *, int *, void *));
 static tree build_srcloc PARAMS ((const char *, int));
 static tree mark_local_for_remap_r PARAMS ((tree *, int *, void *));
@@ -59,9 +59,10 @@ static tree handle_init_priority_attribute PARAMS ((tree *, tree, tree, int, boo
    non-zero, rvalues of class type are considered lvalues.  */
 
 static cp_lvalue_kind
-lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
+lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue)
      tree ref;
      int treat_class_rvalues_as_lvalues;
+     int allow_cast_as_lvalue;
 {
   cp_lvalue_kind op1_lvalue_kind = clk_none;
   cp_lvalue_kind op2_lvalue_kind = clk_none;
@@ -84,16 +85,28 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
     case WITH_CLEANUP_EXPR:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
-      /* This shouldn't be here, but there are lots of places in the compiler
-         that are sloppy about tacking on NOP_EXPRs to the same type when
-        no actual conversion is happening.  */
-    case NOP_EXPR:
       return lvalue_p_1 (TREE_OPERAND (ref, 0),
-                        treat_class_rvalues_as_lvalues);
+                        treat_class_rvalues_as_lvalues,
+                        allow_cast_as_lvalue);
+
+    case NOP_EXPR:
+      /* If expression doesn't change the type, we consider it as an
+        lvalue even when cast_as_lvalue extension isn't selected.
+        That's because parts of the compiler are alleged to be sloppy
+        about sticking in NOP_EXPR node for no good reason. */
+      if (allow_cast_as_lvalue ||
+         same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ref)),
+                      TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (ref, 0)))))
+       return lvalue_p_1 (TREE_OPERAND (ref, 0),
+                          treat_class_rvalues_as_lvalues,
+                          allow_cast_as_lvalue);
+      else
+       return clk_none;
 
     case COMPONENT_REF:
       op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
-                                   treat_class_rvalues_as_lvalues);
+                                   treat_class_rvalues_as_lvalues,
+                                   allow_cast_as_lvalue);
       if (op1_lvalue_kind 
          /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
             situations.  */
@@ -134,16 +147,20 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
     case MAX_EXPR:
     case MIN_EXPR:
       op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
-                                   treat_class_rvalues_as_lvalues);
+                                   treat_class_rvalues_as_lvalues,
+                                   allow_cast_as_lvalue);
       op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
-                                   treat_class_rvalues_as_lvalues);
+                                   treat_class_rvalues_as_lvalues,
+                                   allow_cast_as_lvalue);
       break;
 
     case COND_EXPR:
       op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
-                                   treat_class_rvalues_as_lvalues);
+                                   treat_class_rvalues_as_lvalues,
+                                   allow_cast_as_lvalue);
       op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
-                                   treat_class_rvalues_as_lvalues);
+                                   treat_class_rvalues_as_lvalues,
+                                   allow_cast_as_lvalue);
       break;
 
     case MODIFY_EXPR:
@@ -151,7 +168,8 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
 
     case COMPOUND_EXPR:
       return lvalue_p_1 (TREE_OPERAND (ref, 1),
-                        treat_class_rvalues_as_lvalues);
+                        treat_class_rvalues_as_lvalues,
+                        allow_cast_as_lvalue);
 
     case TARGET_EXPR:
       return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
@@ -196,7 +214,7 @@ cp_lvalue_kind
 real_lvalue_p (ref)
      tree ref;
 {
-  return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
+  return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/ 0, /*cast*/ 1);
 }
 
 /* This differs from real_lvalue_p in that class rvalues are
@@ -207,7 +225,7 @@ lvalue_p (ref)
      tree ref;
 {
   return 
-    (lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1) != clk_none);
+    (lvalue_p_1 (ref, /*class rvalue ok*/ 1, /*cast*/ 1) != clk_none);
 }
 
 /* Return nonzero if REF is an lvalue valid for this language;
@@ -218,7 +236,20 @@ lvalue_or_else (ref, string)
      tree ref;
      const char *string;
 {
-  int win = lvalue_p (ref);
+  int ret = lvalue_p_1 (ref, /* class rvalue ok */ 1, /* cast ok */ 1);
+  int win = (ret != clk_none);
+  if (! win)
+    error ("non-lvalue in %s", string);
+  return win;
+}
+
+int
+non_cast_lvalue_or_else (ref, string)
+     tree ref;
+     const char *string;
+{
+  int ret = lvalue_p_1 (ref, /* class rvalue ok */ 1, /* cast ok */ 0);
+  int win = (ret != clk_none);
   if (! win)
     error ("non-lvalue in %s", string);
   return win;
index 624b379cf7165da0e0c96fbfe4782e530432723f..8535cde4ae70f4f525fac07b25bfdeaa0feb0861 100644 (file)
@@ -4268,7 +4268,7 @@ build_unary_op (code, xarg, noconvert)
         is an error.  */
       else if (TREE_CODE (argtype) != FUNCTION_TYPE
               && TREE_CODE (argtype) != METHOD_TYPE
-              && !lvalue_or_else (arg, "unary `&'"))
+              && !non_cast_lvalue_or_else (arg, "unary `&'"))
        return error_mark_node;
 
       if (argtype != error_mark_node)
index 00a92134d458f17ea7d1387fda01c8396cd5dbed..f509299f6e5d772ca1790bcfd0e6533eb6357487 100644 (file)
@@ -1,3 +1,8 @@
+2002-08-24  Matt Austern  <austern@apple.com>
+
+       * g++.dg/ext/lvaddr.C: New test.
+       * g++.dg/ext/lvcast.C: New test.
+       
 2002-08-22  Mark Mitchell  <mark@codesourcery.com>
 
        * testsuite/g++.dg/inherit/cond1.C: New test.
diff --git a/gcc/testsuite/g++.dg/ext/lvaddr.C b/gcc/testsuite/g++.dg/ext/lvaddr.C
new file mode 100644 (file)
index 0000000..184afce
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright (C) 2002 Free Software Foundation
+// Contributed by Matt Austern <austern@apple.com>
+
+// { dg-do compile }
+
+void f()
+{
+  int n;
+  char* p = &(char) n;         // { dg-error "non-lvalue" }
+}
diff --git a/gcc/testsuite/g++.dg/ext/lvcast.C b/gcc/testsuite/g++.dg/ext/lvcast.C
new file mode 100644 (file)
index 0000000..efff04e
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright (C) 2002 Free Software Foundation
+// Contributed by Matt Austern <austern@apple.com>
+
+// { dg-do compile }
+// { dg-options -fpermissive }
+
+void f ()
+{
+  int n;
+  (char) n = 1;
+}