[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-07-25 Thread Krystian Stasiowski via cfe-commits


@@ -10339,24 +10339,53 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
   if (Previous.empty()) {
 // Nowhere to look anyway.
   } else if (FunctionDecl *Function = dyn_cast(Member)) {
+SmallVector Candidates;
+bool Ambiguous = false;
 for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
-  NamedDecl *D = (*I)->getUnderlyingDecl();
-  if (CXXMethodDecl *Method = dyn_cast(D)) {
-QualType Adjusted = Function->getType();
-if (!hasExplicitCallingConv(Adjusted))
-  Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
-// This doesn't handle deduced return types, but both function
-// declarations should be undeduced at this point.
-if (Context.hasSameType(Adjusted, Method->getType())) {
-  FoundInstantiation = *I;
-  Instantiation = Method;
-  InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
-  MSInfo = Method->getMemberSpecializationInfo();
-  break;
-}
+  CXXMethodDecl *Method =
+  dyn_cast((*I)->getUnderlyingDecl());
+  if (!Method)
+continue;
+  QualType Adjusted = Function->getType();
+  if (!hasExplicitCallingConv(Adjusted))
+Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+  // This doesn't handle deduced return types, but both function
+  // declarations should be undeduced at this point.
+  if (!Context.hasSameType(Adjusted, Method->getType()))
+continue;
+  if (ConstraintSatisfaction Satisfaction;
+  Method->getTrailingRequiresClause() &&
+  (CheckFunctionConstraints(Method, Satisfaction,
+/*UsageLoc=*/Member->getLocation(),
+/*ForOverloadResolution=*/true) ||
+   !Satisfaction.IsSatisfied))
+continue;
+  Candidates.push_back(Method);
+  FunctionDecl *MoreConstrained =
+  Instantiation ? getMoreConstrainedFunction(
+  Method, cast(Instantiation))
+: Method;
+  if (!MoreConstrained) {
+Ambiguous = true;
+continue;
+  }
+  if (MoreConstrained == Method) {
+Ambiguous = false;

sdkrystian wrote:

Whoops, good catch! I'll open a patch to fix this :)

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-07-24 Thread Richard Smith via cfe-commits


@@ -10339,24 +10339,53 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
   if (Previous.empty()) {
 // Nowhere to look anyway.
   } else if (FunctionDecl *Function = dyn_cast(Member)) {
+SmallVector Candidates;
+bool Ambiguous = false;
 for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
-  NamedDecl *D = (*I)->getUnderlyingDecl();
-  if (CXXMethodDecl *Method = dyn_cast(D)) {
-QualType Adjusted = Function->getType();
-if (!hasExplicitCallingConv(Adjusted))
-  Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
-// This doesn't handle deduced return types, but both function
-// declarations should be undeduced at this point.
-if (Context.hasSameType(Adjusted, Method->getType())) {
-  FoundInstantiation = *I;
-  Instantiation = Method;
-  InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
-  MSInfo = Method->getMemberSpecializationInfo();
-  break;
-}
+  CXXMethodDecl *Method =
+  dyn_cast((*I)->getUnderlyingDecl());
+  if (!Method)
+continue;
+  QualType Adjusted = Function->getType();
+  if (!hasExplicitCallingConv(Adjusted))
+Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+  // This doesn't handle deduced return types, but both function
+  // declarations should be undeduced at this point.
+  if (!Context.hasSameType(Adjusted, Method->getType()))
+continue;
+  if (ConstraintSatisfaction Satisfaction;
+  Method->getTrailingRequiresClause() &&
+  (CheckFunctionConstraints(Method, Satisfaction,
+/*UsageLoc=*/Member->getLocation(),
+/*ForOverloadResolution=*/true) ||
+   !Satisfaction.IsSatisfied))
+continue;
+  Candidates.push_back(Method);
+  FunctionDecl *MoreConstrained =
+  Instantiation ? getMoreConstrainedFunction(
+  Method, cast(Instantiation))
+: Method;
+  if (!MoreConstrained) {
+Ambiguous = true;
+continue;
+  }
+  if (MoreConstrained == Method) {
+Ambiguous = false;

zygoloid wrote:

This doesn't look right to me. Suppose we see declaration `A` then `B` then 
`C`, and `A` and `B` are ambiguous and `C` is more constrained than `A`. This 
code will pick `C` as the found instantiation, even though `C` might not be 
more constrained than `B`.

I think we need to do the same two-pass dance we do in overload resolution: 
first do a walk through the declarations tracking the best so far, then go 
through them again and make sure the best so far is actually better than 
everything else.

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian closed 
https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From 5957a414940e4b113eb4ae7db65a36bfb332b8d4 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 01/11] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829..7bfec4e11f7aa 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a416df2e97c43..5c70588bd28b8 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 5c72270ff1504..5fd3121661efc 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10312,6 +10312,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10346,15 +10365,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !IsMor

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Erich Keane via cfe-commits

https://github.com/erichkeane approved this pull request.

happy now :) 

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From 01db101ca28f26181dfedeaef1ec49a5ae42ee99 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 01/11] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c97260282..7bfec4e11f7a 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a416df2e97c4..5c70588bd28b 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e647ac267ab3..eeadc47e9906 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10354,6 +10354,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10388,15 +10407,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !IsMoreConst

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Erich Keane via cfe-commits


@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+
+template
+concept C = I >= 4;
+
+template
+concept D = I < 8;
+
+template
+struct A {
+  constexpr static int f() { return 0; }
+  constexpr static int f() requires C && D { return 1; }
+  constexpr static int f() requires C { return 2; }
+
+  constexpr static int g() requires C { return 0; } // expected-note 
{{member function specialization matches 'g'}}

erichkeane wrote:

Ah, please use the bookmark tags for these notes, I already got confused here: 
) 

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From 01db101ca28f26181dfedeaef1ec49a5ae42ee99 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 01/10] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c97260282..7bfec4e11f7a 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a416df2e97c4..5c70588bd28b 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e647ac267ab3..eeadc47e9906 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10354,6 +10354,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10388,15 +10407,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !IsMoreConst

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From 01db101ca28f26181dfedeaef1ec49a5ae42ee99 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 1/9] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829e..7bfec4e11f7aab 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a416df2e97c439..5c70588bd28b84 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e647ac267ab395..eeadc47e99069c 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10354,6 +10354,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10388,15 +10407,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !I

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

@erichkeane  I added two release notes (one for the bug fix to constraint 
substitution, and one for allowing explicit specializations of constrained 
member functions). 

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From 01db101ca28f26181dfedeaef1ec49a5ae42ee99 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 1/8] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c97260282..7bfec4e11f7a 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a416df2e97c4..5c70588bd28b 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e647ac267ab3..eeadc47e9906 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10354,6 +10354,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10388,15 +10407,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !IsMoreConstra

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

Oh, forgot about the release note :) I'll add one

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Erich Keane via cfe-commits


@@ -5437,6 +5437,11 @@ def note_function_template_spec_matched : Note<
 def err_function_template_partial_spec : Error<
 "function template partial specialization is not allowed">;
 
+def err_function_member_spec_ambiguous : Error<
+"ambiguous member function specialization of %q0">;

erichkeane wrote:

```suggestion
"ambiguous member function specialization of %0">;
```

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Erich Keane via cfe-commits

https://github.com/erichkeane edited 
https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Erich Keane via cfe-commits

https://github.com/erichkeane approved this pull request.

Do we need a release note?  Else LGTM.

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

There is a crash that occurs in the clang-tidy test suite. It will go away once 
#91339 is merged (I plan to merge that first).

This will also fix #90349.

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From 01db101ca28f26181dfedeaef1ec49a5ae42ee99 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 1/7] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829..7bfec4e11f7aa 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a416df2e97c43..5c70588bd28b8 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e647ac267ab39..eeadc47e99069 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10354,6 +10354,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10388,15 +10407,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !IsMoreC

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From 01db101ca28f26181dfedeaef1ec49a5ae42ee99 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 1/8] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829..7bfec4e11f7aa 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a416df2e97c43..5c70588bd28b8 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e647ac267ab39..eeadc47e99069 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10354,6 +10354,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10388,15 +10407,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !IsMoreC

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 458d70674190c4d043d5dfd2e41aecddff5cdb69 
2a471bb4e23a2f50d90ea42827d8dcb4c6341af9 -- 
clang/test/CXX/temp/temp.spec/temp.expl.spec/p14-23.cpp 
clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp 
clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaConcept.cpp 
clang/lib/Sema/SemaOverload.cpp clang/lib/Sema/SemaTemplate.cpp 
clang/lib/Sema/SemaTemplateDeduction.cpp 
clang/lib/Sema/SemaTemplateInstantiate.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 9071c524d8..8f5746ff96 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -10705,7 +10705,7 @@ bool clang::isBetterOverloadCandidate(
   if (!Cand1IsSpecialization && !Cand2IsSpecialization &&
   sameFunctionParameterTypeLists(S, Cand1, Cand2) &&
   (Cand1.Function->getTrailingRequiresClause() ||
-  Cand2.Function->getTrailingRequiresClause()) &&
+   Cand2.Function->getTrailingRequiresClause()) &&
   S.getMoreConstrainedFunction(Cand1.Function, Cand2.Function) ==
   Cand1.Function)
 return true;

