This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 20734
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 5 Apr 2005 22:40:13 -0700
- Subject: C++ PATCH: PR 20734
- Reply-to: mark at codesourcery dot com
This patch fixes PR c++/20734, a problem with pointers-to-members in
templates. Most of this patch is moving the part of front end that
handles creating a pointer-to-member from "&" applied to "X::y" out of
unary_complex_lvalue (where it should never have been) to
build_unary_op, where it clearly belongs. I also simplified that code
a bit in the process of moving it.
Tested on x86_64-unknown-linux-gnu, applied on 4.0 branch and
mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2005-04-05 Mark Mitchell <mark@codesourcery.com>
PR c++/20734
* cp-tree.def (OFFSET_REF): Correct comments.
* init.c (build_offset_ref): Remove misleading comment.
* typeck.c (build_unary_op): Handle pointer-to-member creation
here, rather than ...
(unary_complex_lvalue): ... here.
2005-04-05 Mark Mitchell <mark@codesourcery.com>
PR c++/20734
* g++.dg/template/ptrmem13.C: New test.
Index: testsuite/g++.dg/template/ptrmem13.C
===================================================================
RCS file: testsuite/g++.dg/template/ptrmem13.C
diff -N testsuite/g++.dg/template/ptrmem13.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/ptrmem13.C 6 Apr 2005 02:32:26 -0000
***************
*** 0 ****
--- 1,11 ----
+ // PR c++/20734
+
+ struct A;
+ void blah(int A::*);
+ struct A{
+ int a;
+ };
+ template<typename T>
+ void hoho(){
+ blah(&A::a);
+ }
Index: cp/cp-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.def,v
retrieving revision 1.94
diff -c -5 -p -r1.94 cp-tree.def
*** cp/cp-tree.def 11 Feb 2005 16:28:37 -0000 1.94
--- cp/cp-tree.def 6 Apr 2005 02:32:26 -0000
*************** Boston, MA 02111-1307, USA. */
*** 29,42 ****
a non-static member. In this case, operand 0 will be a TYPE
(corresponding to `A') and operand 1 will be a FIELD_DECL,
BASELINK, or TEMPLATE_ID_EXPR (corresponding to `m').
The expression is a pointer-to-member if its address is taken,
! but simply denotes a member of the object if its address isnot
! taken. In the latter case, resolve_offset_ref is used to
! convert it to a representation of the member referred to by the
! OFFSET_REF.
This form is only used during the parsing phase; once semantic
analysis has taken place they are eliminated.
2. An expression of the form `x.*p'. In this case, operand 0 will
--- 29,40 ----
a non-static member. In this case, operand 0 will be a TYPE
(corresponding to `A') and operand 1 will be a FIELD_DECL,
BASELINK, or TEMPLATE_ID_EXPR (corresponding to `m').
The expression is a pointer-to-member if its address is taken,
! but simply denotes a member of the object if its address is not
! taken.
This form is only used during the parsing phase; once semantic
analysis has taken place they are eliminated.
2. An expression of the form `x.*p'. In this case, operand 0 will
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.412.2.3
diff -c -5 -p -r1.412.2.3 init.c
*** cp/init.c 22 Mar 2005 09:10:49 -0000 1.412.2.3
--- cp/init.c 6 Apr 2005 02:32:27 -0000
*************** build_offset_ref (tree type, tree name,
*** 1549,1561 ****
return error_mark_node;
}
return member;
}
- /* In member functions, the form `type::name' is no longer
- equivalent to `this->type::name', at least not until
- resolve_offset_ref. */
member = build2 (OFFSET_REF, TREE_TYPE (member), decl, member);
PTRMEM_OK_P (member) = 1;
return member;
}
--- 1549,1558 ----
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.616.2.3
diff -c -5 -p -r1.616.2.3 typeck.c
*** cp/typeck.c 25 Mar 2005 22:54:48 -0000 1.616.2.3
--- cp/typeck.c 6 Apr 2005 02:32:27 -0000
*************** build_unary_op (enum tree_code code, tre
*** 4024,4033 ****
--- 4024,4056 ----
case OVERLOAD:
arg = OVL_CURRENT (arg);
break;
+ case OFFSET_REF:
+ /* Turn a reference to a non-static data member into a
+ pointer-to-member. */
+ {
+ tree type;
+ tree t;
+
+ if (!PTRMEM_OK_P (arg))
+ return build_unary_op (code, arg, 0);
+
+ t = TREE_OPERAND (arg, 1);
+ if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
+ {
+ error ("cannot create pointer to reference member %qD", t);
+ return error_mark_node;
+ }
+
+ type = build_ptrmem_type (context_for_name_lookup (t),
+ TREE_TYPE (t));
+ t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
+ return t;
+ }
+
default:
break;
}
/* Allow the address of a constructor if all the elements
*************** unary_complex_lvalue (enum tree_code cod
*** 4180,4235 ****
}
if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (arg)) == METHOD_TYPE
|| TREE_CODE (arg) == OFFSET_REF)
! {
! tree t;
!
! gcc_assert (TREE_CODE (arg) != SCOPE_REF);
!
! if (TREE_CODE (arg) != OFFSET_REF)
! return 0;
!
! t = TREE_OPERAND (arg, 1);
!
! /* Check all this code for right semantics. */
! if (TREE_CODE (t) == FUNCTION_DECL)
! {
! if (DECL_DESTRUCTOR_P (t))
! error ("taking address of destructor");
! return build_unary_op (ADDR_EXPR, t, 0);
! }
! if (TREE_CODE (t) == VAR_DECL)
! return build_unary_op (ADDR_EXPR, t, 0);
! else
! {
! tree type;
!
! if (TREE_OPERAND (arg, 0)
! && ! is_dummy_object (TREE_OPERAND (arg, 0))
! && TREE_CODE (t) != FIELD_DECL)
! {
! error ("taking address of bound pointer-to-member expression");
! return error_mark_node;
! }
! if (!PTRMEM_OK_P (arg))
! return build_unary_op (code, arg, 0);
!
! if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
! {
! error ("cannot create pointer to reference member %qD", t);
! return error_mark_node;
! }
!
! type = build_ptrmem_type (context_for_name_lookup (t),
! TREE_TYPE (t));
! t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
! return t;
! }
! }
!
/* We permit compiler to make function calls returning
objects of aggregate type look like lvalues. */
{
tree targ = arg;
--- 4203,4213 ----
}
if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (arg)) == METHOD_TYPE
|| TREE_CODE (arg) == OFFSET_REF)
! return NULL_TREE;
/* We permit compiler to make function calls returning
objects of aggregate type look like lvalues. */
{
tree targ = arg;