Patchwork C++ PATCH for c++/47705 (ICE with non-pointer argument to pointer template parameter)

login
register
mail settings
Submitter Jason Merrill
Date March 8, 2011, 9:40 p.m.
Message ID <4D76A237.4010000@redhat.com>
Download mbox | patch
Permalink /patch/86038/
State New
Headers show

Comments

Jason Merrill - March 8, 2011, 9:40 p.m.
On 03/08/2011 12:25 PM, Jason Merrill wrote:
> We were asserting that any argument to a non-type template parameter of
> pointer type must be an address. Which is true of valid code (apart from
> null pointer values), but not necessarily of invalid code, where we
> should complain rather than crash.

Dodji had an idea for a different way to fix this crash: avoid the call 
to decay_conversion which adds the NOP to convert 'const int' to 'int' 
by limiting it to the case where the argument is an array.  I think I 
like this way better.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit c9e36778318c240777889a403693e95488a13b6d
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Mar 8 14:02:21 2011 -0500

    	PR c++/47705
    	* pt.c (convert_nontype_argument): Only call decay_conversion on
    	arrays.

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index cda9df8..2ca2cd0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5314,7 +5314,8 @@  convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 
   /* Add the ADDR_EXPR now for the benefit of
      value_dependent_expression_p.  */
-  if (TYPE_PTROBV_P (type))
+  if (TYPE_PTROBV_P (type)
+      && TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE)
     expr = decay_conversion (expr);
 
   /* If we are in a template, EXPR may be non-dependent, but still
@@ -5369,20 +5370,15 @@  convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 	 qualification conversion. Let's strip everything.  */
       else if (TYPE_PTROBV_P (type))
 	{
-	  tree sub = expr;
-	  STRIP_NOPS (sub);
-	  if (TREE_CODE (sub) == ADDR_EXPR)
-	    {
-	      gcc_assert (TREE_CODE (TREE_TYPE (sub)) == POINTER_TYPE);
-	      /* Skip the ADDR_EXPR only if it is part of the decay for
-		 an array. Otherwise, it is part of the original argument
-		 in the source code.  */
-	      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (sub, 0))) == ARRAY_TYPE)
-		expr = TREE_OPERAND (sub, 0);
-	      else
-		expr = sub;
-	      expr_type = TREE_TYPE (expr);
-	    }
+	  STRIP_NOPS (expr);
+	  gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
+	  gcc_assert (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE);
+	  /* Skip the ADDR_EXPR only if it is part of the decay for
+	     an array. Otherwise, it is part of the original argument
+	     in the source code.  */
+	  if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == ARRAY_TYPE)
+	    expr = TREE_OPERAND (expr, 0);
+	  expr_type = TREE_TYPE (expr);
 	}
     }
 
diff --git a/gcc/testsuite/g++.dg/template/nontype21.C b/gcc/testsuite/g++.dg/template/nontype21.C
index c0f5319..69cab54 100644
--- a/gcc/testsuite/g++.dg/template/nontype21.C
+++ b/gcc/testsuite/g++.dg/template/nontype21.C
@@ -4,4 +4,4 @@  template<char const * const x> class Something { };
 
 extern char const xyz;
 
-class SomethingElse:public Something<xyz> { }; // { dg-error "const char *" }
+class SomethingElse:public Something<xyz> { }; // { dg-error "xyz. is a variable" }