OSDN Git Service

* c-decl.c (c_init_decl_processing): Set pedantic_lvalues to
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 20 Jan 2004 01:38:27 +0000 (01:38 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 20 Jan 2004 01:38:27 +0000 (01:38 +0000)
true unconditionally.
* c-typeck.c (unary_complex_lvalue, pedantic_lvalue_warning):
Remove.
(build_unary_op, build_modify_expr): Don't handle extended
lvalues.
(build_component_ref, build_conditional_expr): Call non_lvalue
instead of pedantic_non_lvalue.
(build_c_cast): Don't condition use of non_lvalue on pedantic.
* fold-const.c (fold): Don't check pedantic directly for
COMPOUND_EXPR.  Ensure that results for COMPOUND_EXPR are
passed to pedantic_non_lvalue.
* doc/extend.texi: Remove documentation of extended lvalues.

testsuite:
* gcc.c-torture/compile/981022-1.c: Remove.
* gcc.dg/array-5.c: Remove XFAIL.
* gcc.dg/sequence-pt-1.c: Remove test using extended lvalues.
* gcc.dg/cast-lvalue-1.c, gcc.dg/compound-lvalue-1.c,
gcc.dg/cond-lvalue-1.c: Update.
* gcc.dg/cast-lvalue-2.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@76192 138bc75d-0d04-0410-961f-82ee72b054a4

13 files changed:
gcc/ChangeLog
gcc/c-decl.c
gcc/c-typeck.c
gcc/doc/extend.texi
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/981022-1.c [deleted file]
gcc/testsuite/gcc.dg/array-5.c
gcc/testsuite/gcc.dg/cast-lvalue-1.c
gcc/testsuite/gcc.dg/cast-lvalue-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/compound-lvalue-1.c
gcc/testsuite/gcc.dg/cond-lvalue-1.c
gcc/testsuite/gcc.dg/sequence-pt-1.c

index 7949b4f..c2a1a50 100644 (file)
@@ -1,3 +1,19 @@
+2004-01-20  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+       * c-decl.c (c_init_decl_processing): Set pedantic_lvalues to
+       true unconditionally.
+       * c-typeck.c (unary_complex_lvalue, pedantic_lvalue_warning):
+       Remove.
+       (build_unary_op, build_modify_expr): Don't handle extended
+       lvalues.
+       (build_component_ref, build_conditional_expr): Call non_lvalue
+       instead of pedantic_non_lvalue.
+       (build_c_cast): Don't condition use of non_lvalue on pedantic.
+       * fold-const.c (fold): Don't check pedantic directly for
+       COMPOUND_EXPR.  Ensure that results for COMPOUND_EXPR are
+       passed to pedantic_non_lvalue.
+       * doc/extend.texi: Remove documentation of extended lvalues.
+
 2004-01-19  Roger Sayle  <roger@eyesopen.com>
 
        PR optimization/5263
index 77f6cfb..93360be 100644 (file)
@@ -2282,7 +2282,7 @@ c_init_decl_processing (void)
 
   input_location = save_loc;
 
-  pedantic_lvalues = pedantic;
+  pedantic_lvalues = true;
 
   make_fname_decl = c_make_fname_decl;
   start_fname_decls ();
index e8bec8f..b6a5d9e 100644 (file)
@@ -60,8 +60,6 @@ static tree default_function_array_conversion (tree);
 static tree lookup_field (tree, tree);
 static tree convert_arguments (tree, tree, tree, tree);
 static tree pointer_diff (tree, tree);
-static tree unary_complex_lvalue (enum tree_code, tree, int);
-static void pedantic_lvalue_warning (enum tree_code);
 static tree internal_build_compound_expr (tree, int);
 static tree convert_for_assignment (tree, tree, const char *, tree, tree,
                                    int);
@@ -1303,7 +1301,7 @@ build_component_ref (tree datum, tree component)
   tree ref;
 
   /* If DATUM is a COMPOUND_EXPR, move our reference inside it.
-     If pedantic ensure that the arguments are not lvalues; otherwise,
+     Ensure that the arguments are not lvalues; otherwise,
      if the component is an array, it would wrongly decay to a pointer in
      C89 mode.
      We cannot do this with a COND_EXPR, because in a conditional expression
@@ -1316,7 +1314,7 @@ build_component_ref (tree datum, tree component)
       {
        tree value = build_component_ref (TREE_OPERAND (datum, 1), component);
        return build (COMPOUND_EXPR, TREE_TYPE (value),
-                     TREE_OPERAND (datum, 0), pedantic_non_lvalue (value));
+                     TREE_OPERAND (datum, 0), non_lvalue (value));
       }
     default:
       break;
@@ -2287,12 +2285,6 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
     case POSTINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
     case POSTDECREMENT_EXPR:
-      /* Handle complex lvalues (when permitted)
-        by reduction to simpler cases.  */
-
-      val = unary_complex_lvalue (code, arg, 0);
-      if (val != 0)
-       return val;
 
       /* Increment or decrement the real part of the value,
         and don't change the imaginary part.  */
@@ -2360,57 +2352,6 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
        inc = convert (argtype, inc);
 
-       /* Handle incrementing a cast-expression.  */
-
-       while (1)
-         switch (TREE_CODE (arg))
-           {
-           case NOP_EXPR:
-           case CONVERT_EXPR:
-           case FLOAT_EXPR:
-           case FIX_TRUNC_EXPR:
-           case FIX_FLOOR_EXPR:
-           case FIX_ROUND_EXPR:
-           case FIX_CEIL_EXPR:
-             pedantic_lvalue_warning (CONVERT_EXPR);
-             /* If the real type has the same machine representation
-                as the type it is cast to, we can make better output
-                by adding directly to the inside of the cast.  */
-             if ((TREE_CODE (TREE_TYPE (arg))
-                  == TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))))
-                 && (TYPE_MODE (TREE_TYPE (arg))
-                     == TYPE_MODE (TREE_TYPE (TREE_OPERAND (arg, 0)))))
-               arg = TREE_OPERAND (arg, 0);
-             else
-               {
-                 tree incremented, modify, value;
-                 if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
-                   value = boolean_increment (code, arg);
-                 else
-                   {
-                     arg = stabilize_reference (arg);
-                     if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
-                       value = arg;
-                     else
-                       value = save_expr (arg);
-                     incremented = build (((code == PREINCREMENT_EXPR
-                                            || code == POSTINCREMENT_EXPR)
-                                           ? PLUS_EXPR : MINUS_EXPR),
-                                          argtype, value, inc);
-                     TREE_SIDE_EFFECTS (incremented) = 1;
-                     modify = build_modify_expr (arg, NOP_EXPR, incremented);
-                     value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
-                   }
-                 TREE_USED (value) = 1;
-                 return value;
-               }
-             break;
-
-           default:
-             goto give_up;
-           }
-      give_up:
-
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
                                    || code == POSTINCREMENT_EXPR)
