[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)
@@ -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)
@@ -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)
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)
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)
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)
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)
@@ -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)
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)
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)
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)
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)
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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
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)
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)
@@ -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)
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)
@@ -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)
@@ -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)
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)
@@ -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)
@@ -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)
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)
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)
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)
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 templateconcept 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