Commit 13d3f0b6 by Matt Austern Committed by Stan Shebs

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
parent d241f75b
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> 2002-08-22 Mark Mitchell <mark@codesourcery.com>
* typeck.c (build_class_member_access_expr): Handle COMPOUND_EXPR * typeck.c (build_class_member_access_expr): Handle COMPOUND_EXPR
......
...@@ -4184,6 +4184,7 @@ extern tree canonical_type_variant PARAMS ((tree)); ...@@ -4184,6 +4184,7 @@ extern tree canonical_type_variant PARAMS ((tree));
extern void unshare_base_binfos PARAMS ((tree)); extern void unshare_base_binfos PARAMS ((tree));
extern int member_p PARAMS ((tree)); extern int member_p PARAMS ((tree));
extern cp_lvalue_kind real_lvalue_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 PARAMS ((enum tree_code, tree,
...)); ...));
extern tree build_min_nt PARAMS ((enum tree_code, ...)); extern tree build_min_nt PARAMS ((enum tree_code, ...));
......
...@@ -39,7 +39,7 @@ static tree build_cplus_array_type_1 PARAMS ((tree, tree)); ...@@ -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 int list_hash_eq PARAMS ((const void *, const void *));
static hashval_t list_hash_pieces PARAMS ((tree, tree, tree)); static hashval_t list_hash_pieces PARAMS ((tree, tree, tree));
static hashval_t list_hash PARAMS ((const void *)); 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 no_linkage_helper PARAMS ((tree *, int *, void *));
static tree build_srcloc PARAMS ((const char *, int)); static tree build_srcloc PARAMS ((const char *, int));
static tree mark_local_for_remap_r PARAMS ((tree *, int *, void *)); 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 ...@@ -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. */ non-zero, rvalues of class type are considered lvalues. */
static cp_lvalue_kind 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; tree ref;
int treat_class_rvalues_as_lvalues; int treat_class_rvalues_as_lvalues;
int allow_cast_as_lvalue;
{ {
cp_lvalue_kind op1_lvalue_kind = clk_none; cp_lvalue_kind op1_lvalue_kind = clk_none;
cp_lvalue_kind op2_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) ...@@ -84,16 +85,28 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case WITH_CLEANUP_EXPR: case WITH_CLEANUP_EXPR:
case REALPART_EXPR: case REALPART_EXPR:
case IMAGPART_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), 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: case COMPONENT_REF:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0), 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 if (op1_lvalue_kind
/* The "field" can be a FUNCTION_DECL or an OVERLOAD in some /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
situations. */ situations. */
...@@ -134,16 +147,20 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) ...@@ -134,16 +147,20 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case MAX_EXPR: case MAX_EXPR:
case MIN_EXPR: case MIN_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0), 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), 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; break;
case COND_EXPR: case COND_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1), 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), 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; break;
case MODIFY_EXPR: case MODIFY_EXPR:
...@@ -151,7 +168,8 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) ...@@ -151,7 +168,8 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case COMPOUND_EXPR: case COMPOUND_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 1), 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: case TARGET_EXPR:
return treat_class_rvalues_as_lvalues ? clk_class : clk_none; return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
...@@ -196,7 +214,7 @@ cp_lvalue_kind ...@@ -196,7 +214,7 @@ cp_lvalue_kind
real_lvalue_p (ref) real_lvalue_p (ref)
tree 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 /* This differs from real_lvalue_p in that class rvalues are
...@@ -207,7 +225,7 @@ lvalue_p (ref) ...@@ -207,7 +225,7 @@ lvalue_p (ref)
tree ref; tree ref;
{ {
return 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; /* Return nonzero if REF is an lvalue valid for this language;
...@@ -218,7 +236,20 @@ lvalue_or_else (ref, string) ...@@ -218,7 +236,20 @@ lvalue_or_else (ref, string)
tree ref; tree ref;
const char *string; 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) if (! win)
error ("non-lvalue in %s", string); error ("non-lvalue in %s", string);
return win; return win;
......
...@@ -4268,7 +4268,7 @@ build_unary_op (code, xarg, noconvert) ...@@ -4268,7 +4268,7 @@ build_unary_op (code, xarg, noconvert)
is an error. */ is an error. */
else if (TREE_CODE (argtype) != FUNCTION_TYPE else if (TREE_CODE (argtype) != FUNCTION_TYPE
&& TREE_CODE (argtype) != METHOD_TYPE && TREE_CODE (argtype) != METHOD_TYPE
&& !lvalue_or_else (arg, "unary `&'")) && !non_cast_lvalue_or_else (arg, "unary `&'"))
return error_mark_node; return error_mark_node;
if (argtype != error_mark_node) if (argtype != error_mark_node)
......
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> 2002-08-22 Mark Mitchell <mark@codesourcery.com>
* testsuite/g++.dg/inherit/cond1.C: New test. * testsuite/g++.dg/inherit/cond1.C: New test.
......
// 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" }
}
// 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment