Patchwork C++ PATCH for c++/54946 (ICE on invalid pointer template argument)

login
register
mail settings
Submitter Jason Merrill
Date March 16, 2013, 7:30 p.m.
Message ID <5144C848.4060608@redhat.com>
Download mbox | patch
Permalink /patch/228244/
State New
Headers show

Comments

Jason Merrill - March 16, 2013, 7:30 p.m.
We were assuming well-formed code, which doesn't work out so well.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit f4e6a7962929074fc6290dd27742d93ddd924a43
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Feb 15 15:09:50 2013 -0500

    	PR c++/54946
    	* pt.c (convert_nontype_argument): Handle invalid pointer.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 126e110..c07ed32 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5553,15 +5553,19 @@  convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
      qualification conversion. Let's strip everything.  */
   else if (TREE_CODE (expr) == NOP_EXPR && TYPE_PTROBV_P (type))
     {
-      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);
+      tree probe = expr;
+      STRIP_NOPS (probe);
+      if (TREE_CODE (probe) == ADDR_EXPR
+	  && TREE_CODE (TREE_TYPE (probe)) == 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 (probe, 0))) == ARRAY_TYPE)
+	    probe = TREE_OPERAND (probe, 0);
+	  expr = probe;
+	  expr_type = TREE_TYPE (expr);
+	}
     }
 
   /* [temp.arg.nontype]/5, bullet 1
@@ -5640,6 +5644,13 @@  convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 		     expr, expr);
 	      return NULL_TREE;
 	    }
+	  if (POINTER_TYPE_P (expr_type))
+	    {
+	      error ("%qE is not a valid template argument for %qT"
+		     "because it is not the address of a variable",
+		     expr, type);
+	      return NULL_TREE;
+	    }
 	  /* Other values, like integer constants, might be valid
 	     non-type arguments of some other type.  */
 	  return error_mark_node;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template5.C
new file mode 100644
index 0000000..aa80658
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template5.C
@@ -0,0 +1,6 @@ 
+// PR c++/54946
+// { dg-do compile { target c++11 } }
+
+template<const char*s>    static void testfunc();
+constexpr struct testtype { const char* str; } test = { "abc"} ;
+void (*functionpointer)() = testfunc<(const char*) test.str>; // { dg-error "" }