https://github.com/cor3ntin updated 
https://github.com/llvm/llvm-project/pull/93430

>From 131f515c1341122896ea3c9624751a634db06cb7 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinja...@gmail.com>
Date: Mon, 27 May 2024 01:16:06 +0200
Subject: [PATCH 1/2] [Clang] Static and explicit object member functions with
 the same parameter-type-lists

Implement wg21.link/P2797.

Because taking the address of an explicit object member function
results in a function pointer, a call expression where
the id-expression is an explicit object member is made to behave
consistently with that model.

This change forces clang to perform overload resolution
in the presence of an ixpression of the form `(&Foo::bar)(args...)`,
which we previously failed to do consistently.
---
 clang/docs/ReleaseNotes.rst                   |  3 +
 clang/include/clang/AST/ExprCXX.h             |  4 +
 clang/include/clang/Sema/Overload.h           |  4 +
 clang/lib/Sema/SemaExpr.cpp                   | 27 ++++++-
 clang/lib/Sema/SemaOverload.cpp               | 74 ++++++++++++++++---
 clang/test/CXX/drs/cwg1xx.cpp                 |  8 +-
 clang/test/CXX/drs/cwg26xx.cpp                | 26 +++++++
 clang/test/CXX/drs/cwg2771.cpp                | 18 +++++
 clang/test/CodeGenCXX/cxx2b-deducing-this.cpp | 20 +++++
 clang/test/SemaCXX/cxx2b-deducing-this.cpp    | 27 +++++++
 clang/www/cxx_dr_status.html                  |  6 +-
 clang/www/cxx_status.html                     |  2 +-
 12 files changed, 197 insertions(+), 22 deletions(-)
 create mode 100644 clang/test/CXX/drs/cwg2771.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 825e91876ffce..0a945a9989b0d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -209,6 +209,9 @@ C++23 Feature Support
 - Added a ``__reference_converts_from_temporary`` builtin, completing the 
necessary compiler support for
   `P2255R2: Type trait to determine if a reference binds to a temporary 
<https://wg21.link/P2255R2>`_.
 
+- Implemented `P2797R0: Static and explicit object member functions with the 
same parameter-type-lists <https://wg21.link/P2797R0>`.
+  This completes the support for "deducing this".
+
 C++2c Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/clang/include/clang/AST/ExprCXX.h 
b/clang/include/clang/AST/ExprCXX.h
index dbf693611a7fa..557e9fd99c293 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -3027,6 +3027,7 @@ class OverloadExpr : public Expr {
   struct FindResult {
     OverloadExpr *Expression;
     bool IsAddressOfOperand;
+    bool IsAddressOfOperandWithParen;
     bool HasFormOfMemberPointer;
   };
 
@@ -3039,6 +3040,7 @@ class OverloadExpr : public Expr {
     assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload));
 
     FindResult Result;
+    bool HasParen = isa<ParenExpr>(E);
 
     E = E->IgnoreParens();
     if (isa<UnaryOperator>(E)) {
@@ -3048,10 +3050,12 @@ class OverloadExpr : public Expr {
 
       Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier());
       Result.IsAddressOfOperand = true;
+      Result.IsAddressOfOperandWithParen = HasParen;
       Result.Expression = Ovl;
     } else {
       Result.HasFormOfMemberPointer = false;
       Result.IsAddressOfOperand = false;
+      Result.IsAddressOfOperandWithParen = false;
       Result.Expression = cast<OverloadExpr>(E);
     }
 
diff --git a/clang/include/clang/Sema/Overload.h 
b/clang/include/clang/Sema/Overload.h
index 76311b00d2fc5..64cdd6cdf043d 100644
--- a/clang/include/clang/Sema/Overload.h
+++ b/clang/include/clang/Sema/Overload.h
@@ -899,6 +899,8 @@ class Sema;
     /// object argument.
     bool IgnoreObjectArgument : 1;
 
+    bool TookAddressOfOverload : 1;
+
     /// True if the candidate was found using ADL.
     CallExpr::ADLCallKind IsADLCandidate : 1;
 
@@ -999,6 +1001,8 @@ class Sema;
       /// Initialization of an object of class type by constructor,
       /// using either a parenthesized or braced list of arguments.
       CSK_InitByConstructor,
+
+      CSK_AddressOfOverloadSet,
     };
 
     /// Information about operator rewrites to consider when adding operator
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 410f80ae864a1..15496f3323b02 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5813,6 +5813,24 @@ static TypoCorrection TryTypoCorrectionForCall(Sema &S, 
Expr *Fn,
   return TypoCorrection();
 }
 
+static bool isParenthetizedAndQualifiedAddressOfExpr(Expr *Fn) {
+  if (!isa<ParenExpr>(Fn))
+    return false;
+
+  Fn = Fn->IgnoreParens();
+  auto *UO = dyn_cast<UnaryOperator>(Fn);
+  if (!UO)
+    return false;
+  assert(cast<UnaryOperator>(Fn)->getOpcode() == UO_AddrOf);
+  if (auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens())) {
+    return DRE->hasQualifier();
+  }
+  if (auto *OVL = dyn_cast<OverloadExpr>(UO->getSubExpr()->IgnoreParens())) {
+    return OVL->getQualifier();
+  }
+  return false;
+}
+
 /// ConvertArgumentsForCall - Converts the arguments specified in
 /// Args/NumArgs to the parameter types of the function FDecl with
 /// function prototype Proto. Call is the call expression itself, and
@@ -5834,9 +5852,12 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
 
   // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
   // assignment, to the types of the corresponding parameter, ...
+
+  bool AddressOf = isParenthetizedAndQualifiedAddressOfExpr(Fn);
   bool HasExplicitObjectParameter =
-      FDecl && FDecl->hasCXXExplicitFunctionObjectParameter();
-  unsigned ExplicitObjectParameterOffset = HasExplicitObjectParameter ? 1 : 0;
+      !AddressOf && FDecl && FDecl->hasCXXExplicitFunctionObjectParameter();
+  unsigned ExplicitObjectParameterOffset =
+      HasExplicitObjectParameter && !AddressOf ? 1 : 0;
   unsigned NumParams = Proto->getNumParams();
   bool Invalid = false;
   unsigned MinArgs = FDecl ? FDecl->getMinRequiredArguments() : NumParams;
@@ -6546,7 +6567,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, 
SourceLocation LParenLoc,
     OverloadExpr::FindResult find = OverloadExpr::find(Fn);
 
     // We aren't supposed to apply this logic if there's an '&' involved.
