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 3.4/4.0] Fix PR19311 (ICE overload resolution forpmf function argument)


Hi

These patches fix PR19311 regression in 3.4/4.0.  Function overloading
logic for pointer-to-member function argument fails to deal with
NON_DEPENDENT_EXPR and produces ICE.

The regression was caused by my work to build non-dependent SCOPE_REF.
The intention was to have enough type to catch invalid usage of pmf
during parsing rather than during instantiation.  The SCOPE_REF tree
was used to also allow access checking when the template is instantiated.
However access checking of non-dependent SCOPE_REF has been broken
for quite a long time (see PR16617).

The patches (one for 3.4, another for 4.0) build the target tree nodes
directly, by passing the SCOPE_REF.  Invalid use of pmf is still detected.
Access checking of non-dependent SCOPE_REF has been broken for quite
a long time (see PR16617) so there is no lost here.  The approach I am
pursuing for this problem (for 4.1) is to keep a list of nodes to check
when a template is instantiated.

The patch for 4.0 has one additional hunk for unary_complex_lvalue.
Otherwise they are the same.  Tested on i686-pc-linux-gnu.
OK for 3.4 and mainline?

--Kriang
***** Patch for mainline *****

2005-01-17  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/19311
	* init.c (build_offset_ref): Don't build non-dependent SCOPE_REF.
	* pt.c (build_non_dependent_expr): Don't build NON_DEPENDENT_EXPR
	for OFFSET_TYPE.
	* typeck.c (build_x_unary_op): Don't build non-dependent SCOPE_REF.
	Also set PTRMEM_OK_P for NON_DEPENDENT_EXPR.
	(unary_complex_lvalue): Return NULL_TREE only for type-dependent
	expression.

2005-01-17  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/19311
	* g++.dg/template/non-dependent11.C: New test.


diff -cprN gcc-main-save/gcc/cp/init.c gcc-main-new/gcc/cp/init.c
*** gcc-main-save/gcc/cp/init.c	Sat Jan  1 21:07:41 2005
--- gcc-main-new/gcc/cp/init.c	Sun Jan 16 22:57:10 2005
*************** build_offset_ref (tree type, tree name, 
*** 1417,1430 ****
        return error_mark_node;
      }
  
-   if (processing_template_decl)
-     {
-       if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
- 	return build_min (SCOPE_REF, TREE_TYPE (member), type, orig_name);
-       else
- 	return build_min (SCOPE_REF, TREE_TYPE (member), type, name);
-     }
- 
    if (TREE_CODE (member) == TYPE_DECL)
      {
        TREE_USED (member) = 1;
--- 1417,1422 ----
diff -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c	Mon Jan 10 22:13:46 2005
--- gcc-main-new/gcc/cp/pt.c	Sun Jan 16 22:57:56 2005
*************** build_non_dependent_expr (tree expr)
*** 12372,12378 ****
    if (TREE_CODE (inner_expr) == OVERLOAD 
        || TREE_CODE (inner_expr) == FUNCTION_DECL
        || TREE_CODE (inner_expr) == TEMPLATE_DECL
!       || TREE_CODE (inner_expr) == TEMPLATE_ID_EXPR)
      return expr;
    /* There is no need to return a proxy for a variable.  */
    if (TREE_CODE (expr) == VAR_DECL)
--- 12372,12379 ----
    if (TREE_CODE (inner_expr) == OVERLOAD 
        || TREE_CODE (inner_expr) == FUNCTION_DECL
        || TREE_CODE (inner_expr) == TEMPLATE_DECL
!       || TREE_CODE (inner_expr) == TEMPLATE_ID_EXPR
!       || TREE_CODE (inner_expr) == OFFSET_REF)
      return expr;
    /* There is no need to return a proxy for a variable.  */
    if (TREE_CODE (expr) == VAR_DECL)
diff -cprN gcc-main-save/gcc/cp/typeck.c gcc-main-new/gcc/cp/typeck.c
*** gcc-main-save/gcc/cp/typeck.c	Sat Jan  1 21:08:06 2005
--- gcc-main-new/gcc/cp/typeck.c	Sun Jan 16 22:59:55 2005
*************** build_x_unary_op (enum tree_code code, t
*** 3547,3569 ****
        if (type_dependent_expression_p (xarg))
  	return build_min_nt (code, xarg, NULL_TREE);
  
-       /* For non-dependent pointer-to-member, the SCOPE_REF will be
- 	 processed during template substitution.  Just compute the
- 	 right type here and build an ADDR_EXPR around it for
- 	 diagnostics.  */
-       if (code == ADDR_EXPR && TREE_CODE (xarg) == SCOPE_REF)
- 	{
- 	  tree type;
- 	  if (TREE_TYPE (xarg) == unknown_type_node)
- 	    type = unknown_type_node;
- 	  else if (TREE_CODE (TREE_TYPE (xarg)) == FUNCTION_TYPE)
- 	    type = build_pointer_type (TREE_TYPE (xarg));
- 	  else
- 	    type = build_ptrmem_type (TREE_OPERAND (xarg, 0),
- 				      TREE_TYPE (xarg));
- 	  return build_min (code, type, xarg, NULL_TREE);
- 	}
- 
        xarg = build_non_dependent_expr (xarg);
      }
  
--- 3547,3552 ----
*************** build_x_unary_op (enum tree_code code, t
*** 3627,3639 ****
        else if (TREE_CODE (xarg) == TARGET_EXPR)
  	warning ("taking address of temporary");
        exp = build_unary_op (ADDR_EXPR, xarg, 0);
-       if (TREE_CODE (exp) == ADDR_EXPR)
- 	PTRMEM_OK_P (exp) = ptrmem;
      }
  
    if (processing_template_decl && exp != error_mark_node)
!     return build_min_non_dep (code, exp, orig_expr,
! 			      /*For {PRE,POST}{INC,DEC}REMENT_EXPR*/NULL_TREE);
    return exp;
  }
  
