[cfe-dev] -Wambiguous-reversed-operator with equal types

Richard Smith via cfe-dev cfe-dev at lists.llvm.org
Thu Dec 10 13:39:24 PST 2020


On Thu, 10 Dec 2020 at 06:46, Nuno Lopes via cfe-dev <cfe-dev at lists.llvm.org>
wrote:

> Hi,
>
> I've been trying to fix a bunch of LLVM headers so they are compatible with
> C++20. (so I can include those from Alive2 source code)
>
> I'm currently stuck with -Wambiguous-reversed-operator. I've fixed a
> couple,
> but this one (a few similar) left me wondering if the warning is correct or
> not:
>
> In file included from llvm/include/llvm/Passes/PassBuilder.h:19:
> In file included from llvm/include/llvm/Analysis/CGSCCPassManager.h:98:
> llvm/include/llvm/Analysis/LazyCallGraph.h:1117:22: error: ISO C++20
> considers use of overloaded operator '!=' (with operand types
> 'llvm::User::value_op_iterator' and 'llvm::User::value_op_iterator') to be
> ambiguous despite there being a unique best viable function
> [-Werror,-Wambiguous-reversed-operator]
>       for (Value *Op : C->operand_values())
>                      ^
> llvm/include/llvm/ADT/iterator.h:263:8: note: ambiguity is between a
> regular
> call to this operator and a call with the argument order reversed
>   bool operator==(const DerivedT &RHS) const { return I == RHS.I; }
>        ^
>
> Note that it's complaining about comparing 'llvm::User::value_op_iterator'
> and 'llvm::User::value_op_iterator' (i.e., same type). Since both arguments
> are of the same type and the comparison function has const on both LHS/RHS,
> reversing them shouldn't have any impact, right?
> Unless there's some type conversion going on that the error message is
> hiding.
>
> Could someone please confirm if the warning is correct and/or the code
> needs
> fixing?
>

The warning is correct. In C++20 there are four ways to perform this !=
comparison:

Using iterator_adaptor_base::operator==:

1: !((iterator_adaptor_base&)a == b)  [synthesized != from operator==]
2: !((iterator_adaptor_base&)b == a)  [synthesized != from operator==,
reversed]

Using iterator_facade_base::operator!=:

3: (iterator_facade_base&)a != b  [regular operator!=]
4: (iterator_facade_base&)b != a  [regular operator!=, reversed]

Of these: 1 beats 3 (better conversion for a), 2 beats 4 (better conversion
for b), and they're otherwise unordered, so the result is an ambiguity.

Probably the cleanest solution would be to replace:

bool operator==(const DerivedT &RHS) const { return I == RHS.I; }

with:

friend bool operator==(const DerivedT &LHS, const DerivedT &RHS) const {
return LHS.I == RHS.I; }


> Thanks,
> Nuno
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20201210/fd85b1cb/attachment.html>


More information about the cfe-dev mailing list