-    if (!find.HasFormOfMemberPointer) {
+    if (!find.HasFormOfMemberPointer || find.IsAddressOfOperandWithParen) {
       if (Expr::hasAnyTypeDependentArguments(ArgExprs))
         return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
                                 VK_PRValue, RParenLoc, 
CurFPFeatureOverrides());
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 0c89fca8d38eb..17cccefa8e929 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6971,6 +6971,7 @@ void Sema::AddOverloadCandidate(
   Candidate.IsSurrogate = false;
   Candidate.IsADLCandidate = IsADLCandidate;
   Candidate.IgnoreObjectArgument = false;
+  Candidate.TookAddressOfOverload = false;
   Candidate.ExplicitCallArguments = Args.size();
 
   // Explicit functions are not actually candidates at all if we're not
@@ -7545,10 +7546,19 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, 
DeclAccessPair FoundDecl,
       CandidateSet.getRewriteInfo().getRewriteKind(Method, PO);
   Candidate.IsSurrogate = false;
   Candidate.IgnoreObjectArgument = false;
+  Candidate.TookAddressOfOverload =
+      CandidateSet.getKind() == OverloadCandidateSet::CSK_AddressOfOverloadSet;
   Candidate.ExplicitCallArguments = Args.size();
 
-  unsigned NumParams = Method->getNumExplicitParams();
-  unsigned ExplicitOffset = Method->isExplicitObjectMemberFunction() ? 1 : 0;
+  bool IgnoreExplicitObject =
+      (Method->isExplicitObjectMemberFunction() &&
+       CandidateSet.getKind() ==
+           OverloadCandidateSet::CSK_AddressOfOverloadSet);
+  unsigned ExplicitOffset =
+      !IgnoreExplicitObject && Method->isExplicitObjectMemberFunction() ? 1 : 
0;
+  unsigned NumParams = Method->getNumParams() - ExplicitOffset;
+  if (CandidateSet.getKind() == OverloadCandidateSet::CSK_AddressOfOverloadSet)
+    NumParams += int(Method->isImplicitObjectMemberFunction());
 
   // (C++ 13.3.2p2): A candidate function having fewer than m
   // parameters is viable only if it has an ellipsis in its parameter
@@ -7566,7 +7576,12 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, 
DeclAccessPair FoundDecl,
   // (8.3.6). For the purposes of overload resolution, the
   // parameter list is truncated on the right, so that there are
   // exactly m parameters.
-  unsigned MinRequiredArgs = Method->getMinRequiredExplicitArguments();
+  unsigned MinRequiredArgs = Method->getMinRequiredArguments() - 
ExplicitOffset;
+  if (CandidateSet.getKind() ==
+          OverloadCandidateSet::CSK_AddressOfOverloadSet &&
+      Method->isImplicitObjectMemberFunction())
+    MinRequiredArgs++;
+
   if (Args.size() < MinRequiredArgs && !PartialOverloading) {
     // Not enough arguments.
     Candidate.Viable = false;
@@ -7636,7 +7651,16 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, 
DeclAccessPair FoundDecl,
       // exist for each argument an implicit conversion sequence
       // (13.3.3.1) that converts that argument to the corresponding
       // parameter of F.
-      QualType ParamType = Proto->getParamType(ArgIdx + ExplicitOffset);
+      QualType ParamType;
+      if (CandidateSet.getKind() ==
+              OverloadCandidateSet::CSK_AddressOfOverloadSet &&
+          Method->isImplicitObjectMemberFunction()) {
+        ParamType = ArgIdx == 0
+                        ? Method->getFunctionObjectParameterReferenceType()
+                        : Proto->getParamType(ArgIdx - 1);
+      } else {
+        ParamType = Proto->getParamType(ArgIdx + ExplicitOffset);
+      }
       Candidate.Conversions[ConvIdx]
         = TryCopyInitialization(*this, Args[ArgIdx], ParamType,
                                 SuppressUserConversions,
@@ -7998,6 +8022,7 @@ void Sema::AddConversionCandidate(
   Candidate.Function = Conversion;
   Candidate.IsSurrogate = false;
   Candidate.IgnoreObjectArgument = false;
+  Candidate.TookAddressOfOverload = false;
   Candidate.FinalConversion.setAsIdentityConversion();
   Candidate.FinalConversion.setFromType(ConvType);
   Candidate.FinalConversion.setAllToTypes(ToType);
@@ -8200,6 +8225,7 @@ void Sema::AddTemplateConversionCandidate(
     Candidate.FailureKind = ovl_fail_bad_deduction;
     Candidate.IsSurrogate = false;
     Candidate.IgnoreObjectArgument = false;
+    Candidate.TookAddressOfOverload = false;
     Candidate.ExplicitCallArguments = 1;
     Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
                                                           Info);
@@ -8240,6 +8266,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl 
*Conversion,
   Candidate.Viable = true;
   Candidate.IsSurrogate = true;
   Candidate.IgnoreObjectArgument = false;
+  Candidate.TookAddressOfOverload = false;
   Candidate.ExplicitCallArguments = Args.size();
 
   // Determine the implicit conversion sequence for the implicit
@@ -8465,6 +8492,7 @@ void Sema::AddBuiltinCandidate(QualType *ParamTys, 
ArrayRef<Expr *> Args,
   Candidate.Function = nullptr;
   Candidate.IsSurrogate = false;
   Candidate.IgnoreObjectArgument = false;
+  Candidate.TookAddressOfOverload = false;
   std::copy(ParamTys, ParamTys + Args.size(), Candidate.BuiltinParamTypes);
 
   // Determine the implicit conversion sequences for each of the
@@ -10929,6 +10957,12 @@ OverloadCandidateSet::BestViableFunction(Sema &S, 
SourceLocation Loc,
   if (Best->Function && Best->Function->isDeleted())
     return OR_Deleted;
 
+  if (auto *M = dyn_cast_or_null<CXXMethodDecl>(Best->Function);
+      Kind == CSK_AddressOfOverloadSet && M &&
+      M->isImplicitObjectMemberFunction()) {
+    return OR_No_Viable_Function;
+  }
+
   if (!EquivalentCands.empty())
     S.diagnoseEquivalentInternalLinkageDeclarations(Loc, Best->Function,
                                                     EquivalentCands);
@@ -11538,7 +11572,8 @@ static bool CheckArityMismatch(Sema &S, 
OverloadCandidate *Cand,
 
 /// General arity mismatch diagnosis over a candidate in a candidate set.
 static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D,
-                                  unsigned NumFormalArgs) {
+                                  unsigned NumFormalArgs,
+                                  bool IsAddressOf = false) {
   assert(isa<FunctionDecl>(D) &&
       "The templated declaration should at least be a function"
       " when diagnosing bad template argument deduction due to too many"
@@ -11551,7 +11586,8 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl 
*Found, Decl *D,
   unsigned MinParams = Fn->getMinRequiredExplicitArguments();
 
   // at least / at most / exactly
-  bool HasExplicitObjectParam = Fn->hasCXXExplicitFunctionObjectParameter();
+  bool HasExplicitObjectParam =
+      !IsAddressOf && Fn->hasCXXExplicitFunctionObjectParameter();
   unsigned ParamCount = FnTy->getNumParams() - (HasExplicitObjectParam ? 1 : 
0);
   unsigned mode, modeCount;
   if (NumFormalArgs < MinParams) {
@@ -11593,7 +11629,8 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl 
*Found, Decl *D,
 static void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
                                   unsigned NumFormalArgs) {
   if (!CheckArityMismatch(S, Cand, NumFormalArgs))
-    DiagnoseArityMismatch(S, Cand->FoundDecl, Cand->Function, NumFormalArgs);
+    DiagnoseArityMismatch(S, Cand->FoundDecl, Cand->Function, NumFormalArgs,
+                          Cand->TookAddressOfOverload);
 }
 
 static TemplateDecl *getDescribedTemplate(Decl *Templated) {
@@ -14076,6 +14113,21 @@ static ExprResult FinishOverloadedCallExpr(Sema 
&SemaRef, Scope *S, Expr *Fn,
   }
 
   case OR_No_Viable_Function: {
+    if (*Best != CandidateSet->end() &&
+        CandidateSet->getKind() ==
+            clang::OverloadCandidateSet::CSK_AddressOfOverloadSet) {
+      if (CXXMethodDecl *M =
+              dyn_cast_if_present<CXXMethodDecl>((*Best)->Function);
+          M && M->isImplicitObjectMemberFunction()) {
+        CandidateSet->NoteCandidates(
+            PartialDiagnosticAt(
+                Fn->getBeginLoc(),
+                SemaRef.PDiag(diag::err_member_call_without_object) << 0 << M),
+            SemaRef, OCD_AmbiguousCandidates, Args);
+        return ExprError();
+      }
+    }
+
     // Try to recover by looking for viable functions which the user might
     // have meant to call.
     ExprResult Recovery = BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc,
@@ -14167,8 +14219,10 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, 
Expr *Fn,
                                          Expr *ExecConfig,
                                          bool AllowTypoCorrection,
                                          bool CalleesAddressIsTaken) {
-  OverloadCandidateSet CandidateSet(Fn->getExprLoc(),
-                                    OverloadCandidateSet::CSK_Normal);
+  OverloadCandidateSet CandidateSet(
+      Fn->getExprLoc(), CalleesAddressIsTaken
+                            ? OverloadCandidateSet::CSK_AddressOfOverloadSet
+                            : OverloadCandidateSet::CSK_Normal);
   ExprResult result;
 
   if (buildOverloadedCallSet(S, Fn, ULE, Args, LParenLoc, &CandidateSet,
@@ -16333,7 +16387,7 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr 
*E, DeclAccessPair Found,
     assert(UnOp->getOpcode() == UO_AddrOf &&
            "Can only take the address of an overloaded function");
     if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
-      if (Method->isStatic()) {
+      if (!Method->isImplicitObjectMemberFunction()) {
         // Do nothing: static member functions aren't any different
         // from non-member functions.
       } else {
diff --git a/clang/test/CXX/drs/cwg1xx.cpp b/clang/test/CXX/drs/cwg1xx.cpp
index a8f9b705a9866..21859fc6b1cbf 100644
--- a/clang/test/CXX/drs/cwg1xx.cpp
+++ b/clang/test/CXX/drs/cwg1xx.cpp
@@ -843,23 +843,21 @@ namespace cwg161 { // cwg161: 3.1
   };
 }
 
-namespace cwg162 { // cwg162: no
+namespace cwg162 { // cwg162: 19
   struct A {
     char &f(char);
     static int &f(int);
 
     void g() {
       int &a = (&A::f)(0);
-      // FIXME: expected-error@-1 {{reference to overloaded function could not 
be resolved; did you mean to call it?}}
       char &b = (&A::f)('0');
-      // expected-error@-1 {{reference to overloaded function could not be 
resolved; did you mean to call it?}}
+      // expected-error@-1 {{non-const lvalue reference to type 'char' cannot 
bind to a value of unrelated type 'int'}}
     }
   };
 
   int &c = (&A::f)(0);
-  // FIXME: expected-error@-1 {{reference to overloaded function could not be 
resolved; did you mean to call it?}}
   char &d = (&A::f)('0');
-  // expected-error@-1 {{reference to overloaded function could not be 
resolved; did you mean to call it?}}
+  // expected-error@-1 {{non-const lvalue reference to type 'char' cannot bind 
to a value of unrelated type 'int'}}
 }
 
 // cwg163: na
diff --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp
index d3c5b5bb7b6b9..6c91377643fb9 100644
--- a/clang/test/CXX/drs/cwg26xx.cpp
+++ b/clang/test/CXX/drs/cwg26xx.cpp
@@ -240,3 +240,29 @@ void test() {
 }
 }
 #endif
+
+
+#if __cplusplus >= 202302L
+namespace cwg2692 { // cwg2692: 19
+
+ struct A {
+    static void f(A); // #cwg2692-1
+    void f(this A); // #cwg2692-2
+
+    void g();
+  };
+
+  void A::g() {
+    (&A::f)(A()); // expected-error {{call to 'f' is ambiguous}}
+                  // expected-note@#cwg2692-1 {{candidate}}
+                  // expected-note@#cwg2692-2 {{candidate}}
+
+
+
+    (&A::f)();    // expected-error {{no matching function for call to 'f'}}
+                  // expected-note@#cwg2692-1 {{candidate function not viable: 
requires 1 argument, but 0 were provided}}
+                  // expected-note@#cwg2692-2 {{candidate function not viable: 
requires at most 1 argument, but 0 were provided}}
+  }
+
+}
+#endif
diff --git a/clang/test/CXX/drs/cwg2771.cpp b/clang/test/CXX/drs/cwg2771.cpp
new file mode 100644
index 0000000000000..e877e6fe4a5fe
--- /dev/null
+++ b/clang/test/CXX/drs/cwg2771.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++23 %s -ast-dump | FileCheck --check-prefixes=CXX23 
%s
+
+namespace cwg2771 { // cwg2771: 18
+
+struct A{
+    int a;
+    void cwg2771(){
+      int* r = &a;
+    }
+};
+// CXX23: CXXMethodDecl{{.+}}cwg2771
+// CXX23-NEXT: CompoundStmt
+// CXX23-NEXT: DeclStmt
+// CXX23-NEXT: VarDecl
+// CXX23-NEXT: UnaryOperator
+// CXX23-NEXT: MemberExpr
+// CXX23-NEXT: CXXThisExpr{{.+}}'cwg2771::A *'
+}
diff --git a/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp 
b/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp
index 649fe2afbf4e9..f9f9fbd7397f8 100644
--- a/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp
+++ b/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp
@@ -245,3 +245,23 @@ void f() {
   d();
 }
 }
