re PR c++/37093 (ICE with pointer to member template parameters)

Fix PR c++/37093

gcc/cp/ChangeLog:

	PR c++/37093
	* pt.c (check_valid_ptrmem_cst_expr): New function.
	(convert_nontype_argument): Use it to output an error for
	illegal pointer to member expressions used as template arguments.

gcc/testsuite/ChangeLog:

      PR c++/37093
	* g++.dg/other/ptrmem10.C: New test.
	* g++.dg/other/ptrmem11.C: Likewise.

From-SVN: r153823
This commit is contained in:
Dodji Seketeli 2009-11-02 19:58:57 +00:00 committed by Dodji Seketeli
parent 83a23d296d
commit 5d9a6f46dd
5 changed files with 89 additions and 0 deletions

View File

@ -1,3 +1,10 @@
2009-11-02 Dodji Seketeli <dodji@redhat.com>
PR c++/37093
* pt.c (check_valid_ptrmem_cst_expr): New function.
(convert_nontype_argument): Use it to output an error for
illegal pointer to member expressions used as template arguments.
2009-10-31 Jason Merrill <jason@redhat.com>
PR c++/41754

View File

@ -4322,6 +4322,22 @@ convert_nontype_argument_function (tree type, tree expr)
return fn;
}
/* Subroutine of convert_nontype_argument.
Check if EXPR of type TYPE is a valid pointer-to-member constant.
Emit an error otherwise. */
static bool
check_valid_ptrmem_cst_expr (tree type, tree expr)
{
STRIP_NOPS (expr);
if (expr && (null_ptr_cst_p (expr) || TREE_CODE (expr) == PTRMEM_CST))
return true;
error ("%qE is not a valid template argument for type %qT",
expr, type);
error ("it must be a pointer-to-member of the form `&X::Y'");
return false;
}
/* Attempt to convert the non-type template parameter EXPR to the
indicated TYPE. If the conversion is successful, return the
converted value. If the conversion is unsuccessful, return
@ -4621,6 +4637,11 @@ convert_nontype_argument (tree type, tree expr)
if (expr == error_mark_node)
return error_mark_node;
/* [temp.arg.nontype] bullet 1 says the pointer to member
expression must be a pointer-to-member constant. */
if (!check_valid_ptrmem_cst_expr (type, expr))
return error_mark_node;
/* There is no way to disable standard conversions in
resolve_address_of_overloaded_function (called by
instantiate_type). It is possible that the call succeeded by
@ -4647,6 +4668,11 @@ convert_nontype_argument (tree type, tree expr)
qualification conversions (_conv.qual_) are applied. */
else if (TYPE_PTRMEM_P (type))
{
/* [temp.arg.nontype] bullet 1 says the pointer to member
expression must be a pointer-to-member constant. */
if (!check_valid_ptrmem_cst_expr (type, expr))
return error_mark_node;
expr = perform_qualification_conversions (type, expr);
if (expr == error_mark_node)
return expr;

View File

@ -1,3 +1,9 @@
2009-11-02 Dodji Seketeli <dodji@redhat.com>
PR c++/37093
* g++.dg/other/ptrmem10.C: New test.
* g++.dg/other/ptrmem11.C: Likewise.
2009-11-02 Paul Thomas <pault@gcc.gnu.org>
PR fortran/41772

View File

@ -0,0 +1,29 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin PR c++/37093
template <class C, void (C::*M) ()>
static
void foo(void *obj)
{
C *p = static_cast<C*>(obj);
(p->*M)();
}
template <class C>
static void
bar(C *c, void (C::*m) ())
{
foo<C,m>((void *)c);// { dg-error "(not a valid template arg|pointer-to-member|no matching fun)" }
}
struct S
{
void baz () {}
};
int
main ()
{
S a;
bar(&a, &S::baz);
}

View File

@ -0,0 +1,21 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin PR c++/37093
struct A {};
template <int A::* p>
int
foo(A* q)
{
return q->*p;
}
template <typename T>
int
bar(int T::* p)
{
return foo<p>(0);// { dg-error "(not a valid template arg|no matching func|pointer-to-member)" }
}
int i = bar<A>(0);