-Wambiguous-reversed-operator with equal types

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

-Wambiguous-reversed-operator with equal types

shirley breuer via cfe-dev
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?

Thanks,
Nuno

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: -Wambiguous-reversed-operator with equal types

shirley breuer via cfe-dev
On Thu, 10 Dec 2020 at 06:46, Nuno Lopes via cfe-dev <[hidden email]> 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
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: -Wambiguous-reversed-operator with equal types

shirley breuer via cfe-dev

Thanks, Richard. That works great!

Ok, Ill try to fix the remaining issues on my own 😊

 

Thanks,

Nuno

 

 

From: Richard Smith <[hidden email]>
Sent: 10 December 2020 21:39
To: Nuno Lopes <[hidden email]>
Cc: Clang Dev <[hidden email]>
Subject: Re: [cfe-dev] -Wambiguous-reversed-operator with equal types

 

On Thu, 10 Dec 2020 at 06:46, Nuno Lopes via cfe-dev <[hidden email]> 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
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev