tree.c (lvalue_p_1): Add argument for whether casts of lvalues are allowable.
2002-08-24 Matt Austern <austern@apple.com> * 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 <austern@apple.com> * g++.dg/ext/lvaddr.C: New test. * g++.dg/ext/lvcast.C: New test. From-SVN: r56560
This commit is contained in:
parent
d241f75b96
commit
13d3f0b659
@ -1,3 +1,13 @@
|
||||
2002-08-24 Matt Austern <austern@apple.com>
|
||||
|
||||
* 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 <mark@codesourcery.com>
|
||||
|
||||
* typeck.c (build_class_member_access_expr): Handle COMPOUND_EXPR
|
||||
|
@ -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, ...));
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -1,3 +1,8 @@
|
||||
2002-08-24 Matt Austern <austern@apple.com>
|
||||
|
||||
* g++.dg/ext/lvaddr.C: New test.
|
||||
* g++.dg/ext/lvcast.C: New test.
|
||||
|
||||
2002-08-22 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* testsuite/g++.dg/inherit/cond1.C: New test.
|
||||
|
10
gcc/testsuite/g++.dg/ext/lvaddr.C
Normal file
10
gcc/testsuite/g++.dg/ext/lvaddr.C
Normal file
@ -0,0 +1,10 @@
|
||||
// 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" }
|
||||
}
|
11
gcc/testsuite/g++.dg/ext/lvcast.C
Normal file
11
gcc/testsuite/g++.dg/ext/lvcast.C
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright (C) 2002 Free Software Foundation
|
||||
// Contributed by Matt Austern <austern@apple.com>
|
||||
|
||||
// { dg-do compile }
|
||||
// { dg-options -fpermissive }
|
||||
|
||||
void f ()
|
||||
{
|
||||
int n;
|
||||
(char) n = 1;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user