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:
parent
85ccbba3d7
commit
69851283e8
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
148
gcc/cp/tree.c
148
gcc/cp/tree.c
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Build don't link:
|
||||
|
||||
void f ();
|
||||
void (&fr)() = f; // gets bogus error - references to functions XFAIL *-*-*
|
||||
void (&fr)() = f;
|
||||
|
|
|
@ -11,7 +11,7 @@ int f() { return 1; }
|
|||
|
||||
int main()
|
||||
{
|
||||
int (&fr)() = f; // g++ cannot compile it
|
||||
int (&fr)() = f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue