]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR c++/59707
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 30 Jan 2014 05:28:52 +0000 (05:28 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 30 Jan 2014 05:28:52 +0000 (05:28 +0000)
* call.c (add_builtin_candidate): Catch dependent types.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207295 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/g++.dg/template/operator12.C [new file with mode: 0644]

index 858272ffc8d38f7d575ca0e73895e8b1f9bc381c..59f2b7ec91d585cc992c021ac4ec0bc3ac6fa355 100644 (file)
@@ -1,5 +1,8 @@
 2014-01-29  Jason Merrill  <jason@redhat.com>
 
+       PR c++/59707
+       * call.c (add_builtin_candidate): Catch dependent types.
+
        PR c++/59989
        * pt.c (expand_template_argument_pack): Correct
        non_default_args_count calculation.
index f6566cff1a25d525f1d583f0917c1be6c29173d0..f572bc1fc88013d6952af3f021fe1b51b08bdb81 100644 (file)
@@ -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 (file)
index 0000000..bc8e91d
--- /dev/null
@@ -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" }
+}