aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@markmitchell.com>1998-09-24 23:53:37 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1998-09-24 23:53:37 +0000
commit69851283e8a56a7cfdf40f566dcaae2331840a51 (patch)
tree736e0a7d64b731293e53ed1d5b1cfe97e9274412
parent85ccbba3d72e6025398f487c4a948b192a2fdf8c (diff)
downloadgcc-69851283e8a56a7cfdf40f566dcaae2331840a51.zip
gcc-69851283e8a56a7cfdf40f566dcaae2331840a51.tar.gz
gcc-69851283e8a56a7cfdf40f566dcaae2331840a51.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c14
-rw-r--r--gcc/cp/tree.c148
-rw-r--r--gcc/cp/typeck.c12
-rw-r--r--gcc/cp/typeck2.c4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900519_05.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/ref4.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/arm2.C2
9 files changed, 77 insertions, 123 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 26aad5f7..548bed8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1f4bc0e..d77bb82 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index a8317cc..87a391f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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)
{
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 41475b5..1a87a51 100644
--- a/gcc/cp/tree.c
+++ b/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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 6fc3707..7248175 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 265b387..a00a4f1 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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);
}
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900519_05.C b/gcc/testsuite/g++.old-deja/g++.bugs/900519_05.C
index 05d2ea0..9a2a4cf 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900519_05.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900519_05.C
@@ -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; }
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/ref4.C b/gcc/testsuite/g++.old-deja/g++.jason/ref4.C
index 422c58c..5c62d6a 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/ref4.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/ref4.C
@@ -1,4 +1,4 @@
// Build don't link:
void f ();
-void (&fr)() = f; // gets bogus error - references to functions XFAIL *-*-*
+void (&fr)() = f;
diff --git a/gcc/testsuite/g++.old-deja/g++.law/arm2.C b/gcc/testsuite/g++.old-deja/g++.law/arm2.C
index de8fe42..d2f43d7 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/arm2.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/arm2.C
@@ -11,7 +11,7 @@ int f() { return 1; }
int main()
{
- int (&fr)() = f; // g++ cannot compile it
+ int (&fr)() = f;
return 0;
}