cp-tree.h (language_lvalue_valid): Remove.

* cp-tree.h (language_lvalue_valid): Remove.
	* decl.c (grokdeclarator): Don't disallow references to functions.
	* tree.c (lvalue_p_1): New function, combining duplicated
	code from ...
	(lvalue_p): Use it.
	(real_lvalue_p): Likewise.
	* typeck.c (language_lvalue_valid): Remove.
	(build_modify_expr): Treat FUNCTION_TYPEs as readonly, even though
	they don't have TREE_READONLY set.
	* typeck2.c (readonly_error): Add case for FUNCTION_DECLs.

From-SVN: r22583
This commit is contained in:
Mark Mitchell 1998-09-24 23:53:37 +00:00 committed by Mark Mitchell
parent 85ccbba3d7
commit 69851283e8
9 changed files with 77 additions and 123 deletions

View File

@ -1,3 +1,16 @@
1998-09-24 Mark Mitchell <mark@markmitchell.com>
* cp-tree.h (language_lvalue_valid): Remove.
* decl.c (grokdeclarator): Don't disallow references to functions.
* tree.c (lvalue_p_1): New function, combining duplicated
code from ...
(lvalue_p): Use it.
(real_lvalue_p): Likewise.
* typeck.c (language_lvalue_valid): Remove.
(build_modify_expr): Treat FUNCTION_TYPEs as readonly, even though
they don't have TREE_READONLY set.
* typeck2.c (readonly_error): Add case for FUNCTION_DECLs.
1998-09-24 Benjamin Kosnik <bkoz@loony.cygnus.com>
* spew.c (yylex): Give diagnostic.

View File

@ -3101,7 +3101,6 @@ extern tree build_const_cast PROTO((tree, tree));
extern tree build_c_cast PROTO((tree, tree));
extern tree build_x_modify_expr PROTO((tree, enum tree_code, tree));
extern tree build_modify_expr PROTO((tree, enum tree_code, tree));
extern int language_lvalue_valid PROTO((tree));
extern void warn_for_assignment PROTO((char *, char *, char *, tree, int, int));
extern tree convert_for_initialization PROTO((tree, tree, tree, int, char *, tree, int));
extern void c_expand_asm_operands PROTO((tree, tree, tree, tree, int, char *, int));

View File

@ -9744,18 +9744,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else if (TREE_CODE (declarator) == ADDR_EXPR)
{
if (TREE_CODE (type) == FUNCTION_TYPE)
{
error ("cannot declare references to functions; use pointer to function instead");
type = build_pointer_type (type);
}
if (TREE_CODE (type) == VOID_TYPE)
error ("invalid type: `void &'");
else
{
if (TREE_CODE (type) == VOID_TYPE)
error ("invalid type: `void &'");
else
type = build_reference_type (type);
}
type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
{

View File

@ -40,20 +40,19 @@ static tree list_hash_lookup PROTO((int, int, int, int, tree, tree,
tree));
static void propagate_binfo_offsets PROTO((tree, tree));
static int avoid_overlap PROTO((tree, tree));
static int lvalue_p_1 PROTO((tree, int));
#define CEIL(x,y) (((x) + (y) - 1) / (y))
/* Return nonzero if REF is an lvalue valid for this language.
Lvalues can be assigned, unless they have TREE_READONLY.
Lvalues can have their address taken, unless they have DECL_REGISTER. */
/* Returns non-zero if REF is an lvalue. If
TREAT_CLASS_RVALUES_AS_LVALUES is non-zero, rvalues of class type
are considered lvalues. */
int
real_lvalue_p (ref)
static int
lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
tree ref;
int treat_class_rvalues_as_lvalues;
{
if (! language_lvalue_valid (ref))
return 0;
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
@ -71,7 +70,10 @@ real_lvalue_p (ref)
case UNSAVE_EXPR:
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
return real_lvalue_p (TREE_OPERAND (ref, 0));
case REALPART_EXPR:
case IMAGPART_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues);
case STRING_CST:
return 1;
@ -85,7 +87,6 @@ real_lvalue_p (ref)
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
case ERROR_MARK:
if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1;
@ -97,24 +98,43 @@ real_lvalue_p (ref)
case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1;
return real_lvalue_p (TREE_OPERAND (ref, 0))
&& real_lvalue_p (TREE_OPERAND (ref, 1));
return (lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues)
&& lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues));
break;
case COND_EXPR:
return (real_lvalue_p (TREE_OPERAND (ref, 1))
&& real_lvalue_p (TREE_OPERAND (ref, 2)));
return (lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues)
&& lvalue_p_1 (TREE_OPERAND (ref, 2),
treat_class_rvalues_as_lvalues));
case MODIFY_EXPR:
return 1;
case COMPOUND_EXPR:
return real_lvalue_p (TREE_OPERAND (ref, 1));
return lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues);
case MAX_EXPR:
case MIN_EXPR:
return (real_lvalue_p (TREE_OPERAND (ref, 0))
&& real_lvalue_p (TREE_OPERAND (ref, 1)));
return (lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues)
&& lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues));
case TARGET_EXPR:
return treat_class_rvalues_as_lvalues;
case CALL_EXPR:
return (treat_class_rvalues_as_lvalues
&& IS_AGGR_TYPE (TREE_TYPE (ref)));
case FUNCTION_DECL:
/* All functions (except non-static-member functions) are
lvalues. */
return !DECL_NONSTATIC_MEMBER_FUNCTION_P (ref);
default:
break;
@ -123,92 +143,26 @@ real_lvalue_p (ref)
return 0;
}
/* Return nonzero if REF is an lvalue valid for this language.
Lvalues can be assigned, unless they have TREE_READONLY, or unless
they are FUNCTION_DECLs. Lvalues can have their address taken,
unless they have DECL_REGISTER. */
int
real_lvalue_p (ref)
tree ref;
{
return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
}
/* This differs from real_lvalue_p in that class rvalues are considered
lvalues. */
int
lvalue_p (ref)
tree ref;
{
if (! language_lvalue_valid (ref))
return 0;
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
if (ref == current_class_ptr && flag_this_is_variable <= 0)
return 0;
switch (TREE_CODE (ref))
{
/* preincrements and predecrements are valid lvals, provided
what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
case UNSAVE_EXPR:
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
return lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST:
return 1;
case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref))
return 0;
case INDIRECT_REF:
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
case ERROR_MARK:
if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1;
break;
case TARGET_EXPR:
return 1;
case CALL_EXPR:
if (IS_AGGR_TYPE (TREE_TYPE (ref)))
return 1;
break;
/* A currently unresolved scope ref. */
case SCOPE_REF:
my_friendly_abort (103);
case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1;
return lvalue_p (TREE_OPERAND (ref, 0))
&& lvalue_p (TREE_OPERAND (ref, 1));
break;
case COND_EXPR:
return (lvalue_p (TREE_OPERAND (ref, 1))
&& lvalue_p (TREE_OPERAND (ref, 2)));
case MODIFY_EXPR:
return 1;
case COMPOUND_EXPR:
return lvalue_p (TREE_OPERAND (ref, 1));
case MAX_EXPR:
case MIN_EXPR:
return (lvalue_p (TREE_OPERAND (ref, 0))
&& lvalue_p (TREE_OPERAND (ref, 1)));
default:
break;
}
return 0;
return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1);
}
/* Return nonzero if REF is an lvalue valid for this language;

View File

@ -6106,6 +6106,9 @@ build_modify_expr (lhs, modifycode, rhs)
&& (IS_SIGNATURE_POINTER (TREE_TYPE (TREE_OPERAND (lhs, 0)))
|| IS_SIGNATURE_REFERENCE (TREE_TYPE (TREE_OPERAND (lhs, 0)))))
&& (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
/* Functions are not modifiable, even though they are
lvalues. */
|| TREE_CODE (TREE_TYPE (lhs)) == FUNCTION_TYPE
|| ((TREE_CODE (lhstype) == RECORD_TYPE
|| TREE_CODE (lhstype) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (lhstype))
@ -6354,15 +6357,6 @@ build_x_modify_expr (lhs, modifycode, rhs)
return build_modify_expr (lhs, modifycode, rhs);
}
/* Return 0 if EXP is not a valid lvalue in this language
even though `lvalue_or_else' would accept it. */
int
language_lvalue_valid (exp)
tree exp ATTRIBUTE_UNUSED;
{
return 1;
}
/* Get difference in deltas for different pointer to member function
types. Return integer_zero_node, if FROM cannot be converted to a

View File

@ -118,7 +118,9 @@ readonly_error (arg, string, soft)
(*fn) ("%s of read-only reference `%D'", string, TREE_OPERAND (arg, 0));
else if (TREE_CODE (arg) == RESULT_DECL)
(*fn) ("%s of read-only named return value `%D'", string, arg);
else
else if (TREE_CODE (arg) == FUNCTION_DECL)
(*fn) ("%s of function `%D'", string, arg);
else
(*fn) ("%s of read-only location", string);
}

View File

@ -7,12 +7,12 @@
// keywords: function types, reference types
typedef void (func_type) (int, int);
typedef func_type& func_ref_type; // gets bogus error, XFAIL *-*-*
typedef func_type& func_ref_type;
void function (int arg1, int arg2)
{
}
func_type& global_func_ref1 = function; // gets bogus error, XFAIL *-*-*
func_type& global_func_ref1 = function;
int main () { return 0; }

View File

@ -1,4 +1,4 @@
// Build don't link:
void f ();
void (&fr)() = f; // gets bogus error - references to functions XFAIL *-*-*
void (&fr)() = f;

View File

@ -11,7 +11,7 @@ int f() { return 1; }
int main()
{
int (&fr)() = f; // g++ cannot compile it
int (&fr)() = f;
return 0;
}