This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH for 3.4/4.0] Fix PR19311 (ICE overload resolution forpmf function argument)
- From: Kriang Lerdsuwanakij <lerdsuwa at users dot sf dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 17 Jan 2005 21:38:09 +0700
- Subject: [C++ PATCH for 3.4/4.0] Fix PR19311 (ICE overload resolution forpmf function argument)
- Reply-to: lerdsuwa at users dot sf dot net
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);
+ }