+
+
+namespace P2797 {
+struct C {
+  void c(this const C&);    // #first
+  void c() &;               // #second
+  static void c(int = 0);   // #third
+
+  void d() {
+    (&C::c)(C{});
+    (&C::c)();
+  }
+};
+void test() {
+    (void)C{}.d();
+}
+// CHECK-LABEL: {{.*}} @_ZN5P27971C1dEv
+// CHECK: call void @_ZNH5P27971C1cERKS0_
+// CHECK: call void @_ZN5P27971C1cEi
+}
diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp 
b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
index cdb9d1324b974..86046497c2ef2 100644
--- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp
+++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
@@ -893,3 +893,30 @@ void g() {
   a * lval;
 }
 }
+
+namespace P2797 {
+struct C {
+  void c(this const C&);    // #first
+  void c() &;               // #second
+  static void c(int = 0);   // #third
+
+  void d() {
+    c();                // expected-error {{call to member function 'c' is 
ambiguous}}
+                        // expected-note@#first {{candidate function}}
+                        // expected-note@#second {{candidate function}}
+                        // expected-note@#third {{candidate function}}
+
+    (C::c)();           // expected-error {{call to member function 'c' is 
ambiguous}}
+                        // expected-note@#first {{candidate function}}
+                        // expected-note@#second {{candidate function}}
+                        // expected-note@#third {{candidate function}}
+
+    (&(C::c))();        // expected-error {{cannot create a non-constant 
pointer to member function}}
+    (&C::c)(C{});
+    (&C::c)(*this);     // expected-error {{call to non-static member function 
without an object argument}}
+                        // expected-note@#second {{candidate function}}
+
+    (&C::c)();
+  }
+};
+}
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 4cce88fe0490f..7df6c0a05a487 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -1010,7 +1010,7 @@ <h2 id="cxxdr">C++ defect report implementation 
status</h2>
     <td><a href="https://cplusplus.github.io/CWG/issues/162.html";>162</a></td>
     <td>CD1</td>
     <td>(<TT>&amp;C::f)()</TT> with nonstatic members</td>
