[clang] Fix assertion failure during conversion function overload resolution. (PR #98671)
Daniel M. Katz via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 25 09:09:35 PDT 2024
https://github.com/katzdm updated https://github.com/llvm/llvm-project/pull/98671
>From 47db72077258ebe086059f116bbf7fb32c184c8d Mon Sep 17 00:00:00 2001
From: Dan Katz <katzdm at gmail.com>
Date: Fri, 12 Jul 2024 13:57:33 -0400
Subject: [PATCH 1/4] Fix assertion failure during operator overload
resolution.
---
clang/lib/Sema/SemaConcept.cpp | 3 ++-
clang/test/SemaCXX/PR98671.cpp | 14 ++++++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
create mode 100644 clang/test/SemaCXX/PR98671.cpp
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 202dd86c67f62..f94fb8be20e07 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -1519,7 +1519,8 @@ bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
auto IsExpectedEntity = [](const FunctionDecl *FD) {
FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
return Kind == FunctionDecl::TK_NonTemplate ||
- Kind == FunctionDecl::TK_FunctionTemplate;
+ Kind == FunctionDecl::TK_FunctionTemplate ||
+ Kind == FunctionDecl::TK_FunctionTemplateSpecialization;
};
const auto *FD2 = dyn_cast<FunctionDecl>(D2);
(void)IsExpectedEntity;
diff --git a/clang/test/SemaCXX/PR98671.cpp b/clang/test/SemaCXX/PR98671.cpp
new file mode 100644
index 0000000000000..696b750759854
--- /dev/null
+++ b/clang/test/SemaCXX/PR98671.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only %s -verify
+
+struct S {
+ operator int();
+
+ template <typename T>
+ operator T();
+};
+
+
+// Ensure that no assertion is raised when overload resolution fails while
+// choosing between an operator function template and an operator function.
+constexpr auto r = &S::operator int;
+// expected-error at -1 {{initializer of type '<overloaded function type>'}}
>From aa4d40bca37edd0c4facff609b483a6c9994d0c2 Mon Sep 17 00:00:00 2001
From: Dan Katz <katzdm at gmail.com>
Date: Tue, 16 Jul 2024 11:15:27 -0400
Subject: [PATCH 2/4] Address feedback.
---
clang/lib/Sema/SemaConcept.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index f94fb8be20e07..d55a053babaf9 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -1519,7 +1519,7 @@ bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
auto IsExpectedEntity = [](const FunctionDecl *FD) {
FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
return Kind == FunctionDecl::TK_NonTemplate ||
- Kind == FunctionDecl::TK_FunctionTemplate ||
+ Kind == FunctionDecl::TK_MemberSpecialization ||
Kind == FunctionDecl::TK_FunctionTemplateSpecialization;
};
const auto *FD2 = dyn_cast<FunctionDecl>(D2);
>From adf2226bb95bd71c7d8632b7fe89de8dab57e784 Mon Sep 17 00:00:00 2001
From: Dan Katz <katzdm at gmail.com>
Date: Mon, 22 Jul 2024 06:56:53 -0400
Subject: [PATCH 3/4] Change approach to fixing this.
---
clang/lib/Sema/SemaConcept.cpp | 3 +--
clang/lib/Sema/SemaTemplateDeduction.cpp | 23 +++++++++++++++++------
clang/test/SemaCXX/PR98671.cpp | 18 ++++++++++++++++--
3 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index d55a053babaf9..202dd86c67f62 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -1519,8 +1519,7 @@ bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
auto IsExpectedEntity = [](const FunctionDecl *FD) {
FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
return Kind == FunctionDecl::TK_NonTemplate ||
- Kind == FunctionDecl::TK_MemberSpecialization ||
- Kind == FunctionDecl::TK_FunctionTemplateSpecialization;
+ Kind == FunctionDecl::TK_FunctionTemplate;
};
const auto *FD2 = dyn_cast<FunctionDecl>(D2);
(void)IsExpectedEntity;
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index b7b857ebf804b..c05909dd09ab8 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5824,12 +5824,23 @@ FunctionDecl *Sema::getMoreConstrainedFunction(FunctionDecl *FD1,
FunctionDecl *FD2) {
assert(!FD1->getDescribedTemplate() && !FD2->getDescribedTemplate() &&
"not for function templates");
- FunctionDecl *F1 = FD1;
- if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
- F1 = MF;
- FunctionDecl *F2 = FD2;
- if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
- F2 = MF;
+
+ auto getTemplatePattern = [](FunctionDecl *FD) {
+ // Specializations of conversion function templates are believed to be the
+ // only case where a function template specialization reaches here.
+ assert(!FD->isFunctionTemplateSpecialization() ||
+ isa<CXXConversionDecl>(FD));
+
+ if (FunctionDecl *MF = FD->getInstantiatedFromMemberFunction())
+ return MF;
+ else if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate())
+ return FTD->getTemplatedDecl();
+
+ return FD;
+ };
+ FunctionDecl *F1 = getTemplatePattern(FD1);
+ FunctionDecl *F2 = getTemplatePattern(FD2);
+
llvm::SmallVector<const Expr *, 1> AC1, AC2;
F1->getAssociatedConstraints(AC1);
F2->getAssociatedConstraints(AC2);
diff --git a/clang/test/SemaCXX/PR98671.cpp b/clang/test/SemaCXX/PR98671.cpp
index 696b750759854..f505186735885 100644
--- a/clang/test/SemaCXX/PR98671.cpp
+++ b/clang/test/SemaCXX/PR98671.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -std=c++20 -fsyntax-only %s -verify
-struct S {
+struct S1 {
operator int();
template <typename T>
@@ -10,5 +10,19 @@ struct S {
// Ensure that no assertion is raised when overload resolution fails while
// choosing between an operator function template and an operator function.
-constexpr auto r = &S::operator int;
+constexpr auto r = &S1::operator int;
// expected-error at -1 {{initializer of type '<overloaded function type>'}}
+
+
+template <typename T>
+struct S2 {
+ template <typename U=T>
+ S2(U={}) requires (sizeof(T) > 0) {}
+ // expected-note at -1 {{candidate constructor}}
+
+ template <typename U=T>
+ S2(U={}) requires (true) {}
+ // expected-note at -1 {{candidate constructor}}
+};
+
+S2<int> s; // expected-error {{call to constructor of 'S2<int>' is ambiguous}}
>From ba21c6820975f1cf6406498b7bf151c9a114dd42 Mon Sep 17 00:00:00 2001
From: Dan Katz <katzdm at gmail.com>
Date: Thu, 25 Jul 2024 12:09:19 -0400
Subject: [PATCH 4/4] Addressing feedback.
---
clang/lib/Sema/SemaTemplateDeduction.cpp | 28 ++++++++++--------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index c05909dd09ab8..915291be6841e 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5824,22 +5824,18 @@ FunctionDecl *Sema::getMoreConstrainedFunction(FunctionDecl *FD1,
FunctionDecl *FD2) {
assert(!FD1->getDescribedTemplate() && !FD2->getDescribedTemplate() &&
"not for function templates");
-
- auto getTemplatePattern = [](FunctionDecl *FD) {
- // Specializations of conversion function templates are believed to be the
- // only case where a function template specialization reaches here.
- assert(!FD->isFunctionTemplateSpecialization() ||
- isa<CXXConversionDecl>(FD));
-
- if (FunctionDecl *MF = FD->getInstantiatedFromMemberFunction())
- return MF;
- else if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate())
- return FTD->getTemplatedDecl();
-
- return FD;
- };
- FunctionDecl *F1 = getTemplatePattern(FD1);
- FunctionDecl *F2 = getTemplatePattern(FD2);
+ assert(!FD1->isFunctionTemplateSpecialization() ||
+ isa<CXXConversionDecl>(FD1));
+ assert(!FD2->isFunctionTemplateSpecialization() ||
+ isa<CXXConversionDecl>(FD2));
+
+ FunctionDecl *F1 = FD1;
+ if (FunctionDecl *P = FD1->getTemplateInstantiationPattern(false))
+ F1 = P;
+
+ FunctionDecl *F2 = FD2;
+ if (FunctionDecl *P = FD2->getTemplateInstantiationPattern(false))
+ F2 = P;
llvm::SmallVector<const Expr *, 1> AC1, AC2;
F1->getAssociatedConstraints(AC1);
More information about the cfe-commits
mailing list