@@ -2457,12 +2398,6 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
                                  TREE_OPERAND (arg, 1), 1);
        }
 
-      /* Handle complex lvalues (when permitted)
-        by reduction to simpler cases.  */
-      val = unary_complex_lvalue (code, arg, flag);
-      if (val != 0)
-       return val;
-
       /* Anything not already handled and not a true memory reference
         or a non-lvalue array is an error.  */
       else if (typecode != FUNCTION_TYPE && !flag
@@ -2580,67 +2515,6 @@ lvalue_or_else (tree ref, const char *msgid)
   return win;
 }
 
-/* Apply unary lvalue-demanding operator CODE to the expression ARG
-   for certain kinds of expressions which are not really lvalues
-   but which we can accept as lvalues.  If FLAG is nonzero, then
-   non-lvalues are OK since we may be converting a non-lvalue array to
-   a pointer in C99.
-
-   If ARG is not a kind of expression we can handle, return zero.  */
-
-static tree
-unary_complex_lvalue (enum tree_code code, tree arg, int flag)
-{
-  /* Handle (a, b) used as an "lvalue".  */
-  if (TREE_CODE (arg) == COMPOUND_EXPR)
-    {
-      tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0);
-
-      /* If this returns a function type, it isn't really being used as
-        an lvalue, so don't issue a warning about it.  */
-      if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag)
-       pedantic_lvalue_warning (COMPOUND_EXPR);
-
-      return build (COMPOUND_EXPR, TREE_TYPE (real_result),
-                   TREE_OPERAND (arg, 0), real_result);
-    }
-
-  /* Handle (a ? b : c) used as an "lvalue".  */
-  if (TREE_CODE (arg) == COND_EXPR)
-    {
-      if (!flag)
-       pedantic_lvalue_warning (COND_EXPR);
-      if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag)
-       pedantic_lvalue_warning (COMPOUND_EXPR);
-
-      return (build_conditional_expr
-             (TREE_OPERAND (arg, 0),
-              build_unary_op (code, TREE_OPERAND (arg, 1), flag),
-              build_unary_op (code, TREE_OPERAND (arg, 2), flag)));
-    }
-
-  return 0;
-}
-
-/* If pedantic, warn about improper lvalue.   CODE is either COND_EXPR
-   COMPOUND_EXPR, or CONVERT_EXPR (for casts).  */
-
-static void
-pedantic_lvalue_warning (enum tree_code code)
-{
-  switch (code)
-    {
-    case COND_EXPR:
-      pedwarn ("use of conditional expressions as lvalues is deprecated");
-      break;
-    case COMPOUND_EXPR:
-      pedwarn ("use of compound expressions as lvalues is deprecated");
-      break;
-    default:
-      pedwarn ("use of cast expressions as lvalues is deprecated");
-      break;
-    }
-}
 \f
 /* Warn about storing in something that is `const'.  */
 
