[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