dblaikie added inline comments.

================
Comment at: llvm/include/llvm/IR/BasicBlock.h:324-325
+    template <typename PHINodeU, typename BBIteratorU,
+              typename = std::enable_if_t<
+                  std::is_convertible<PHINodeU *, PHINodeT *>::value>>
     phi_iterator_impl(const phi_iterator_impl<PHINodeU, BBIteratorU> &Arg)
----------------
dblaikie wrote:
> Quuxplusone wrote:
> > BRevzin wrote:
> > > dblaikie wrote:
> > > > BRevzin wrote:
> > > > > dblaikie wrote:
> > > > > > What tripped over/required this SFINAE?
> > > > > There's somewhere which compared a const iterator to a non-const 
> > > > > iterator, that ends up doing conversions in both directions under 
> > > > > C++20 rules, one direction of which is perfectly fine and the other 
> > > > > was a hard error. Need to make the non-const iterator not 
> > > > > constructible from a const iterator.
> > > > Is this true for all iterators? Or some quirk of how this one is 
> > > > written/used (that could be fixed/changed there instead)?
> > > So I undid this change to copy the exact issue that I ran into. But it 
> > > actually ended up still compiling anyway. Part of the issue might be that 
> > > I keep futzing with the cmake configuration since it takes me more than 
> > > an hour to compile, so maybe there's some target that needed this change 
> > > that I no longer compile.
> > > 
> > > But the kind of problem I think this had was:
> > > 
> > > ```
> > > template <typename T>
> > > struct iterator {
> > >     T* p;
> > >     
> > >     template <typename U>
> > >     iterator(iterator<U> rhs)
> > >         : p(rhs.p)
> > >     { } 
> > > 
> > >     bool operator==(iterator const& rhs);
> > > };
> > > 
> > > bool check(iterator<int const> a, iterator<int> b) {
> > >     return a == b;
> > > }
> > > ```
> > > 
> > > which compiles fine in C++17 but is ambiguous in C++20 because 
> > > `b.operator==(a)` is also a candidate (even though it's not _really_ a 
> > > candidate, and would be a hard error if selected). the sfinae removes the 
> > > bad candidate from the set. 
> > > 
> > > It's true for all iterators in general in that you want `const_iterator` 
> > > constructible from `iterator` but not the reverse (unless they're the 
> > > same type).
> > IMO there is a (much) bigger task hiding here, which is to audit every type 
> > in the codebase whose name contains the string "Iterator" and compare them 
> > to the C++20 Ranges `std::forward_iterator` concept. My impression is that 
> > the vast majority of real-world "iterator types" are not iterators 
> > according to C++20 Ranges, and that this can have arbitrarily weird effects 
> > when you mix them with the C++20 STL.
> > 
> > However, that is //massive// scope creep re this particular patch. I think 
> > the larger question of "do all our iterators need X / are all our iterators 
> > written wrong" should be scoped-outside-of this patch.
> Sorry, not suggesting that kind of scope creep - but do want to understand 
> whether this is representative of the way code should generally be written, 
> or whether this is working around some other issue/different fix.
Fair enough - don't mind keeping it in then.


================
Comment at: llvm/include/llvm/Support/BinaryStreamRef.h:124
 
-  bool operator==(const RefType &Other) const {
-    if (BorrowedImpl != Other.BorrowedImpl)
+  friend bool operator==(const RefType &Self, const RefType &Other) {
+    if (Self.BorrowedImpl != Other.BorrowedImpl)
----------------
dblaikie wrote:
> Quuxplusone wrote:
> > Is there a neat rule of thumb for when you were able to preserve the member 
> > `bool Me::operator==(const Me& rhs) const` versus when you were forced to 
> > change it to a hidden friend? It seems like maybe you changed it to a 
> > hidden friend only in cases where `Me` was a base class, is that right?
> Be curious of the answer here - and, honestly, I'd be fine with changing them 
> all to friends. It makes them more consistent - equal rank for implicit 
> conversions on LHS and RHS, etc. (generally considered best practice 
> basically to not define op overloads as members if they can be defined as 
> non-members)
Ping on this (& I'd usually call the parameters LHS and RHS rather than Self 
and Other)


================
Comment at: llvm/unittests/ADT/STLExtrasTest.cpp:465
   // Check fancy pointer overload for unique_ptr
+  // Parenthesizing to_address to avoid ADL finding std::to_address
   std::unique_ptr<int> V2 = std::make_unique<int>(0);
----------------
dblaikie wrote:
> jhenderson wrote:
> > Nit: trailing full stop.
> Probably more suitable to use qualify the name rather than use parens (teh 
> comment's still helpful to explain why either strategy is used) - that's 
> what's done with llvm::make_unique, for instance.
Ping on this.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78938/new/

https://reviews.llvm.org/D78938

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to