@@ -2901,7 +2775,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
     op2 = convert_and_check (result_type, op2);
 
   if (TREE_CODE (ifexp) == INTEGER_CST)
-    return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
+    return non_lvalue (integer_zerop (ifexp) ? op2 : op1);
 
   return fold (build (COND_EXPR, result_type, ifexp, op1, op2));
 }
@@ -3158,14 +3032,14 @@ build_c_cast (tree type, tree expr)
        }
     }
 
-  /* Pedantically, don't let (void *) (FOO *) 0 be a null pointer constant.  */
-  if (pedantic && TREE_CODE (value) == INTEGER_CST
+  /* Don't let (void *) (FOO *) 0 be a null pointer constant.  */
+  if (TREE_CODE (value) == INTEGER_CST
       && TREE_CODE (expr) == INTEGER_CST
       && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE)
     value = non_lvalue (value);
 
-  /* If pedantic, don't let a cast be an lvalue.  */
-  if (value == expr && pedantic)
+  /* Don't let a cast be an lvalue.  */
+  if (value == expr)
     value = non_lvalue (value);
 
   return value;
@@ -3216,45 +3090,6 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
   newrhs = rhs;
 
-  /* Handle control structure constructs used as "lvalues".  */
-
-  switch (TREE_CODE (lhs))
-    {
-      /* Handle (a, b) used as an "lvalue".  */
-    case COMPOUND_EXPR:
-      pedantic_lvalue_warning (COMPOUND_EXPR);
-      newrhs = build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs);
-      if (TREE_CODE (newrhs) == ERROR_MARK)
-       return error_mark_node;
-      return build (COMPOUND_EXPR, lhstype,
-                   TREE_OPERAND (lhs, 0), newrhs);
-
-      /* Handle (a ? b : c) used as an "lvalue".  */
-    case COND_EXPR:
-      pedantic_lvalue_warning (COND_EXPR);
-      rhs = save_expr (rhs);
-      {
-       /* Produce (a ? (b = rhs) : (c = rhs))
-          except that the RHS goes through a save-expr
-          so the code to compute it is only emitted once.  */
-       tree cond
-         = build_conditional_expr (TREE_OPERAND (lhs, 0),
-                                   build_modify_expr (TREE_OPERAND (lhs, 1),
-                                                      modifycode, rhs),
-                                   build_modify_expr (TREE_OPERAND (lhs, 2),
-                                                      modifycode, rhs));
-       if (TREE_CODE (cond) == ERROR_MARK)
-         return cond;
-       /* Make sure the code to compute the rhs comes out
-          before the split.  */
-       return build (COMPOUND_EXPR, TREE_TYPE (lhs),
-                     /* But cast it to void to avoid an "unused" error.  */
-                     convert (void_type_node, rhs), cond);
-      }
-    default:
-      break;
-    }
-
   /* If a binary op has been requested, combine the old LHS value with the RHS
      producing the value we should actually store into the LHS.  */
 