``




https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From 01db101ca28f26181dfedeaef1ec49a5ae42ee99 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 1/8] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829..7bfec4e11f7aa 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a416df2e97c43..5c70588bd28b8 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e647ac267ab39..eeadc47e99069 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10354,6 +10354,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10388,15 +10407,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !IsMoreC

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From 01db101ca28f26181dfedeaef1ec49a5ae42ee99 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 1/7] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829e..7bfec4e11f7aab 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a416df2e97c439..5c70588bd28b84 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e647ac267ab395..eeadc47e99069c 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10354,6 +10354,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10388,15 +10407,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !I

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-07 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From bcffb80bba2a6f9ce9eddad61b99a3e59a58f8a0 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 1/7] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829..7bfec4e11f7aa 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a416df2e97c43..5c70588bd28b8 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e647ac267ab39..eeadc47e99069 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10354,6 +10354,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10388,15 +10407,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !IsMoreC

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-06 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From bcffb80bba2a6f9ce9eddad61b99a3e59a58f8a0 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 1/6] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829e..7bfec4e11f7aab 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a416df2e97c439..5c70588bd28b84 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e647ac267ab395..eeadc47e99069c 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10354,6 +10354,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10388,15 +10407,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !I

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-06 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From bcffb80bba2a6f9ce9eddad61b99a3e59a58f8a0 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 1/5] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829e..7bfec4e11f7aab 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a416df2e97c439..5c70588bd28b84 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e647ac267ab395..eeadc47e99069c 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10354,6 +10354,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10388,15 +10407,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !I

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-03 Thread Krystian Stasiowski via cfe-commits


@@ -275,6 +275,13 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl 
*Function,
  TemplateArgs->asArray(),
  /*Final=*/false);
 
