[clang] Revert [clang] Handle templated operators with reversed arguments and [STLExtras] Undo C++20 hack (PR #69937)

Utkarsh Saxena via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 23 09:06:36 PDT 2023


https://github.com/usx95 created https://github.com/llvm/llvm-project/pull/69937

None

>From b100ca6f219fda1fed5b92aba8471aa9a6ef8906 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <usx at google.com>
Date: Mon, 23 Oct 2023 18:02:35 +0200
Subject: [PATCH 1/2] Revert "[STLExtras] Undo C++20 hack"

This reverts commit e558be51bab051d1471d92e967f8a2aecc13567a.
---
 llvm/include/llvm/ADT/STLExtras.h | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index fade92d458675f2..d0b79fa91c03130 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -1291,11 +1291,15 @@ class indexed_accessor_range_base {
   }
 
   /// Compare this range with another.
-  template <typename OtherT> bool operator==(const OtherT &rhs) const {
-    return std::equal(begin(), end(), rhs.begin(), rhs.end());
-  }
-  template <typename OtherT> bool operator!=(const OtherT &rhs) const {
-    return !(*this == rhs);
+  template <typename OtherT>
+  friend bool operator==(const indexed_accessor_range_base &lhs,
+                         const OtherT &rhs) {
+    return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+  }
+  template <typename OtherT>
+  friend bool operator!=(const indexed_accessor_range_base &lhs,
+                         const OtherT &rhs) {
+    return !(lhs == rhs);
   }
 
   /// Return the size of this range.

>From 69426793f377a7449a08cd2e8c9a6def5e63b583 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <usx at google.com>
Date: Mon, 23 Oct 2023 18:05:03 +0200
Subject: [PATCH 2/2] Revert "[clang] Handle templated operators with reversed
 arguments (#69595)"

This reverts commit 47747da6340b00e301d3656f95ecf9b04a6ec2bb.
---
 clang/docs/ReleaseNotes.rst     | 21 ---------------------
 clang/lib/Sema/SemaOverload.cpp | 28 ++++++++++------------------
 2 files changed, 10 insertions(+), 39 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c292e012c4548d9..f71b458597e1833 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -37,27 +37,6 @@ These changes are ones which we think may surprise users when upgrading to
 Clang |release| because of the opportunity they pose for disruption to existing
 code bases.
 
-- Fix a bug in reversed argument for templated operators.
-  This breaks code in C++20 which was previously accepted in C++17. Eg:
-
-  .. code-block:: cpp
-
-    struct P {};
-    template<class S> bool operator==(const P&, const S&);
-
-    struct A : public P {};
-    struct B : public P {};
-
-    // This equality is now ambiguous in C++20.
-    bool ambiguous(A a, B b) { return a == b; }
-
-    template<class S> bool operator!=(const P&, const S&);
-    // Ok. Found a matching operator!=.
-    bool fine(A a, B b) { return a == b; }
-
-  To reduce such widespread breakages, as an extension, Clang accepts this code
-  with an existing warning ``-Wambiguous-reversed-operator`` warning.
-  Fixes `GH <https://github.com/llvm/llvm-project/issues/53954>`_.
 
 C/C++ Language Potentially Breaking Changes
 -------------------------------------------
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index d2475459fa4f4f7..db386fef0661c05 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -7685,7 +7685,7 @@ bool Sema::CheckNonDependentConversions(
     QualType ParamType = ParamTypes[I + Offset];
     if (!ParamType->isDependentType()) {
       unsigned ConvIdx = PO == OverloadCandidateParamOrder::Reversed
-                             ? Args.size() - 1 - (ThisConversions + I)
+                             ? 0
                              : (ThisConversions + I);
       Conversions[ConvIdx]
         = TryCopyInitialization(*this, Args[I], ParamType,
@@ -10082,19 +10082,11 @@ getImplicitObjectParamType(ASTContext &Context, const FunctionDecl *F) {
   return M->getFunctionObjectParameterReferenceType();
 }
 
-// As a Clang extension, allow ambiguity among F1 and F2 if they represent
-// represent the same entity.
-static bool allowAmbiguity(ASTContext &Context, const FunctionDecl *F1,
-                           const FunctionDecl *F2) {
+static bool haveSameParameterTypes(ASTContext &Context, const FunctionDecl *F1,
+                                   const FunctionDecl *F2) {
   if (declaresSameEntity(F1, F2))
     return true;
-  if (F1->isTemplateInstantiation() && F2->isTemplateInstantiation() &&
-      declaresSameEntity(F1->getPrimaryTemplate(), F2->getPrimaryTemplate())) {
-    return true;
-  }
-  // TODO: It is not clear whether comparing parameters is necessary (i.e.
-  // different functions with same params). Consider removing this (as no test
-  // fail w/o it).
+
   auto NextParam = [&](const FunctionDecl *F, unsigned &I, bool First) {
     if (First) {
       if (std::optional<QualType> T = getImplicitObjectParamType(Context, F))
@@ -10279,14 +10271,14 @@ bool clang::isBetterOverloadCandidate(
     case ImplicitConversionSequence::Worse:
       if (Cand1.Function && Cand2.Function &&
           Cand1.isReversed() != Cand2.isReversed() &&
-          allowAmbiguity(S.Context, Cand1.Function, Cand2.Function)) {
+          haveSameParameterTypes(S.Context, Cand1.Function, Cand2.Function)) {
         // Work around large-scale breakage caused by considering reversed
         // forms of operator== in C++20:
         //
-        // When comparing a function against a reversed function, if we have a
-        // better conversion for one argument and a worse conversion for the
-        // other, the implicit conversion sequences are treated as being equally
-        // good.
+        // When comparing a function against a reversed function with the same
+        // parameter types, if we have a better conversion for one argument and
+        // a worse conversion for the other, the implicit conversion sequences
+        // are treated as being equally good.
         //
         // This prevents a comparison function from being considered ambiguous
         // with a reversed form that is written in the same way.
@@ -14457,7 +14449,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
           llvm::SmallVector<FunctionDecl*, 4> AmbiguousWith;
           for (OverloadCandidate &Cand : CandidateSet) {
             if (Cand.Viable && Cand.Function && Cand.isReversed() &&
-                allowAmbiguity(Context, Cand.Function, FnDecl)) {
+                haveSameParameterTypes(Context, Cand.Function, FnDecl)) {
               for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
                 if (CompareImplicitConversionSequences(
                         *this, OpLoc, Cand.Conversions[ArgIdx],



More information about the cfe-commits mailing list