@@ -3264,42 +3099,6 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
       newrhs = build_binary_op (modifycode, lhs, rhs, 1);
     }
 
-  /* Handle a cast used as an "lvalue".
-     We have already performed any binary operator using the value as cast.
-     Now convert the result to the cast type of the lhs,
-     and then true type of the lhs and store it there;
-     then convert result back to the cast type to be the value
-     of the assignment.  */
-
-  switch (TREE_CODE (lhs))
-    {
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-    case FLOAT_EXPR:
-    case FIX_TRUNC_EXPR:
-    case FIX_FLOOR_EXPR:
-    case FIX_ROUND_EXPR:
-    case FIX_CEIL_EXPR:
-      newrhs = default_function_array_conversion (newrhs);
-      {
-       tree inner_lhs = TREE_OPERAND (lhs, 0);
-       tree result;
-       result = build_modify_expr (inner_lhs, NOP_EXPR,
-                                   convert (TREE_TYPE (inner_lhs),
-                                            convert (lhstype, newrhs)));
-       if (TREE_CODE (result) == ERROR_MARK)
-         return result;
-       pedantic_lvalue_warning (CONVERT_EXPR);
-       return convert (TREE_TYPE (lhs), result);
-      }
-
-    default:
-      break;
-    }
-
-  /* Now we have handled acceptable kinds of LHS that are not truly lvalues.
-     Reject anything strange now.  */
-
   if (!lvalue_or_else (lhs, "invalid lvalue in assignment"))
     return error_mark_node;
 
index 9b03c77..0eed679 100644 (file)
@@ -429,7 +429,6 @@ extensions, accepted by GCC in C89 mode and in C++.
 * Nested Functions::    As in Algol and Pascal, lexical scoping of functions.
 * Constructing Calls:: Dispatching a call to another function.
 * Typeof::              @code{typeof}: referring to the type of an expression.
-* Lvalues::             Using @samp{?:}, @samp{,} and casts in lvalues.
 * Conditionals::        Omitting the middle operand of a @samp{?:} expression.
 * Long Long::          Double-word integers---@code{long long int}.
 * Complex::             Data types for complex numbers.
@@ -1060,94 +1059,6 @@ typedef typeof(@var{expr}) @var{T};
 @noindent
 This will work with all versions of GCC@.
 