-    <td class="none" align="center">No</td>
+    <td class="unreleased" align="center">Clang 19</td>
   </tr>
   <tr id="163">
     <td><a href="https://cplusplus.github.io/CWG/issues/163.html";>163</a></td>
@@ -15960,7 +15960,7 @@ <h2 id="cxxdr">C++ defect report implementation 
status</h2>
     <td><a 
href="https://cplusplus.github.io/CWG/issues/2692.html";>2692</a></td>
     <td>C++23</td>
     <td>Static and explicit object member functions with the same 
parameter-type-lists</td>
-    <td class="unknown" align="center">Unknown</td>
+    <td class="unreleased" align="center">Clang 19</td>
   </tr>
   <tr class="open" id="2693">
     <td><a 
href="https://cplusplus.github.io/CWG/issues/2693.html";>2693</a></td>
@@ -16435,7 +16435,7 @@ <h2 id="cxxdr">C++ defect report implementation 
status</h2>
     <td><a 
href="https://cplusplus.github.io/CWG/issues/2771.html";>2771</a></td>
     <td>DR</td>
     <td>Transformation for <I>unqualified-id</I>s in address operator</td>
-    <td class="unknown" align="center">Unknown</td>
+    <td class="full" align="center">Clang 18</td>
   </tr>
   <tr id="2772">
     <td><a 
