[clang] 3c75fea - [clang] Compare constraints before diagnosing mismatched ref qualifiers (GH58962)

Roy Jacobson via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 29 04:57:32 PST 2022


Author: Roy Jacobson
Date: 2022-11-29T14:57:26+02:00
New Revision: 3c75feab3bbda563374f08e46a7c052c0c6f1c36

URL: https://github.com/llvm/llvm-project/commit/3c75feab3bbda563374f08e46a7c052c0c6f1c36
DIFF: https://github.com/llvm/llvm-project/commit/3c75feab3bbda563374f08e46a7c052c0c6f1c36.diff

LOG: [clang] Compare constraints before diagnosing mismatched ref qualifiers (GH58962)

As noticed in GH58962, we should only diagnose illegal overloads of member functions
when the ref qualifiers don't match if the trailing constraints are the same.

The fix is to move the existing constraints check earlier in Sema::IsOverload.

Closes https://github.com/llvm/llvm-project/issues/58962

Reviewed By: erichkeane

Differential Revision: https://reviews.llvm.org/D138749

Added: 
    

Modified: 
    clang/lib/Sema/SemaOverload.cpp
    clang/test/CXX/over/over.load/p2-0x.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a20d7dda79300..1eb68090a8fdb 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1316,6 +1316,17 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
         (!SameTemplateParameterList || !SameReturnType))
       return true;
   }
+
+  if (ConsiderRequiresClauses) {
+    Expr *NewRC = New->getTrailingRequiresClause(),
+         *OldRC = Old->getTrailingRequiresClause();
+    if ((NewRC != nullptr) != (OldRC != nullptr))
+      return true;
+
+    if (NewRC && !AreConstraintExpressionsEqual(Old, OldRC, New, NewRC))
+        return true;
+  }
+
   // If the function is a class member, its signature includes the
   // cv-qualifiers (if any) and ref-qualifier (if any) on the function itself.
   //
@@ -1332,14 +1343,15 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
       if (!UseMemberUsingDeclRules &&
           (OldMethod->getRefQualifier() == RQ_None ||
            NewMethod->getRefQualifier() == RQ_None)) {
-        // C++0x [over.load]p2:
-        //   - Member function declarations with the same name and the same
-        //     parameter-type-list as well as member function template
-        //     declarations with the same name, the same parameter-type-list, and
-        //     the same template parameter lists cannot be overloaded if any of
-        //     them, but not all, have a ref-qualifier (8.3.5).
+        // C++20 [over.load]p2:
+        //   - Member function declarations with the same name, the same
+        //     parameter-type-list, and the same trailing requires-clause (if
+        //     any), as well as member function template declarations with the
+        //     same name, the same parameter-type-list, the same trailing
+        //     requires-clause (if any), and the same template-head, cannot be
+        //     overloaded if any of them, but not all, have a ref-qualifier.
         Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
-          << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
+            << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
         Diag(OldMethod->getLocation(), diag::note_previous_declaration);
       }
       return true;
@@ -1403,23 +1415,6 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
     }
   }
 
-  if (ConsiderRequiresClauses) {
-    Expr *NewRC = New->getTrailingRequiresClause(),
-         *OldRC = Old->getTrailingRequiresClause();
-    if ((NewRC != nullptr) != (OldRC != nullptr))
-      // RC are most certainly 
diff erent - these are overloads.
-      return true;
-
-    if (NewRC) {
-      llvm::FoldingSetNodeID NewID, OldID;
-      NewRC->Profile(NewID, Context, /*Canonical=*/true);
-      OldRC->Profile(OldID, Context, /*Canonical=*/true);
-      if (NewID != OldID)
-        // RCs are not equivalent - these are overloads.
-        return true;
-    }
-  }
-
   // The signatures match; this is not an overload.
   return false;
 }

diff  --git a/clang/test/CXX/over/over.load/p2-0x.cpp b/clang/test/CXX/over/over.load/p2-0x.cpp
index cf38741056aba..183f3cb322af7 100644
--- a/clang/test/CXX/over/over.load/p2-0x.cpp
+++ b/clang/test/CXX/over/over.load/p2-0x.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
 
 // Member function declarations with the same name and the same
 // parameter-type-list as well as mem- ber function template
@@ -22,3 +23,31 @@ class Y {
   void k(); // expected-note{{previous declaration}}
   void k() &&; // expected-error{{cannot overload a member function with ref-qualifier '&&' with a member function without a ref-qualifier}}
 };
+
+
+#if __cplusplus >= 202002L
+namespace GH58962 {
+
+template<typename T>
+__add_rvalue_reference(T) declval();
+
+template<unsigned R>
+struct type
+{
+    void func() requires (R == 0);
+    void func() & requires (R == 1);
+    void func() && requires (R == 2);
+};
+
+template<typename T>
+concept test = requires { declval<T>().func(); };
+
+static_assert(test<type<0>&>);
+static_assert(test<type<0>&&>);
+static_assert(test<type<1>&>);
+static_assert(not test<type<1>&&>);
+static_assert(not test<type<2>&>);
+static_assert(test<type<2>&&>);
+
+}
+#endif


        


More information about the cfe-commits mailing list