-@node Lvalues
-@section Generalized Lvalues
-@cindex compound expressions as lvalues
-@cindex expressions, compound, as lvalues
-@cindex conditional expressions as lvalues
-@cindex expressions, conditional, as lvalues
-@cindex casts as lvalues
-@cindex generalized lvalues
-@cindex lvalues, generalized
-@cindex extensions, @code{?:}
-@cindex @code{?:} extensions
-
-Compound expressions, conditional expressions and casts are allowed as
-lvalues provided their operands are lvalues.  This means that you can take
-their addresses or store values into them.  All these extensions are
-deprecated.
-
-Standard C++ allows compound expressions and conditional expressions
-as lvalues, and permits casts to reference type, so use of this
-extension is not supported for C++ code.
-
-For example, a compound expression can be assigned, provided the last
-expression in the sequence is an lvalue.  These two expressions are
-equivalent:
-
-@smallexample
-(a, b) += 5
-a, (b += 5)
-@end smallexample
-
-Similarly, the address of the compound expression can be taken.  These two
-expressions are equivalent:
-
-@smallexample
-&(a, b)
-a, &b
-@end smallexample
-
-A conditional expression is a valid lvalue if its type is not void and the
-true and false branches are both valid lvalues.  For example, these two
-expressions are equivalent:
-
-@smallexample
-(a ? b : c) = 5
-(a ? b = 5 : (c = 5))
-@end smallexample
-
-A cast is a valid lvalue if its operand is an lvalue.  This extension
-is deprecated.  A simple
-assignment whose left-hand side is a cast works by converting the
-right-hand side first to the specified type, then to the type of the
-inner left-hand side expression.  After this is stored, the value is
-converted back to the specified type to become the value of the
-assignment.  Thus, if @code{a} has type @code{char *}, the following two
-expressions are equivalent:
-
-@smallexample
-(int)a = 5
-(int)(a = (char *)(int)5)
-@end smallexample
-
-An assignment-with-arithmetic operation such as @samp{+=} applied to a cast
-performs the arithmetic using the type resulting from the cast, and then
-continues as in the previous case.  Therefore, these two expressions are
-equivalent:
-
-@smallexample
-(int)a += 5
-(int)(a = (char *)(int) ((int)a + 5))
-@end smallexample
-
-You cannot take the address of an lvalue cast, because the use of its
-address would not work out coherently.  Suppose that @code{&(int)f} were
-permitted, where @code{f} has type @code{float}.  Then the following
-statement would try to store an integer bit-pattern where a floating
-point number belongs:
-
-@smallexample
-*&(int)f = 1;
-@end smallexample
-
-This is quite different from what @code{(int)f = 1} would do---that
-would convert 1 to floating point and store it.  Rather than cause this
-inconsistency, we think it is better to prohibit use of @samp{&} on a cast.
-
-If you really do want an @code{int *} pointer with the address of
-@code{f}, you can simply write @code{(int *)&f}.
-
 @node Conditionals
 @section Conditionals with Omitted Operands
 @cindex conditional expressions, extensions
index b226215..402a560 100644 (file)
@@ -8170,12 +8170,12 @@ fold (tree expr)
     case COMPOUND_EXPR:
       /* When pedantic, a compound expression can be neither an lvalue
         nor an integer constant expression.  */
-      if (TREE_SIDE_EFFECTS (arg0) || pedantic)
+      if (TREE_SIDE_EFFECTS (arg0) || TREE_CONSTANT (arg1))
        return t;
       /* Don't let (0, 0) be null pointer constant.  */
       if (integer_zerop (arg1))
-       return build1 (NOP_EXPR, type, arg1);
-      return convert (type, arg1);
+       return pedantic_non_lvalue (build1 (NOP_EXPR, type, arg1));
+      return pedantic_non_lvalue (convert (type, arg1));
 
     case COMPLEX_EXPR:
       if (wins)
index 7571391..35ac2ab 100644 (file)
@@ -1,3 +1,12 @@
+2004-01-20  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+       * gcc.c-torture/compile/981022-1.c: Remove.
+       * gcc.dg/array-5.c: Remove XFAIL.
+       * gcc.dg/sequence-pt-1.c: Remove test using extended lvalues.
+       * gcc.dg/cast-lvalue-1.c, gcc.dg/compound-lvalue-1.c,
+       gcc.dg/cond-lvalue-1.c: Update.
+       * gcc.dg/cast-lvalue-2.c: New test.
+
 2004-01-19  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/13592
