From 13d3f0b659c7db21e006e8d2894c93707a95583d Mon Sep 17 00:00:00 2001 From: Matt Austern Date: Sun, 25 Aug 2002 04:57:16 +0000 Subject: [PATCH] tree.c (lvalue_p_1): Add argument for whether casts of lvalues are allowable. 2002-08-24 Matt Austern * 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 * g++.dg/ext/lvaddr.C: New test. * g++.dg/ext/lvcast.C: New test. From-SVN: r56560 --- gcc/cp/ChangeLog | 10 +++++ gcc/cp/cp-tree.h | 1 + gcc/cp/tree.c | 63 +++++++++++++++++++++++-------- gcc/cp/typeck.c | 2 +- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/ext/lvaddr.C | 10 +++++ gcc/testsuite/g++.dg/ext/lvcast.C | 11 ++++++ 7 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/lvaddr.C create mode 100644 gcc/testsuite/g++.dg/ext/lvcast.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cb95b6d33b7..def395ea126 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2002-08-24 Matt Austern + + * 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 * typeck.c (build_class_member_access_expr): Handle COMPOUND_EXPR diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 44a52fc8e78..ef4f171829b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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, ...)); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 36305660372..6e092850762 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 624b379cf71..8535cde4ae7 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 00a92134d45..f509299f6e5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2002-08-24 Matt Austern + + * g++.dg/ext/lvaddr.C: New test. + * g++.dg/ext/lvcast.C: New test. + 2002-08-22 Mark Mitchell * 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 index 00000000000..184afce900b --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/lvaddr.C @@ -0,0 +1,10 @@ +// Copyright (C) 2002 Free Software Foundation +// Contributed by Matt Austern + +// { 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 index 00000000000..efff04ec089 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/lvcast.C @@ -0,0 +1,11 @@ +// Copyright (C) 2002 Free Software Foundation +// Contributed by Matt Austern + +// { dg-do compile } +// { dg-options -fpermissive } + +void f () +{ + int n; + (char) n = 1; +} -- 2.30.2