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: r153822
This commit is contained in:
Dodji Seketeli 2009-11-02 19:55:02 +00:00 committed by Dodji Seketeli
parent 5815841f11
commit 9d5874cf05
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-11-02 Jason Merrill <jason@redhat.com> 2009-11-02 Jason Merrill <jason@redhat.com>
Restrict DR 757 change to C++0x mode. Restrict DR 757 change to C++0x mode.

View File

@ -4686,6 +4686,22 @@ convert_nontype_argument_function (tree type, tree expr)
return fn; 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 /* Attempt to convert the non-type template parameter EXPR to the
indicated TYPE. If the conversion is successful, return the indicated TYPE. If the conversion is successful, return the
converted value. If the conversion is unsuccessful, return converted value. If the conversion is unsuccessful, return
@ -4985,6 +5001,11 @@ convert_nontype_argument (tree type, tree expr)
if (expr == error_mark_node) if (expr == error_mark_node)
return 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 /* There is no way to disable standard conversions in
resolve_address_of_overloaded_function (called by resolve_address_of_overloaded_function (called by
instantiate_type). It is possible that the call succeeded by instantiate_type). It is possible that the call succeeded by
@ -5011,6 +5032,11 @@ convert_nontype_argument (tree type, tree expr)
qualification conversions (_conv.qual_) are applied. */ qualification conversions (_conv.qual_) are applied. */
else if (TYPE_PTRMEM_P (type)) 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); expr = perform_qualification_conversions (type, expr);
if (expr == error_mark_node) if (expr == error_mark_node)
return expr; 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 Janis Johnson <janis187@us.ibm.com> 2009-11-02 Janis Johnson <janis187@us.ibm.com>
PR testsuite/41878 PR testsuite/41878

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);