This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/59707 (ICE with binary operation and template conversion)


We've previously tweaked a few rules to avoid creating builtin candidates with dependent types, but things keep slipping through the cracks. This should be a more complete solution.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit aca790abae74da31099bcfb3ceb1459b6c2b6f05
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jan 29 17:09:04 2014 -0500

    	PR c++/59707
    	* call.c (add_builtin_candidate): Catch dependent types.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f6566cf..f572bc1 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2329,7 +2329,6 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
 
     case INDIRECT_REF:
       if (TYPE_PTR_P (type1)
-	  && !uses_template_parms (TREE_TYPE (type1))
 	  && (TYPE_PTROB_P (type1)
 	      || TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE))
 	break;
@@ -2467,15 +2466,13 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
 	  && TREE_CODE (type2) == ENUMERAL_TYPE)
 	break;
       if (TYPE_PTR_P (type1) 
-	  && null_ptr_cst_p (args[1])
-	  && !uses_template_parms (type1))
+	  && null_ptr_cst_p (args[1]))
 	{
 	  type2 = type1;
 	  break;
 	}
       if (null_ptr_cst_p (args[0]) 
-	  && TYPE_PTR_P (type2)
-	  && !uses_template_parms (type2))
+	  && TYPE_PTR_P (type2))
 	{
 	  type1 = type2;
 	  break;
@@ -2642,6 +2639,28 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
       gcc_unreachable ();
     }
 
+  /* Make sure we don't create builtin candidates with dependent types.  */
+  bool u1 = uses_template_parms (type1);
+  bool u2 = type2 ? uses_template_parms (type2) : false;
+  if (u1 || u2)
+    {
+      /* Try to recover if one of the types is non-dependent.  But if
+	 there's only one type, there's nothing we can do.  */
+      if (!type2)
+	return;
+      /* And we lose if both are dependent.  */
+      if (u1 && u2)
+	return;
+      /* Or if they have different forms.  */
+      if (TREE_CODE (type1) != TREE_CODE (type2))
+	return;
+
+      if (u1 && !u2)
+	type1 = type2;
+      else if (u2 && !u1)
+	type2 = type1;
+    }
+
   /* If we're dealing with two pointer types or two enumeral types,
      we need candidates for both of them.  */
   if (type2 && !same_type_p (type1, type2)
diff --git a/gcc/testsuite/g++.dg/template/operator12.C b/gcc/testsuite/g++.dg/template/operator12.C
new file mode 100644
index 0000000..bc8e91d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/operator12.C
@@ -0,0 +1,9 @@
+// PR c++/59707
+
+struct T {
+    template<class D> operator D*() const;
+};
+
+void f(T x) {
+    x < x;			// { dg-error "no match" }
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]