aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDodji Seketeli <dodji@redhat.com>2009-11-02 19:55:02 +0000
committerDodji Seketeli <dodji@gcc.gnu.org>2009-11-02 20:55:02 +0100
commit9d5874cf05b0cabd722dfbc1d5acb8c11f067fc7 (patch)
tree3a220827c8faa9f288db192ce601a0e0bc67433a
parent5815841f113b625c746a17e3ddf0deb1458e9d40 (diff)
downloadgcc-9d5874cf05b0cabd722dfbc1d5acb8c11f067fc7.zip
gcc-9d5874cf05b0cabd722dfbc1d5acb8c11f067fc7.tar.gz
gcc-9d5874cf05b0cabd722dfbc1d5acb8c11f067fc7.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/pt.c26
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/other/ptrmem10.C29
-rw-r--r--gcc/testsuite/g++.dg/other/ptrmem11.C21
5 files changed, 89 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1921f72..10fa16a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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>
Restrict DR 757 change to C++0x mode.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2f0fa12..5af348a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -4686,6 +4686,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
@@ -4985,6 +5001,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
@@ -5011,6 +5032,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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ace8f7e..cfc4a0a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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>
PR testsuite/41878
diff --git a/gcc/testsuite/g++.dg/other/ptrmem10.C b/gcc/testsuite/g++.dg/other/ptrmem10.C
new file mode 100644
index 0000000..4b8c40a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/ptrmem10.C
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/other/ptrmem11.C b/gcc/testsuite/g++.dg/other/ptrmem11.C
new file mode 100644
index 0000000..a850c55
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/ptrmem11.C
@@ -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);
+