aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2012-10-15 19:15:48 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2012-10-15 19:15:48 +0000
commit52243905a209f98799e8b8e4416520d11c17a04a (patch)
tree3cdd6d195d2a5d6ef57c4f63655d1981322d1c32 /gcc
parentc9e3b2097b6cd7bd26fad8d5cf3ddd7335776a84 (diff)
downloadgcc-52243905a209f98799e8b8e4416520d11c17a04a.zip
gcc-52243905a209f98799e8b8e4416520d11c17a04a.tar.gz
gcc-52243905a209f98799e8b8e4416520d11c17a04a.tar.bz2
re PR c++/17805 (too liberal operator lookup)
/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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/call.c50
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/overload/operator6.C27
4 files changed, 87 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 555345f..67ceed9 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c94bbbe..e21049b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 99c7a706..1b23a7b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..5002602
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/operator6.C
@@ -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);