From 4af9e878d91689da977b1e31fbb3248b5ad677b9 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 15 Jan 2009 13:14:32 -0500 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 10 +++++++++ gcc/cp/cp-tree.h | 6 +++--- gcc/cp/tree.c | 24 ++++++++++++++-------- gcc/cp/typeck.c | 2 +- gcc/testsuite/ChangeLog | 8 ++++++++ gcc/testsuite/g++.dg/conversion/memfn1.C | 26 ++++++++++++++++++++++++ gcc/testsuite/g++.dg/conversion/memfn2.C | 11 ++++++++++ 7 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/conversion/memfn1.C create mode 100644 gcc/testsuite/g++.dg/conversion/memfn2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index af7f0c06b9e..4b23d319363 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2009-01-15 Jason Merrill + + 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 PR c++/38357 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 718167f0160..186ec9ab6ad 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 8ac272095be..3347bfb9f0b 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 3c7787c675c..415b8a26291 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 f7c483320c6..198ba977e5b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2009-01-15 Jason Merrill + + 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 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 00000000000..da2fb0fadee --- /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 00000000000..c3d76133dbd --- /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" } + } +}; -- 2.30.2