]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/17805 (too liberal operator lookup)
authorAlexandre Oliva <aoliva@redhat.com>
Mon, 15 Oct 2012 19:15:48 +0000 (19:15 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Mon, 15 Oct 2012 19:15:48 +0000 (19:15 +0000)
/cp
2012-10-15  Alexandre Oliva  <aoliva@redhat.com>
    Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/17805
* call.c (build_new_op): Filter out operator functions that don't
satisfy enum-conversion match requirements.

/testsuite
2012-10-15  Alexandre Oliva  <aoliva@redhat.com>
    Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/17805
* g++.dg/overload/operator6.C: New.

Co-Authored-By: Paolo Carlini <paolo.carlini@oracle.com>
From-SVN: r192471

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

index 555345f58a800a24546bdf87271767b4eb0ff459..67ceed97723e8f3741856e260f4a2ada6fd7f98f 100644 (file)
@@ -1,3 +1,10 @@
+2012-10-15  Alexandre Oliva  <aoliva@redhat.com>
+           Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/17805
+       * call.c (build_new_op): Filter out operator functions that don't
+       satisfy enum-conversion match requirements.
+
 2012-10-15  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/50080 (again)
index c94bbbe3c08d13c75ad1b294c2b8e102a29f4d1a..e21049b8e648a803d8421244835206a7d85eaf3e 100644 (file)
@@ -5043,6 +5043,11 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
                  NULL_TREE, arglist, NULL_TREE,
                  NULL_TREE, false, NULL_TREE, NULL_TREE,
                  flags, &candidates, complain);
+
+  args[0] = arg1;
+  args[1] = arg2;
+  args[2] = NULL_TREE;
+
   /* Add class-member operators to the candidate set.  */
   if (CLASS_TYPE_P (TREE_TYPE (arg1)))
     {
@@ -5062,10 +5067,49 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
                        BASELINK_ACCESS_BINFO (fns),
                        flags, &candidates, complain);
     }
+  /* Per 13.3.1.2/3, 2nd bullet, if no operand has a class type, then
+     only non-member functions that have type T1 or reference to
+     cv-qualified-opt T1 for the first argument, if the first argument
+     has an enumeration type, or T2 or reference to cv-qualified-opt
+     T2 for the second argument, if the the second argument has an
+     enumeration type.  Filter out those that don't match.  */
+  else if (! arg2 || ! CLASS_TYPE_P (TREE_TYPE (arg2)))
+    {
+      struct z_candidate **candp, **next;
 
-  args[0] = arg1;
-  args[1] = arg2;
-  args[2] = NULL_TREE;
+      for (candp = &candidates; *candp; candp = next)
+       {
+         tree parmlist, parmtype;
+         int i, nargs = (arg2 ? 2 : 1);
+
+         cand = *candp;
+         next = &cand->next;
+
+         parmlist = TYPE_ARG_TYPES (TREE_TYPE (cand->fn));
+
+         for (i = 0; i < nargs; ++i)
+           {
+             parmtype = TREE_VALUE (parmlist);
+
+             if (TREE_CODE (parmtype) == REFERENCE_TYPE)
+               parmtype = TREE_TYPE (parmtype);
+             if (TREE_CODE (TREE_TYPE (args[i])) == ENUMERAL_TYPE
+                 && (same_type_ignoring_top_level_qualifiers_p
+                     (TREE_TYPE (args[i]), parmtype)))
+               break;
+
+             parmlist = TREE_CHAIN (parmlist);
+           }
+
+         /* No argument has an appropriate type, so remove this
+            candidate function from the list.  */
+         if (i == nargs)
+           {
+             *candp = cand->next;
+             next = candp;
+           }
+       }
+    }
 
   add_builtin_candidates (&candidates, code, code2, fnname, args,
                          flags, complain);
index 99c7a70676a382f57a38a41f1d76131d468d528e..1b23a7b1dd33b834a4faec9b3e834213bf476e81 100644 (file)
@@ -1,3 +1,9 @@
+2012-10-15  Alexandre Oliva  <aoliva@redhat.com>
+           Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/17805
+       * g++.dg/overload/operator6.C: New.
+
 2012-10-15  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/50080 (again)
diff --git a/gcc/testsuite/g++.dg/overload/operator6.C b/gcc/testsuite/g++.dg/overload/operator6.C
new file mode 100644 (file)
index 0000000..5002602
--- /dev/null
@@ -0,0 +1,27 @@
+// PR c++/17805
+
+// Per 13.3.1.2/3 bullet 2, an operator function is not a candidate
+// for overload resolution if neither argument is of class type and
+// neither enumerator-typed argument gets an exact match, with or
+// without reference binding, for the corresponding parameter.
+
+struct A
+{
+  A(int);
+  A(const char*);
+};
+
+bool operator==(const A&, const A&);
+const A& operator*(const A&);
+
+enum E { e };
+
+bool b1 = (e == "");     // { dg-error "no match" }
+
+bool b2 = (A(1) == "");
+
+bool b3 = (e == A(1));
+
+const A& a1 = *e;        // { dg-error "no match" }
+
+const A& a2 = *A(1);