ychen updated this revision to Diff 470546.
ychen added a comment.
- rebase
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D136545/new/
https://reviews.llvm.org/D136545
Files:
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaConcept.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaOverload.cpp
clang/test/CXX/over/over.match/over.match.best/p2.cpp
clang/test/CXX/temp/temp.constr/temp.constr.order/non-template-functions.cpp
Index: clang/test/CXX/temp/temp.constr/temp.constr.order/non-template-functions.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/temp/temp.constr/temp.constr.order/non-template-functions.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -std=c++2a -x c++ -verify %s
+// expected-no-diagnostics
+
+template<typename T, typename U>
+constexpr static bool is_same_v = false;
+
+template<typename T>
+constexpr static bool is_same_v<T, T> = true;
+
+namespace PR56154 {
+ template <int N> concept C0 = (N == 0);
+ template <int N, int N2> concept C0x = C0<N>;
+ template <int N1, int N2> concept C00 = C0x<N1, N2> && C0<N2>;
+
+ template<int N1, int N2>
+ struct A {
+ void f() requires C00<N1, N2>;
+ void f() requires C0x<N1, N2> = delete;
+
+ static short g() requires C00<N1, N2>;
+ static int g() requires C0x<N1, N2>;
+ };
+ void h(A<0, 0> a) {
+ a.f();
+ static_assert(is_same_v<decltype(&A<0, 0>::g), short(*)()>);
+ }
+}
Index: clang/test/CXX/over/over.match/over.match.best/p2.cpp
===================================================================
--- clang/test/CXX/over/over.match/over.match.best/p2.cpp
+++ clang/test/CXX/over/over.match/over.match.best/p2.cpp
@@ -7,7 +7,11 @@
bool operator<(const A&) const & requires X<T>; // #1
int operator<=>(const A&) const & requires X<T> && X<int> = delete; // #2
};
- bool k1 = A<int>() < A<int>(); // not ordered by constraints: prefer non-rewritten form
+ bool k1 = A<int>() < A<int>(); // prefer more-constrained 'operator<=>'
+ // expected-error@-1 {{deleted}}
+ // expected-note@#1 {{candidate}}
+ // expected-note@#2 {{candidate function has been explicitly deleted}}
+ // expected-note@#2 {{candidate function (with reversed parameter order) has been explicitly deleted}}
bool k2 = A<float>() < A<float>(); // prefer more-constrained 'operator<=>'
// expected-error@-1 {{deleted}}
// expected-note@#1 {{candidate}}
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -10033,13 +10033,20 @@
// parameter-type-lists, and F1 is more constrained than F2 [...],
if (!Cand1IsSpecialization && !Cand2IsSpecialization &&
sameFunctionParameterTypeLists(S, Cand1, Cand2)) {
- Expr *RC1 = Cand1.Function->getTrailingRequiresClause();
- Expr *RC2 = Cand2.Function->getTrailingRequiresClause();
+ FunctionDecl *Function1 = Cand1.Function;
+ FunctionDecl *Function2 = Cand2.Function;
+ if (FunctionDecl *MF = Function1->getInstantiatedFromMemberFunction())
+ Function1 = MF;
+ if (FunctionDecl *MF = Function2->getInstantiatedFromMemberFunction())
+ Function2 = MF;
+
+ Expr *RC1 = Function1->getTrailingRequiresClause();
+ Expr *RC2 = Function2->getTrailingRequiresClause();
if (RC1 && RC2) {
bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (S.IsAtLeastAsConstrained(Cand1.Function, {RC1}, Cand2.Function, {RC2},
+ if (S.IsAtLeastAsConstrained(Function1, {RC1}, Function2, {RC2},
AtLeastAsConstrained1) ||
- S.IsAtLeastAsConstrained(Cand2.Function, {RC2}, Cand1.Function, {RC1},
+ S.IsAtLeastAsConstrained(Function2, {RC2}, Function1, {RC1},
AtLeastAsConstrained2))
return false;
if (AtLeastAsConstrained1 != AtLeastAsConstrained2)
@@ -12624,20 +12631,24 @@
DeclAccessPair DAP;
SmallVector<FunctionDecl *, 2> AmbiguousDecls;
- auto CheckMoreConstrained =
- [&] (FunctionDecl *FD1, FunctionDecl *FD2) -> Optional<bool> {
- SmallVector<const Expr *, 1> AC1, AC2;
- FD1->getAssociatedConstraints(AC1);
- FD2->getAssociatedConstraints(AC2);
- bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
- return None;
- if (IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
- return None;
- if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
- return None;
- return AtLeastAsConstrained1;
- };
+ auto CheckMoreConstrained = [&](FunctionDecl *FD1,
+ FunctionDecl *FD2) -> Optional<bool> {
+ if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+ FD1 = MF;
+ if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+ FD2 = MF;
+ SmallVector<const Expr *, 1> AC1, AC2;
+ FD1->getAssociatedConstraints(AC1);
+ FD2->getAssociatedConstraints(AC2);
+ bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+ if (IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+ return None;
+ if (IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+ return None;
+ if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+ return None;
+ return AtLeastAsConstrained1;
+ };
// Don't use the AddressOfResolver because we're specifically looking for
// cases where we have one overload candidate that lacks
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -18211,13 +18211,20 @@
if (!SatisfactionStatus[i])
continue;
CXXMethodDecl *Method = Methods[i];
- const Expr *Constraints = Method->getTrailingRequiresClause();
+ CXXMethodDecl *OrigMethod = Method;
+ if (FunctionDecl *MF = OrigMethod->getInstantiatedFromMemberFunction())
+ OrigMethod = cast<CXXMethodDecl>(MF);
+
+ const Expr *Constraints = OrigMethod->getTrailingRequiresClause();
bool AnotherMethodIsMoreConstrained = false;
for (size_t j = 0; j < Methods.size(); j++) {
if (i == j || !SatisfactionStatus[j])
continue;
CXXMethodDecl *OtherMethod = Methods[j];
- if (!AreSpecialMemberFunctionsSameKind(S.Context, Method, OtherMethod,
+ if (FunctionDecl *MF = OtherMethod->getInstantiatedFromMemberFunction())
+ OtherMethod = cast<CXXMethodDecl>(MF);
+
+ if (!AreSpecialMemberFunctionsSameKind(S.Context, OrigMethod, OtherMethod,
CSM))
continue;
@@ -18228,7 +18235,7 @@
AnotherMethodIsMoreConstrained = true;
break;
}
- if (S.IsAtLeastAsConstrained(OtherMethod, {OtherConstraints}, Method,
+ if (S.IsAtLeastAsConstrained(OtherMethod, {OtherConstraints}, OrigMethod,
{Constraints},
AnotherMethodIsMoreConstrained)) {
// There was an error with the constraints comparison. Exit the loop
Index: clang/lib/Sema/SemaConcept.cpp
===================================================================
--- clang/lib/Sema/SemaConcept.cpp
+++ clang/lib/Sema/SemaConcept.cpp
@@ -1276,6 +1276,18 @@
bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef<const Expr *> AC1,
NamedDecl *D2, ArrayRef<const Expr *> AC2,
bool &Result) {
+ if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
+ auto IsExpectedEntity = [](const FunctionDecl *FD) {
+ FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
+ return Kind == FunctionDecl::TK_NonTemplate ||
+ Kind == FunctionDecl::TK_FunctionTemplate;
+ };
+ const auto *FD2 = dyn_cast<FunctionDecl>(D2);
+ assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
+ "use non-instantiated function declaration for constraints partial "
+ "ordering");
+ }
+
if (AC1.empty()) {
Result = AC2.empty();
return false;
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -255,6 +255,8 @@
- Reject non-type template arguments formed by casting a non-zero integer
to a pointer in pre-C++17 modes, instead of treating them as null
pointers.
+- Fix an issue when performing constraints partial ordering on non-template
+ functions. `Issue 56154 <https://github.com/llvm/llvm-project/issues/56154>`_
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits