Here, the problem is that value_dependent_expression_p only expects to see constant expressions, but potential_constant_expression_1 was letting through some things that aren't in a way that the former function was checking for. Fixed by returning false from the latter function in that case.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 97bd6eae21005915c47eea8f3b52aff72ba3238d
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon Feb 25 16:05:19 2013 -0500

    	PR c++/56438
    	* semantics.c (potential_constant_expression_1): In C++98, a cast
    	to non-integral type can't be a constant expression.

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 458ed26..60271b5 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8607,6 +8607,18 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case STATIC_CAST_EXPR:
     case REINTERPRET_CAST_EXPR:
     case IMPLICIT_CONV_EXPR:
+      if (cxx_dialect < cxx0x
+	  && !dependent_type_p (TREE_TYPE (t))
+	  && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t)))
+	/* In C++98, a conversion to non-integral type can't be part of a
+	   constant expression.  */
+	{
+	  if (flags & tf_error)
+	    error ("cast to non-integral type %qT in a constant expression",
+		   TREE_TYPE (t));
+	  return false;
+	}
+
       return (potential_constant_expression_1
 	      (TREE_OPERAND (t, 0),
 	       TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE, flags));
diff --git a/gcc/testsuite/g++.dg/template/cast3.C b/gcc/testsuite/g++.dg/template/cast3.C
new file mode 100644
index 0000000..b343ee4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/cast3.C
@@ -0,0 +1,22 @@
+// PR c++/56438
+
+struct A { };
+A& operator<<(A&, const char*);
+
+struct B {
+  int size();
+};
+
+struct C { };
+
+template <class S, class T>
+S bar(const S& s, const T& t) {
+  return s;
+}
+
+template<class S, class T>
+void foo() {
+  A a;
+  B b;
+  a << bar(b.size(), C());	// { dg-error "no match" }
+}

Reply via email to