This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

generalized lvalues -- patch outline


On 19 Nov 2004, at 17.50, Ziemowit Laski wrote:

To put it another way, I'm only concerned with cases where the compiler currently complains
about assigning to a non-lvalue, and the non-lvalue in question is a cast of an lvalue.

Indeed, I now appear to have a mainline mod for C and C++ which allows assignment to lvalue casts for pointer types. What follows is a high-level synopsis of what I did; if there is interest, I can whip up a full-fledged patch, complete with docs. Please let me know.


Thanks,

--Zem

------

The lvalue cast assignment/increment/decrement can be enabled with the -flvalue-cast-assign flag (which is off by default).

The active ingredient of the C patch is:

Index: gcc/c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.400
diff -u -3 -p -r1.400 c-typeck.c
--- gcc/c-typeck.c      20 Nov 2004 20:31:43 -0000      1.400
+++ gcc/c-typeck.c      22 Nov 2004 20:32:00 -0000
@@ -2724,6 +2724,16 @@ lvalue_or_else (tree ref, enum lvalue_us
 {
   int win = lvalue_p (ref);

+ /* If -flvalue-cast-assignment is specified, we shall allow assignments
+ (including increment/decrement) to casts of lvalues, as long as
+ both the lvalue and the cast are pointers. */
+ if (!win && flag_lvalue_cast_assign
+ && TREE_CODE (ref) == NOP_EXPR
+ && (use == lv_assign || use == lv_increment || use == lv_decrement)
+ && TREE_CODE (TREE_TYPE (ref)) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == POINTER_TYPE)
+ win = lvalue_p (TREE_OPERAND (ref, 0));
+
if (!win)
{
switch (use)


and will allow code as follows:

Index: gcc/testsuite/gcc.dg/lvalue-cast-1.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/lvalue-cast-1.c
diff -N gcc/testsuite/gcc.dg/lvalue-cast-1.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/lvalue-cast-1.c 22 Nov 2004 20:32:50 -0000
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-flvalue-cast-assign" } */
+
+int foo(void) {
+
+ char *p;
+ long l;
+ short s;
+
+ (long *)p = &l; /* ok */
+ ((long *)p)++; /* ok */
+ (short)l = 2; /* { dg-error "non-lvalue" } */
+ (long)s = 3; /* { dg-error "non-lvalue" } */
+
+ return 0;
+}


Note that we're still erroring out on the non-pointer types, though that too can be changed. FWIW, Microsoft's C compiler also allows the '(short)l = 2' (though not the '(long)s = 3').

The C++ side of things is very similar:

Index: gcc/cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.419
diff -u -3 -p -r1.419 tree.c
--- gcc/cp/tree.c 12 Nov 2004 21:47:09 -0000 1.419
+++ gcc/cp/tree.c 22 Nov 2004 20:34:50 -0000
@@ -223,6 +223,17 @@ lvalue_or_else (tree ref, const char* st
{
if (!lvalue_p (ref))
{
+ /* If -flvalue-cast-assignment is specified, we shall allow assignments
+ (including increment/decrement) to casts of lvalues, as long as
+ both the lvalue and the cast are pointers. */
+ if (flag_lvalue_cast_assign
+ && TREE_CODE (ref) == NOP_EXPR
+ && string && string[0] == 'a'
+ && TREE_CODE (TREE_TYPE (ref)) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == POINTER_TYPE
+ && lvalue_p (TREE_OPERAND (ref, 0)))
+ return 1;
+
error ("non-lvalue in %s", string);
return 0;
}


although we clearly could use an 'enum lvalue_use' here as well. At any rate, this patch causes the following to compile and run successfully:

Index: gcc/testsuite/g++.dg/ext/lvalue-cast-1.cpp
===================================================================
RCS file: gcc/testsuite/g++.dg/ext/lvalue-cast-1.cpp
diff -N gcc/testsuite/g++.dg/ext/lvalue-cast-1.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/g++.dg/ext/lvalue-cast-1.cpp 22 Nov 2004 20:36:43 -0000
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-options "-flvalue-cast-assign" } */
+
+#include <stdlib.h>
+#define CHECK_IF(expr) if (!(expr)) abort ()
+
+static int global;
+
+void f(int &) { global = 35; }
+void f(const int &) { global = 78; }
+
+long long_arr[2];
+
+int main(void) {
+
+ char *p;
+
+ (long *)p = long_arr;
+ ((long *)p)++;
+ *(long *)p = -1;
+ *p = -2;
+ CHECK_IF(p[-1] == 0 && p[0] == -2 && p[1] == -1);
+
+ long x = 0;
+ f((int)x);
+ CHECK_IF(global == 78);
+
+ return 0;
+}


The rest of the patch (not shown) deals with defining/handling of the -flvalue-cast-assign flag.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]