diff --git a/gcc/testsuite/gcc.c-torture/compile/981022-1.c b/gcc/testsuite/gcc.c-torture/compile/981022-1.c
deleted file mode 100644 (file)
index 46369fc..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* This tests a combination of two gcc extensions.  Omitting the middle
-   operand of ?: and using ?: as an lvalue.  */
-int x, y;
-
-int main ()
-{
-  (x ?: y) = 0; /* { dg-bogus "lvalue" "" { xfail *-*-* } } */
-  return 0;
-}
index 7a8e3ac..1717de4 100644 (file)
@@ -37,6 +37,6 @@ void func(int n, int m)
        expression, and thus A is a VLA.  */
     int a[6][(2, 2)];
     int (*p)[3];
-    p = a; /* { dg-bogus "incompatible" "bad vla handling" { xfail *-*-* } } */
+    p = a; /* { dg-bogus "incompatible" "bad vla handling" } */
   }
 }
index 1e0f04a..4e84804 100644 (file)
@@ -8,5 +8,6 @@ int x;
 void
 foo (void)
 {
-  (char) x = 1; /* { dg-warning "lvalue" "cast as lvalue deprecated" } */
+  (char) x = 1; /* { dg-bogus "warning" "warning in place of error" } */
 }
+/* { dg-error "lvalue" "cast as lvalue" { target *-*-* } 11 } */
diff --git a/gcc/testsuite/gcc.dg/cast-lvalue-2.c b/gcc/testsuite/gcc.dg/cast-lvalue-2.c
new file mode 100644 (file)
index 0000000..ed6a2e6
--- /dev/null
@@ -0,0 +1,13 @@
+/* Test for error on casts as lvalues.  Casts to same type.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+int x;
+
+void
+foo (void)
+{
+  (int) x = 1; /* { dg-bogus "warning" "warning in place of error" } */
+}
+/* { dg-error "lvalue" "cast as lvalue" { target *-*-*} 11 } */
index c77403d..30ed58f 100644 (file)
@@ -8,5 +8,6 @@ int x, y;
 void
 foo (void)
 {
-  (x, y) = 1; /* { dg-warning "lvalue" "compound expression as lvalue deprecated" } */
+  (x, y) = 1; /* { dg-bogus "warning" "warning in place of error" } */
 }
+/* { dg-error "lvalue" "compound expression as lvalue" { target *-*-* } 11 } */
index 1765546..f2605af 100644 (file)
@@ -8,5 +8,6 @@ int x, y, z;
 void
 foo (void)
 {
-  (x ? y : z) = 1; /* { dg-warning "lvalue" "conditional expression as lvalue deprecated" } */
+  (x ? y : z) = 1; /* { dg-bogus "warning" "warning in place of error" } */
 }
+/* { dg-error "lvalue" "conditional expression as lvalue" { target *-*-* } 11 } */
index 5220227..29f809c 100644 (file)
@@ -58,7 +58,6 @@ foo (int a, int b, int n, int p, int *ptr, struct s *sptr,
   b = a, a = a++; /* { dg-warning "undefined" "sequence point warning" } */
   a = (b++ ? n : a) + b; /* { dg-warning "undefined" "sequence point warning" { xfail *-*-* } } */
   b ? a = a++ : a; /* { dg-warning "undefined" "sequence point warning" } */
-  b ? a : a = a++; /* { dg-warning "undefined" "sequence point warning" } */
   b && (a = a++); /* { dg-warning "undefined" "sequence point warning" } */
   (a = a++) && b; /* { dg-warning "undefined" "sequence point warning" } */
   b, (a = a++); /* { dg-warning "undefined" "sequence point warning" } */