This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/36334 and 37646


Two different bugs where lvalue_p wasn't handling member function names properly, at least one fallout from the fix for 28588 when we started using BASELINKs for a reference to a static member function.

To fix this I needed to revert the const_tree changes for the lvalue_p family of functions, since the BASELINK_FUNCTIONS macro isn't const-correct.

Tested x86_64-pc-linux-gnu, applied to trunk.
2009-01-14  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.
	* g++.dg/conversion/memfn1.C: New test.
	* g++.dg/conversion/memfn2.C: New test.

Index: cp/typeck.c
===================================================================
*** cp/typeck.c	(revision 143386)
--- cp/typeck.c	(working copy)
*************** non_reference (tree t)
*** 7339,7345 ****
     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)
  {
    int win = lvalue_p (ref);
  
--- 7339,7345 ----
     how the lvalue is being used and so selects the error message.  */
  
  int
! lvalue_or_else (tree ref, enum lvalue_use use, tsubst_flags_t complain)
  {
    int win = lvalue_p (ref);
  
Index: cp/tree.c
===================================================================
*** cp/tree.c	(revision 143386)
--- cp/tree.c	(working copy)
*************** static tree build_cplus_array_type_1 (tr
*** 44,50 ****
  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 tree build_target_expr (tree, tree);
  static tree count_trees_r (tree *, int *, void *);
  static tree verify_stmt_tree_r (tree *, int *, void *);
--- 44,50 ----
  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 (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 *);
*************** static tree handle_init_priority_attribu
*** 59,65 ****
     nonzero, rvalues of class type are considered lvalues.  */
  
  static cp_lvalue_kind
! lvalue_p_1 (const_tree ref,
  	    int treat_class_rvalues_as_lvalues)
  {
    cp_lvalue_kind op1_lvalue_kind = clk_none;
--- 59,65 ----
     nonzero, rvalues of class type are considered lvalues.  */
  
  static cp_lvalue_kind
! lvalue_p_1 (tree ref,
  	    int treat_class_rvalues_as_lvalues)
  {
    cp_lvalue_kind op1_lvalue_kind = clk_none;
*************** lvalue_p_1 (const_tree ref,
*** 110,120 ****
        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)
  	;
        else if (DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
  	{
  	  /* Clear the ordinary bit.  If this object was a class
--- 110,122 ----
        op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
  				    treat_class_rvalues_as_lvalues);
        /* Look at the member designator.  */
!       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
*************** lvalue_p_1 (const_tree ref,
*** 195,200 ****
--- 197,208 ----
        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
*************** lvalue_p_1 (const_tree ref,
*** 227,233 ****
     computes the C++ definition of lvalue.  */
  
  cp_lvalue_kind
! real_lvalue_p (const_tree ref)
  {
    return lvalue_p_1 (ref,
  		     /*treat_class_rvalues_as_lvalues=*/0);
--- 235,241 ----
     computes the C++ definition of lvalue.  */
  
  cp_lvalue_kind
! real_lvalue_p (tree ref)
  {
    return lvalue_p_1 (ref,
  		     /*treat_class_rvalues_as_lvalues=*/0);
*************** real_lvalue_p (const_tree ref)
*** 237,243 ****
     considered lvalues.  */
  
  int
! lvalue_p (const_tree ref)
  {
    return
      (lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none);
--- 245,251 ----
     considered lvalues.  */
  
  int
! lvalue_p (tree ref)
  {
    return
      (lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none);
Index: cp/cp-tree.h
===================================================================
*** cp/cp-tree.h	(revision 143386)
--- cp/cp-tree.h	(working copy)
*************** extern tree canonical_type_variant		(tre
*** 4836,4842 ****
  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 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, ...);
--- 4836,4842 ----
  extern tree copy_binfo				(tree, tree, tree,
  						 tree *, int);
  extern int member_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, ...);
*************** extern tree lookup_anon_field			(tree, t
*** 4984,4992 ****
  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,
                                                   tsubst_flags_t);
! extern int lvalue_p				(const_tree);
  
  /* in typeck2.c */
  extern void require_complete_eh_spec_types	(tree, tree);
--- 4984,4992 ----
  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			(tree, enum lvalue_use,
                                                   tsubst_flags_t);
! extern int lvalue_p				(tree);
  
  /* in typeck2.c */
  extern void require_complete_eh_spec_types	(tree, tree);
Index: testsuite/g++.dg/conversion/memfn1.C
===================================================================
*** testsuite/g++.dg/conversion/memfn1.C	(revision 0)
--- testsuite/g++.dg/conversion/memfn1.C	(revision 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;
+ }
Index: testsuite/g++.dg/conversion/memfn2.C
===================================================================
*** testsuite/g++.dg/conversion/memfn2.C	(revision 0)
--- testsuite/g++.dg/conversion/memfn2.C	(revision 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" }
+   }
+ };

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]