aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-01-15 13:14:32 -0500
committerJason Merrill <jason@gcc.gnu.org>2009-01-15 13:14:32 -0500
commit4af9e878d91689da977b1e31fbb3248b5ad677b9 (patch)
tree813a681559b4e930c5f836452d80f24baae41519 /gcc
parentf1253e7e69d20a489bb734ea66d0702e9eaa4b76 (diff)
downloadgcc-4af9e878d91689da977b1e31fbb3248b5ad677b9.zip
gcc-4af9e878d91689da977b1e31fbb3248b5ad677b9.tar.gz
gcc-4af9e878d91689da977b1e31fbb3248b5ad677b9.tar.bz2
re PR c++/36334 (typedef to function type leads to problems)
PR c++/36334 PR c++/37646 * tree.c (lvalue_p_1): Handle BASELINK. A COMPONENT_REF to a function isn't necessarily an lvalue. Take tree, not const_tree. (lvalue_p, real_lvalue_p): Take tree, not const_tree. * typeck.c (lvalue_or_else): Likewise. * cp-tree.h: Adjust prototypes. From-SVN: r143404
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/cp-tree.h6
-rw-r--r--gcc/cp/tree.c24
-rw-r--r--gcc/cp/typeck.c2
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/conversion/memfn1.C26
-rw-r--r--gcc/testsuite/g++.dg/conversion/memfn2.C11
7 files changed, 75 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index af7f0c0..4b23d31 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2009-01-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/36334
+ PR c++/37646
+ * tree.c (lvalue_p_1): Handle BASELINK. A COMPONENT_REF to
+ a function isn't necessarily an lvalue. Take tree, not const_tree.
+ (lvalue_p, real_lvalue_p): Take tree, not const_tree.
+ * typeck.c (lvalue_or_else): Likewise.
+ * cp-tree.h: Adjust prototypes.
+
2009-01-15 Steve Ellcey <sje@cup.hp.com>
PR c++/38357
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 718167f..186ec9a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4836,7 +4836,7 @@ extern tree canonical_type_variant (tree);
extern tree copy_binfo (tree, tree, tree,
tree *, int);
extern int member_p (const_tree);
-extern cp_lvalue_kind real_lvalue_p (const_tree);
+extern cp_lvalue_kind real_lvalue_p (tree);
extern bool builtin_valid_in_constant_expr_p (const_tree);
extern tree build_min (enum tree_code, tree, ...);
extern tree build_min_nt (enum tree_code, ...);
@@ -4984,9 +4984,9 @@ extern tree lookup_anon_field (tree, tree);
extern bool invalid_nonstatic_memfn_p (const_tree, tsubst_flags_t);
extern tree convert_member_func_to_ptr (tree, tree);
extern tree convert_ptrmem (tree, tree, bool, bool);
-extern int lvalue_or_else (const_tree, enum lvalue_use,
+extern int lvalue_or_else (tree, enum lvalue_use,
tsubst_flags_t);
-extern int lvalue_p (const_tree);
+extern int lvalue_p (tree);
/* in typeck2.c */
extern void require_complete_eh_spec_types (tree, tree);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8ac2720..3347bfb 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -44,7 +44,7 @@ static tree build_cplus_array_type_1 (tree, tree);
static int list_hash_eq (const void *, const void *);
static hashval_t list_hash_pieces (tree, tree, tree);
static hashval_t list_hash (const void *);
-static cp_lvalue_kind lvalue_p_1 (const_tree, int);
+static cp_lvalue_kind lvalue_p_1 (tree, int);
static tree build_target_expr (tree, tree);
static tree count_trees_r (tree *, int *, void *);
static tree verify_stmt_tree_r (tree *, int *, void *);
@@ -59,7 +59,7 @@ static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
nonzero, rvalues of class type are considered lvalues. */
static cp_lvalue_kind
-lvalue_p_1 (const_tree ref,
+lvalue_p_1 (tree ref,
int treat_class_rvalues_as_lvalues)
{
cp_lvalue_kind op1_lvalue_kind = clk_none;
@@ -110,11 +110,13 @@ lvalue_p_1 (const_tree ref,
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues);
/* Look at the member designator. */
- if (!op1_lvalue_kind
- /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
- situations. */
- || TREE_CODE (TREE_OPERAND (ref, 1)) != FIELD_DECL)
+ if (!op1_lvalue_kind)
;
+ else if (is_overloaded_fn (TREE_OPERAND (ref, 1)))
+ /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
+ situations. */
+ op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues);
else if (DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
{
/* Clear the ordinary bit. If this object was a class
@@ -195,6 +197,12 @@ lvalue_p_1 (const_tree ref,
return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
? clk_none : clk_ordinary);
+ case BASELINK:
+ /* We now represent a reference to a single static member function
+ with a BASELINK. */
+ return lvalue_p_1 (BASELINK_FUNCTIONS (ref),
+ treat_class_rvalues_as_lvalues);
+
case NON_DEPENDENT_EXPR:
/* We must consider NON_DEPENDENT_EXPRs to be lvalues so that
things like "&E" where "E" is an expression with a
@@ -227,7 +235,7 @@ lvalue_p_1 (const_tree ref,
computes the C++ definition of lvalue. */
cp_lvalue_kind
-real_lvalue_p (const_tree ref)
+real_lvalue_p (tree ref)
{
return lvalue_p_1 (ref,
/*treat_class_rvalues_as_lvalues=*/0);
@@ -237,7 +245,7 @@ real_lvalue_p (const_tree ref)
considered lvalues. */
int
-lvalue_p (const_tree ref)
+lvalue_p (tree ref)
{
return
(lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 3c7787c..415b8a2 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -7339,7 +7339,7 @@ non_reference (tree t)
how the lvalue is being used and so selects the error message. */
int
-lvalue_or_else (const_tree ref, enum lvalue_use use, tsubst_flags_t complain)
+lvalue_or_else (tree ref, enum lvalue_use use, tsubst_flags_t complain)
{
int win = lvalue_p (ref);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f7c4833..198ba97 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2009-01-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/36334
+ * g++.dg/conversion/memfn1.C: New test.
+
+ PR c++/37646
+ * g++.dg/conversion/memfn2.C: New test.
+
2008-01-15 Steve Ellcey <sje@cup.hp.com>
PR c++/38357
diff --git a/gcc/testsuite/g++.dg/conversion/memfn1.C b/gcc/testsuite/g++.dg/conversion/memfn1.C
new file mode 100644
index 0000000..da2fb0f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/memfn1.C
@@ -0,0 +1,26 @@
+// PR c++/36334
+
+struct X
+{
+ typedef int* foobar();
+ static void foo(foobar&);
+};
+
+void X::foo(foobar&)
+{
+}
+
+struct Y : public X
+{
+ static foobar bar;
+ static void foo();
+};
+
+void Y::foo()
+{
+ X::foo(bar);
+}
+int* Y::bar()
+{
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/conversion/memfn2.C b/gcc/testsuite/g++.dg/conversion/memfn2.C
new file mode 100644
index 0000000..c3d7613
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/memfn2.C
@@ -0,0 +1,11 @@
+// PR c++/37646
+
+struct A
+{
+ void foo();
+
+ void bar(int i)
+ {
+ void (*p)() = i ? foo : foo; // { dg-error "invalid use of member" }
+ }
+};