This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
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.