href="https://cplusplus.github.io/CWG/issues/2772.html";>2772</a></td>
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index 45416170b16e5..65dd31a0fb802 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -283,7 +283,7 @@ <h2 id="cxx23">C++23 implementation status</h2>
     </tr>
     <tr>
       <td><a href="https://wg21.link/P2797R0";>P2797R0</a></td>
-      <td class="none" align="center">No</td>
+      <td class="unreleased" align="center">Clang 19</td>
     </tr>
     <tr>
       <td rowspan=2>Change scope of lambda trailing-return-type</td>

>From 5bdf858ae5677e601132009892f957932209e454 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinja...@gmail.com>
Date: Tue, 28 May 2024 15:04:19 +0200
Subject: [PATCH 2/2] fix tests

---
 clang/lib/Sema/SemaExpr.cpp                |  3 +--
 clang/lib/Sema/SemaOverload.cpp            | 31 +++++++++++++++++-----
 clang/test/CXX/drs/cwg26xx.cpp             |  2 +-
 clang/test/SemaCXX/cxx2b-deducing-this.cpp |  2 --
 4 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 15496f3323b02..eb5ae072a465b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5819,9 +5819,8 @@ static bool isParenthetizedAndQualifiedAddressOfExpr(Expr 
*Fn) {
 
   Fn = Fn->IgnoreParens();
   auto *UO = dyn_cast<UnaryOperator>(Fn);
-  if (!UO)
+  if (!UO || UO->getOpcode() != clang::UO_AddrOf)
     return false;
-  assert(cast<UnaryOperator>(Fn)->getOpcode() == UO_AddrOf);
   if (auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens())) {
     return DRE->hasQualifier();
   }
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 17cccefa8e929..21a9fe09d1bc2 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -7741,6 +7741,7 @@ void Sema::AddMethodTemplateCandidate(
     Candidate.IgnoreObjectArgument =
         cast<CXXMethodDecl>(Candidate.Function)->isStatic() ||
         ObjectType.isNull();
+    Candidate.TookAddressOfOverload = false;
     Candidate.ExplicitCallArguments = Args.size();
     if (Result == TemplateDeductionResult::NonDependentConversionFailure)
       Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -7831,6 +7832,7 @@ void Sema::AddTemplateOverloadCandidate(
     Candidate.IgnoreObjectArgument =
         isa<CXXMethodDecl>(Candidate.Function) &&
         !isa<CXXConstructorDecl>(Candidate.Function);
+    Candidate.TookAddressOfOverload = false;
     Candidate.ExplicitCallArguments = Args.size();
     if (Result == TemplateDeductionResult::NonDependentConversionFailure)
       Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -11542,9 +11544,10 @@ static void DiagnoseBadConversion(Sema &S, 
OverloadCandidate *Cand,
 /// candidates. This is not covered by the more general DiagnoseArityMismatch()
 /// over a candidate in any candidate set.
 static bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand,
-                               unsigned NumArgs) {
+                               unsigned NumArgs, bool IsAddressOf = false) {
   FunctionDecl *Fn = Cand->Function;
-  unsigned MinParams = Fn->getMinRequiredArguments();
+  unsigned MinParams = Fn->getMinRequiredExplicitArguments() +
+                       ((IsAddressOf && !Fn->isStatic()) ? 1 : 0);
 
   // With invalid overloaded operators, it's possible that we think we
   // have an arity mismatch when in fact it looks like we have the
@@ -11583,13 +11586,17 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl 
*Found, Decl *D,
 
   // TODO: treat calls to a missing default constructor as a special case
   const auto *FnTy = Fn->getType()->castAs<FunctionProtoType>();
-  unsigned MinParams = Fn->getMinRequiredExplicitArguments();
+  unsigned MinParams = Fn->getMinRequiredExplicitArguments() +
+                       ((IsAddressOf && !Fn->isStatic()) ? 1 : 0);
 
   // at least / at most / exactly
   bool HasExplicitObjectParam =
       !IsAddressOf && Fn->hasCXXExplicitFunctionObjectParameter();
-  unsigned ParamCount = FnTy->getNumParams() - (HasExplicitObjectParam ? 1 : 
0);
+
+  unsigned ParamCount =
+      Fn->getNumNonObjectParams() + ((IsAddressOf && !Fn->isStatic()) ? 1 : 0);
   unsigned mode, modeCount;
+
   if (NumFormalArgs < MinParams) {
     if (MinParams != ParamCount || FnTy->isVariadic() ||
         FnTy->isTemplateVariadic())
@@ -11609,7 +11616,7 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl 
*Found, Decl *D,
   std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
       ClassifyOverloadCandidate(S, Found, Fn, CRK_None, Description);
 
-  if (modeCount == 1 &&
+  if (modeCount == 1 && !IsAddressOf &&
       Fn->getParamDecl(HasExplicitObjectParam ? 1 : 0)->getDeclName())
     S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one)
         << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
@@ -11628,7 +11635,7 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl 
*Found, Decl *D,
 /// Arity mismatch diagnosis specific to a function overload candidate.
 static void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
                                   unsigned NumFormalArgs) {
-  if (!CheckArityMismatch(S, Cand, NumFormalArgs))
+  if (!CheckArityMismatch(S, Cand, NumFormalArgs, Cand->TookAddressOfOverload))
     DiagnoseArityMismatch(S, Cand->FoundDecl, Cand->Function, NumFormalArgs,
                           Cand->TookAddressOfOverload);
 }
@@ -12070,6 +12077,13 @@ static void NoteFunctionCandidate(Sema &S, 
OverloadCandidate *Cand,
       Cand->FailureKind != ovl_fail_bad_conversion)
     return;
 
+  // Skip implicit member functions when trying to resolve
+  // the address of a an overload set for a function pointer.
+  if (Cand->TookAddressOfOverload &&
+      !Cand->Function->hasCXXExplicitFunctionObjectParameter() &&
+      !Cand->Function->isStatic())
+    return;
+
   // Note deleted candidates, but only if they're viable.
   if (Cand->Viable) {
     if (Fn->isDeleted()) {
@@ -16447,7 +16461,10 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr 
*E, DeclAccessPair Found,
     }
 
     QualType Type = Fn->getType();
-    ExprValueKind ValueKind = getLangOpts().CPlusPlus ? VK_LValue : VK_PRValue;
+    ExprValueKind ValueKind =
+        getLangOpts().CPlusPlus && !Fn->hasCXXExplicitFunctionObjectParameter()
+            ? VK_LValue
+            : VK_PRValue;
 
     // FIXME: Duplicated from BuildDeclarationNameExpr.
     if (unsigned BID = Fn->getBuiltinID()) {
diff --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp
index 6c91377643fb9..76c02ec2f4ea9 100644
--- a/clang/test/CXX/drs/cwg26xx.cpp
+++ b/clang/test/CXX/drs/cwg26xx.cpp
@@ -261,7 +261,7 @@ namespace cwg2692 { // cwg2692: 19
 
     (&A::f)();    // expected-error {{no matching function for call to 'f'}}
                   // expected-note@#cwg2692-1 {{candidate function not viable: 
requires 1 argument, but 0 were provided}}
-                  // expected-note@#cwg2692-2 {{candidate function not viable: 
requires at most 1 argument, but 0 were provided}}
+                  // expected-note@#cwg2692-2 {{candidate function not viable: 
requires 1 argument, but 0 were provided}}
   }
 
 }
diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp 
b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
index 86046497c2ef2..2c19b091fabad 100644
--- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp
+++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
@@ -914,8 +914,6 @@ struct C {
     (&(C::c))();        // expected-error {{cannot create a non-constant 
pointer to member function}}
     (&C::c)(C{});
     (&C::c)(*this);     // expected-error {{call to non-static member function 
without an object argument}}
-                        // expected-note@#second {{candidate function}}
-
     (&C::c)();
   }
 };

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

Reply via email to