This is the mail archive of the gcc-patches@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]

Re: Ping: PATCH to generate error for address of cast


On Tuesday, August 20, 2002, at 02:52 PM, Jason Merrill wrote:

On Tue, 20 Aug 2002 10:57:27 -0700, Matt Austern <austern@apple.com> wrote:

My proposed solution: add new functions, non_cast_lvalue_p and
non_cast_lvalue_or_else, in the C++ front end only.  Annoying and
none too pretty, but I don't see a better alternative.
Seems like a reasonable interim solution.
OK! Here's my latest version, then.

--Matt

* gcc/cp/cp-tree.h, gcc/cp/tree.c: Introduced new functions
non_cast_lvalue_p and non_cast_lvalue_or_else. Same as
lvalue_p and lvalue_or_else except that they don't
treat casts as lvalues. (cast-as-lvalue is a GNU extension.)
* gcc/cp/typeck.c: Emit an error message for address of cast.

bash-2.05$ cvs diff -u
? gcc/testsuite/g++.dg/ext/lvaddr.C
? gcc/testsuite/g++.dg/ext/lvcast.C
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.744
diff -u -r1.744 cp-tree.h
--- gcc/cp/cp-tree.h 9 Aug 2002 19:57:00 -0000 1.744
+++ gcc/cp/cp-tree.h 20 Aug 2002 21:43:37 -0000
@@ -4184,6 +4184,8 @@
extern void unshare_base_binfos PARAMS ((tree));
extern int member_p PARAMS ((tree));
extern cp_lvalue_kind real_lvalue_p PARAMS ((tree));
+extern cp_lvalue_kind non_cast_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: gcc/cp/tree.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.295
diff -u -r1.295 tree.c
--- gcc/cp/tree.c 11 Aug 2002 16:05:27 -0000 1.295
+++ gcc/cp/tree.c 20 Aug 2002 21:43:37 -0000
@@ -39,7 +39,7 @@
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 @@
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 @@
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 @@
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 @@

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,9 +214,20 @@
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 cast expressions are not
+ considered lvalues. (cast-as-lvalue is a GNU extension) */
+
+cp_lvalue_kind
+non_cast_lvalue_p (ref)
+ tree ref;
+{
+ return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/ 0, /*cast*/ 0);
+}
+
+
/* This differs from real_lvalue_p in that class rvalues are
considered lvalues. */

@@ -207,7 +236,7 @@
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 +247,20 @@
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: gcc/cp/typeck.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.423
diff -u -r1.423 typeck.c
--- gcc/cp/typeck.c 17 Aug 2002 12:26:01 -0000 1.423
+++ gcc/cp/typeck.c 20 Aug 2002 21:43:37 -0000
@@ -4247,7 +4247,7 @@
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)
bash-2.05$ cat gcc/testsuite/g++.dg/ext/lvaddr.C
// 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" }
}
bash-2.05$ cat gcc/testsuite/g++.dg/ext/lvcast.C
// Copyright (C) 2002 Free Software Foundation
// Contributed by Matt Austern <austern@apple.com>

// { dg-do compile }
// { dg-options -fpermissive }

void f()
{
int n;
static_cast<char>(n) = 0;
(char) n = 1;
}
bash-2.05$


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