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" }
+}