+if (RelativeToPrimary &&
+(Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitSpecialization ||

sdkrystian wrote:

gcc does not support class scope explicit specializations.

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-03 Thread Qizhi Hu via cfe-commits


@@ -275,6 +275,13 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl 
*Function,
  TemplateArgs->asArray(),
  /*Final=*/false);
 
+if (RelativeToPrimary &&
+(Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitSpecialization ||

jcsxky wrote:

@sdkrystian but gcc fails on the testcase you provided.

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-02 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

Added tests + diagnostics for ambiguous member specializations

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-02 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From 0e779c3386c345fb68f4273f08748f5a344682e0 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 1/4] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829e..7bfec4e11f7aab 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 04cd9e78739d20..6f7aec0b319e3b 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 989f3995ca5991..93fe7a57af738a 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10346,6 +10346,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10380,15 +10399,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !I

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-02 Thread Vlad Serebrennikov via cfe-commits


@@ -9739,6 +9739,9 @@ class Sema final : public SemaBase {
  const PartialDiagnostic &CandidateDiag,
  bool Complain = true, QualType TargetType = QualType());
 
+  FunctionDecl *getMoreConstrainedFunction(FunctionDecl *FD1,

Endilll wrote:

You put this declaration into `SemaTemplateDeclaration` section of `Sema.h`, 
but the function is implemented in `SemaTemplate.cpp`. They should be in sync.

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-02 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From 0e779c3386c345fb68f4273f08748f5a344682e0 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 1/3] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829e..7bfec4e11f7aab 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 04cd9e78739d20..6f7aec0b319e3b 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 989f3995ca5991..93fe7a57af738a 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10346,6 +10346,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10380,15 +10399,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !I

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-02 Thread Krystian Stasiowski via cfe-commits


@@ -275,6 +275,13 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl 
*Function,
  TemplateArgs->asArray(),
  /*Final=*/false);
 
+if (RelativeToPrimary &&
+(Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitSpecialization ||

sdkrystian wrote:

@jcsxky https://godbolt.org/z/7rTxcG7EE


https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-02 Thread Qizhi Hu via cfe-commits


@@ -275,6 +275,13 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl 
*Function,
  TemplateArgs->asArray(),
  /*Final=*/false);
 
+if (RelativeToPrimary &&
+(Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitSpecialization ||

jcsxky wrote:

This testcase runs OK before 
[be79079](https://github.com/llvm/llvm-project/pull/88963/commits/be79079507ffbd9b29683498f405dc2c32dd8ba7)
 applied and it may not be related to the condition 
`Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization`.

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-02 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian edited 
https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-02 Thread Krystian Stasiowski via cfe-commits


@@ -275,6 +275,13 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl 
*Function,
  TemplateArgs->asArray(),
  /*Final=*/false);
 
+if (RelativeToPrimary &&
+(Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitSpecialization ||

sdkrystian wrote:

@jcsxky There already is a test case which will fail without the condition in 
this PR:
```cpp
template
concept C = sizeof(T) <= sizeof(long);

template
struct A {
  template
  void f(U) requires C;
};

template<>
template
void A::f(U) requires C;
```

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-05-02 Thread Qizhi Hu via cfe-commits


@@ -275,6 +275,13 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl 
*Function,
  TemplateArgs->asArray(),
  /*Final=*/false);
 
+if (RelativeToPrimary &&
+(Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitSpecialization ||

jcsxky wrote:

Is this condition `Function->getTemplateSpecializationKind() == 
TSK_ExplicitSpecialization` necessary? I removed it and all testcases passed. 
Could you please add a testcase to cover it which would fail without this 
condition?

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-04-30 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/88963

>From 77de225477afd3689b8bf64107e8f3a4eeab85ac Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH 1/2] [Clang][Sema] Improve support for explicit
 specializations of constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829e..7bfec4e11f7aab 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 04cd9e78739d20..6f7aec0b319e3b 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
   return true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 7f18631c6096d1..49f878f683103b 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10349,6 +10349,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
   return false;
 }
 
+static bool IsMoreConstrainedFunction(Sema &S, FunctionDecl *FD1,
+  FunctionDecl *FD2) {
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+FD1 = MF;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+FD2 = MF;
+  llvm::SmallVector AC1, AC2;
+  FD1->getAssociatedConstraints(AC1);
+  FD2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (S.IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+return false;
+  if (S.IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+return false;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+return false;
+  return AtLeastAsConstrained1;
+}
+
 /// Perform semantic analysis for the given non-template member
 /// specialization.
 ///
@@ -10383,15 +10402,26 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, 
LookupResult &Previous) {
 QualType Adjusted = Function->getType();
 if (!hasExplicitCallingConv(Adjusted))
   Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+if (!Context.hasSameType(Adjusted, Method->getType()))
+  continue;
+if (Method->getTrailingRequiresClause()) {
+  ConstraintSatisfaction Satisfaction;
+  if (CheckFunctionConstraints(Method, Satisfaction,
+   /*UsageLoc=*/Member->getLocation(),
+   /*ForOverloadResolution=*/true) ||
+  !Satisfaction.IsSatisfied)
+continue;
+  if (Instantiation &&
+  !I

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-04-16 Thread Erich Keane via cfe-commits

https://github.com/erichkeane commented:

Approach/fix looks fine, other than release notes + tests, LGTM.

https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-04-16 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian edited 
https://github.com/llvm/llvm-project/pull/88963
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)

2024-04-16 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Krystian Stasiowski (sdkrystian)


Changes

Consider the following snippet from the discussion of 
[CWG2847](https://cplusplus.github.io/CWG/issues/2847.html) on the [core 
reflector](https://lists.isocpp.org/core/2024/04/15720.php) ([godbolt 
link](https://godbolt.org/z/dvvef9xzM)):
```cpp
template
concept C = sizeof(T) <= sizeof(long);

template
struct A 
{
template
void f(U) requires C; // #1, declares a function template 

void g() requires C; // #2, declares a function

template<>
void f(char);  // #3, an explicit specialization of a function 
template that declares a function
};

template<>
template
void A::f(U) requires C; // #4, an explicit 
specialization of a function template that declares a function template

template<>
template<>
void A::f(int); // #5, an explicit specialization of a 
function template that declares a function

template<>
void A::g(); // #6, an explicit specialization of a 
function that declares a function
```

A number of problems exist:
- Clang rejects `#4` because the trailing _requires-clause_ has `U` 
substituted with the wrong template parameter depth when 
`Sema::AreConstraintExpressionsEqual` is called to determine whether it matches 
the trailing _requires-clause_ of the implicitly instantiated function template.
- Clang rejects `#5` because the function template specialization 
instantiated from `A::f` has a trailing _requires-clause_, but 
`#5` does not (nor can it have one as it isn't a templated function).
- Clang rejects `#6` for the same reasons it rejects `#5`.

This patch resolves these issues by making the following changes:
- To fix `#4`, `Sema::AreConstraintExpressionsEqual` is passed 
`FunctionTemplateDecl`s when comparing the trailing _requires-clauses_ of 
`#4` and the function template instantiated from `#1`.
- To fix `#5` and `#6`, the trailing _requires-clauses_ are not 
compared for explicit specializations that declare functions.

In addition to these changes, `CheckMemberSpecialization` now considers 
constraint satisfaction/constraint partial ordering when determining which 
member function is specialized by an explicit specialization of a member 
function for an implicit instantiation of a class template.

---
Full diff: https://github.com/llvm/llvm-project/pull/88963.diff


5 Files Affected:

- (modified) clang/lib/Sema/SemaConcept.cpp (+1-1) 
- (modified) clang/lib/Sema/SemaOverload.cpp (+8-3) 
- (modified) clang/lib/Sema/SemaTemplate.cpp (+37-7) 
- (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+4) 
- (added) clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp (+74) 


``diff
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829e..7bfec4e11f7aab 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 227ef564ba3e08..594cfc58d2226a 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (OldRC != nullptr))
   return true;
-
-if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, 
NewRC))
+if (NewRC &&
+!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC

[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)


https://github.com/sdkrystian created 
https://github.com/llvm/llvm-project/pull/88963

Consider the following snippet from the discussion of 
[CWG2847](https://cplusplus.github.io/CWG/issues/2847.html) on the [core 
reflector](https://lists.isocpp.org/core/2024/04/15720.php) ([godbolt 
link](https://godbolt.org/z/dvvef9xzM)):
```cpp
template
concept C = sizeof(T) <= sizeof(long);

template
struct A 
{
template
void f(U) requires C; // #1, declares a function template 

void g() requires C; // #2, declares a function

template<>
void f(char);  // #3, an explicit specialization of a function template 
that declares a function
};

template<>
template
void A::f(U) requires C; // #4, an explicit specialization of a 
function template that declares a function template

template<>
template<>
void A::f(int); // #5, an explicit specialization of a function template 
that declares a function

template<>
void A::g(); // #6, an explicit specialization of a function that 
declares a function
```

A number of problems exist:
- Clang rejects `#4` because the trailing _requires-clause_ has `U` substituted 
with the wrong template parameter depth when 
`Sema::AreConstraintExpressionsEqual` is called to determine whether it matches 
the trailing _requires-clause_ of the implicitly instantiated function template.
- Clang rejects `#5` because the function template specialization instantiated 
from `A::f` has a trailing _requires-clause_, but `#5` does not (nor can 
it have one as it isn't a templated function).
- Clang rejects `#6` for the same reasons it rejects `#5`.

This patch resolves these issues by making the following changes:
- To fix `#4`, `Sema::AreConstraintExpressionsEqual` is passed 
`FunctionTemplateDecl`s when comparing the trailing _requires-clauses_ of `#4` 
and the function template instantiated from `#1`.
- To fix `#5` and `#6`, the trailing _requires-clauses_ are not compared for 
explicit specializations that declare functions.

In addition to these changes, `CheckMemberSpecialization` now considers 
constraint satisfaction/constraint partial ordering when determining which 
member function is specialized by an explicit specialization of a member 
function for an implicit instantiation of a class template.

>From ede52d5020c12b1a3010c6637bb2fad0157da79e Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 16 Apr 2024 13:36:11 -0400
Subject: [PATCH] [Clang][Sema] Improve support for explicit specializations of
 constrained member functions & member function templates

---
 clang/lib/Sema/SemaConcept.cpp|  2 +-
 clang/lib/Sema/SemaOverload.cpp   | 11 ++-
 clang/lib/Sema/SemaTemplate.cpp   | 44 +--
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  4 +
 .../CXX/temp/temp.spec/temp.expl.spec/p8.cpp  | 74 +++
 5 files changed, 124 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p8.cpp

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e00c972602829e..7bfec4e11f7aab 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -811,7 +811,7 @@ static const Expr 
*SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl()))
+  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
 for (auto *PVD : FD->parameters())
   ScopeForParameters.InstantiatedLocal(PVD, PVD);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 227ef564ba3e08..594cfc58d2226a 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1303,6 +1303,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   if (New->isMSVCRTEntryPoint())
 return false;
 
+  NamedDecl *OldDecl = Old;
+  NamedDecl *NewDecl = New;
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -1347,6 +1349,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
   // references to non-instantiated entities during constraint substitution.
   // GH78101.
   if (NewTemplate) {
+OldDecl = OldTemplate;
+NewDecl = NewTemplate;
 // C++ [temp.over.link]p4:
 //   The signature of a function template consists of its function
 //   signature, its return type and its template parameter list. The names
@@ -1506,13 +1510,14 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, 
FunctionDecl *New,
 }
   }
 
-  if (!UseOverrideRules) {
+  if (!UseOverrideRules &&
+  New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
 Expr *NewRC = New->getTrailingRequiresClause(),
  *OldRC = Old->getTrailingRequiresClause();
 if ((NewRC != nullptr) != (O