Skip to content

Commit

Permalink
PR c++/36334
Browse files Browse the repository at this point in the history
        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.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@143404 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information
jason committed Jan 15, 2009
1 parent c2bfeae commit db9317c
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 12 deletions.
10 changes: 10 additions & 0 deletions gcc/cp/ChangeLog
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 3 additions & 3 deletions gcc/cp/cp-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, ...);
Expand Down Expand Up @@ -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);
Expand Down
24 changes: 16 additions & 8 deletions gcc/cp/tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion gcc/cp/typeck.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
8 changes: 8 additions & 0 deletions gcc/testsuite/ChangeLog
Original file line number Diff line number Diff line change
@@ -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
Expand Down
26 changes: 26 additions & 0 deletions gcc/testsuite/g++.dg/conversion/memfn1.C
Original file line number Diff line number Diff line change
@@ -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;
}
11 changes: 11 additions & 0 deletions gcc/testsuite/g++.dg/conversion/memfn2.C
Original file line number Diff line number Diff line change
@@ -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" }
}
};

0 comments on commit db9317c

Please sign in to comment.