Patchwork PR c++/51476 - ICE on PTRMEM_CST as template argument in c++11

login
register
mail settings
Submitter Dodji Seketeli
Date Dec. 13, 2011, 3:50 p.m.
Message ID <m3ty545v3a.fsf@redhat.com>
Download mbox | patch
Permalink /patch/131124/
State New
Headers show

Comments

Dodji Seketeli - Dec. 13, 2011, 3:50 p.m.
Hello,

In the example of the patch, we crash because convert_nontype_argument
calls maybe_constant_value with the PTRMEM_CST for &B::i (in cxx0x
mode) which ends up trying to poke at the offset of i, but struct B is
not yet laid out.

My understanding is that using a pointer to non-static member as an
argument of the template A (in this context) is invalid anyway, so we
could avoid trying to see if it's a constant value altogether, similar
to what's done in the 'else if' right after the offending 'if'.

Thus the patch below, bootstrapped and tested on
x86_64-unknown-linux-gnu against trunk.

gcc/cp/

	PR c++/51476
	* pt.c (convert_nontype_argument): Don't call maybe_constant_value
	for PTRMEM_CST nodes.

gcc/testsuite/

	PR c++/51476
	* cpp0x/ptrmem-cst-arg1.C: New test.
---
 gcc/cp/pt.c                                  |    3 ++-
 gcc/testsuite/g++.dg/cpp0x/ptrmem-cst-arg1.C |    9 +++++++++
 2 files changed, 11 insertions(+), 1 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/ptrmem-cst-arg1.C
Jason Merrill - Dec. 13, 2011, 4:14 p.m.
On 12/13/2011 10:50 AM, Dodji Seketeli wrote:
> -      if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
> +      if (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
> +	&&  TREE_CODE (expr) != PTRMEM_CST)
>   	expr = maybe_constant_value (expr);
>         else if (TYPE_PTR_P (type)
>   	       || (TYPE_PTR_TO_MEMBER_P (type)

This could still break for a parameter of object pointer type.  Let's 
check for PTRMEM_CST separately, before any of the other tests.

Jason

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bb5aa0c..8c9f97b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5720,7 +5720,8 @@  convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
      to a null value, but otherwise still need to be of a specific form.  */
   if (cxx_dialect >= cxx0x)
     {
-      if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+      if (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+	  && TREE_CODE (expr) != PTRMEM_CST)
 	expr = maybe_constant_value (expr);
       else if (TYPE_PTR_P (type)
 	       || (TYPE_PTR_TO_MEMBER_P (type)
diff --git a/gcc/testsuite/g++.dg/cpp0x/ptrmem-cst-arg1.C b/gcc/testsuite/g++.dg/cpp0x/ptrmem-cst-arg1.C
new file mode 100644
index 0000000..b6c81d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/ptrmem-cst-arg1.C
@@ -0,0 +1,9 @@ 
+// Origin PR c++/51476
+// { dg-options "-std=c++11" }
+
+template<int> struct A {};                                                               
+struct B
+{
+    int i;
+    A<&B::i> a; // { dg-error "could not convert template argument" }
+};