diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2012-10-15 19:15:48 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2012-10-15 19:15:48 +0000 |
commit | 52243905a209f98799e8b8e4416520d11c17a04a (patch) | |
tree | 3cdd6d195d2a5d6ef57c4f63655d1981322d1c32 /gcc | |
parent | c9e3b2097b6cd7bd26fad8d5cf3ddd7335776a84 (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/call.c | 50 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/overload/operator6.C | 27 |
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); |