--- 3610,3622 ----
        else if (TREE_CODE (xarg) == TARGET_EXPR)
  	warning ("taking address of temporary");
        exp = build_unary_op (ADDR_EXPR, xarg, 0);
      }
  
    if (processing_template_decl && exp != error_mark_node)
!     exp = build_min_non_dep (code, exp, orig_expr,
! 			     /*For {PRE,POST}{INC,DEC}REMENT_EXPR*/NULL_TREE);
!   if (TREE_CODE (exp) == ADDR_EXPR)
!     PTRMEM_OK_P (exp) = ptrmem;
    return exp;
  }
  
*************** tree
*** 4160,4168 ****
  unary_complex_lvalue (enum tree_code code, tree arg)
  {
    /* Inside a template, making these kinds of adjustments is
!      pointless; we are only concerned with the type of the
!      expression.  */
!   if (processing_template_decl)
      return NULL_TREE;
  
    /* Handle (a, b) used as an "lvalue".  */
--- 4143,4151 ----
  unary_complex_lvalue (enum tree_code code, tree arg)
  {
    /* Inside a template, making these kinds of adjustments is
!      pointless if it is still type dependent; we are only
!      concerned with the type of the expression.  */
!   if (type_dependent_expression_p (arg))
      return NULL_TREE;
  
    /* Handle (a, b) used as an "lvalue".  */
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/non-dependent11.C gcc-main-new/gcc/testsuite/g++.dg/template/non-dependent11.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/non-dependent11.C	Thu Jan  1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/non-dependent11.C	Sun Jan 16 23:04:04 2005
***************
*** 0 ****
--- 1,18 ----
+ // { dg-do compile }
+ 
+ // Origin: Jakub Jelinek <jakub@gcc.gnu.org>
+ //	   Wolfgang Bangerth <bangerth@ticam.utexas.edu>
+ 
+ // PR c++/19311: Non-dependent address to member as function argument.
+ 
+ template <class R, class T>          void foo (R (T::*x) ()); 
+ template <class R, class T, class C> void foo (R (T::*x) (C)); 
+  
+ template<int> struct I { 
+   int o (); 
+   int o () const; 
+ }; 
+  
+ template <int> void bar (void) { 
+   foo <int, I<1> > (&I<1>::o); 
+ }
***** Patch for 3.4 branch *****

2005-01-17  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/19311
	* init.c (build_offset_ref): Don't build non-dependent SCOPE_REF.
	* pt.c (build_non_dependent_expr): Don't build NON_DEPENDENT_EXPR
	for OFFSET_TYPE.
	* typeck.c (build_x_unary_op): Don't build non-dependent SCOPE_REF.
	Also set PTRMEM_OK_P for NON_DEPENDENT_EXPR.

2005-01-17  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/19311
	* g++.dg/template/non-dependent11.C: New test.


diff -cprN gcc-34-save/gcc/cp/init.c gcc-34-new/gcc/cp/init.c
*** gcc-34-save/gcc/cp/init.c	Sun Dec 19 19:10:45 2004
--- gcc-34-new/gcc/cp/init.c	Sun Jan 16 23:45:08 2005
*************** build_offset_ref (tree type, tree name, 
*** 1462,1475 ****
        return error_mark_node;
      }
  
-   if (processing_template_decl)
-     {
-       if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
- 	return build_min (SCOPE_REF, TREE_TYPE (member), type, orig_name);
-       else
- 	return build_min (SCOPE_REF, TREE_TYPE (member), type, name);
-     }
- 
    if (TREE_CODE (member) == TYPE_DECL)
      {
        TREE_USED (member) = 1;
--- 1462,1467 ----
diff -cprN gcc-34-save/gcc/cp/pt.c gcc-34-new/gcc/cp/pt.c
*** gcc-34-save/gcc/cp/pt.c	Sun Jan 16 23:51:43 2005
--- gcc-34-new/gcc/cp/pt.c	Sun Jan 16 23:45:08 2005
*************** build_non_dependent_expr (tree expr)
*** 12272,12278 ****
    if (TREE_CODE (inner_expr) == OVERLOAD 
        || TREE_CODE (inner_expr) == FUNCTION_DECL
        || TREE_CODE (inner_expr) == TEMPLATE_DECL
!       || TREE_CODE (inner_expr) == TEMPLATE_ID_EXPR)
      return expr;
    /* Preserve string constants; conversions from string constants to
       "char *" are allowed, even though normally a "const char *"
--- 12272,12279 ----
    if (TREE_CODE (inner_expr) == OVERLOAD 
        || TREE_CODE (inner_expr) == FUNCTION_DECL
        || TREE_CODE (inner_expr) == TEMPLATE_DECL
!       || TREE_CODE (inner_expr) == TEMPLATE_ID_EXPR
!       || TREE_CODE (inner_expr) == OFFSET_REF)
      return expr;
    /* Preserve string constants; conversions from string constants to
       "char *" are allowed, even though normally a "const char *"
diff -cprN gcc-34-save/gcc/cp/typeck.c gcc-34-new/gcc/cp/typeck.c
*** gcc-34-save/gcc/cp/typeck.c	Thu Aug  5 21:36:12 2004
--- gcc-34-new/gcc/cp/typeck.c	Sun Jan 16 23:45:08 2005
*************** build_x_unary_op (enum tree_code code, t
*** 3549,3571 ****
        if (type_dependent_expression_p (xarg))
  	return build_min_nt (code, xarg, NULL_TREE);
  
-       /* For non-dependent pointer-to-member, the SCOPE_REF will be
- 	 processed during template substitution.  Just compute the
- 	 right type here and build an ADDR_EXPR around it for
- 	 diagnostics.  */
-       if (code == ADDR_EXPR && TREE_CODE (xarg) == SCOPE_REF)
- 	{
- 	  tree type;
- 	  if (TREE_TYPE (xarg) == unknown_type_node)
- 	    type = unknown_type_node;
- 	  else if (TREE_CODE (TREE_TYPE (xarg)) == FUNCTION_TYPE)
- 	    type = build_pointer_type (TREE_TYPE (xarg));
- 	  else
- 	    type = build_ptrmem_type (TREE_OPERAND (xarg, 0),
- 				      TREE_TYPE (xarg));
- 	  return build_min (code, type, xarg, NULL_TREE);
- 	}
- 
        xarg = build_non_dependent_expr (xarg);
      }
  
--- 3549,3554 ----
*************** build_x_unary_op (enum tree_code code, t
*** 3627,3639 ****
        else if (TREE_CODE (xarg) == TARGET_EXPR)
  	warning ("taking address of temporary");
        exp = build_unary_op (ADDR_EXPR, xarg, 0);
-       if (TREE_CODE (exp) == ADDR_EXPR)
- 	PTRMEM_OK_P (exp) = ptrmem;
      }
  
    if (processing_template_decl && exp != error_mark_node)
!     return build_min_non_dep (code, exp, orig_expr,
! 			      /*For {PRE,POST}{INC,DEC}REMENT_EXPR*/NULL_TREE);
    return exp;
  }
  
--- 3610,3622 ----
        else if (TREE_CODE (xarg) == TARGET_EXPR)
  	warning ("taking address of temporary");
        exp = build_unary_op (ADDR_EXPR, xarg, 0);
      }
  
    if (processing_template_decl && exp != error_mark_node)
!     exp = build_min_non_dep (code, exp, orig_expr,
! 			     /*For {PRE,POST}{INC,DEC}REMENT_EXPR*/NULL_TREE);
!   if (TREE_CODE (exp) == ADDR_EXPR)
!     PTRMEM_OK_P (exp) = ptrmem;
    return exp;
  }
  
diff -cprN gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent11.C gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent11.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent11.C	Thu Jan  1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent11.C	Sun Jan 16 23:45:08 2005
***************
*** 0 ****
--- 1,18 ----
+ // { dg-do compile }
+ 
+ // Origin: Jakub Jelinek <jakub@gcc.gnu.org>
+ //	   Wolfgang Bangerth <bangerth@ticam.utexas.edu>
+ 
+ // PR c++/19311: Non-dependent address to member as function argument.
+ 
+ template <class R, class T>          void foo (R (T::*x) ()); 
+ template <class R, class T, class C> void foo (R (T::*x) (C)); 
+  
+ template<int> struct I { 
+   int o (); 
+   int o () const; 
+ }; 
+  
+ template <int> void bar (void) { 
+   foo <int, I<1> > (&I<1>::o); 
+ }

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