Patchwork C++ PATCH for c++/56438 (ICE with cast in template)

login
register
mail settings
Submitter Jason Merrill
Date Feb. 26, 2013, 4:19 a.m.
Message ID <512C37E7.60502@redhat.com>
Download mbox | patch
Permalink /patch/223107/
State New
Headers show

Comments

Jason Merrill - Feb. 26, 2013, 4:19 a.m.
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.

Patch

commit 97bd6eae21005915c47eea8f3b52aff72ba3238d
Author: Jason Merrill <jason@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" }
+}