[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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

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


[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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

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

>From 34af5511804b8c0fd8b0d742653f6017dd8e9e87 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Wed, 8 May 2024 08:43:23 -0400
Subject: [PATCH 1/2] [Clang][Sema] Do not mark template parameters in the
 exception specification as used during partial ordering

---
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 36 +++---
 .../temp.deduct/temp.deduct.partial/p3.cpp| 72 +++
 2 files changed, 100 insertions(+), 8 deletions(-)
 create mode 100644 
clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 853c0e1b50619..b5d405111fe4c 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5453,7 +5453,7 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
 // is used.
 if (DeduceTemplateArgumentsByTypeMatch(
 S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced,
-TDF_None,
+TDF_AllowCompatibleFunctionType,
 /*PartialOrdering=*/true) != TemplateDeductionResult::Success)
   return false;
 break;
@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
   switch (TPOC) {
   case TPOC_Call:
 for (unsigned I = 0, N = Args2.size(); I != N; ++I)
-  ::MarkUsedTemplateParameters(S.Context, Args2[I], false,
-   TemplateParams->getDepth(),
-   UsedParameters);
+  ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false,
+   TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Conversion:
-::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
+::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(),
+ /*OnlyDeduced=*/false,
  TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Other:
-::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
- TemplateParams->getDepth(),
- UsedParameters);
+// We do not deduce template arguments from the exception specification
+// when determining the primary template of a function template
+// specialization or when taking the address of a function template.
+// Therefore, we do not mark template parameters in the exception
+// specification as used during partial ordering to prevent the following
+// from being ambiguous:
+//
+//   template
+//   void f(U) noexcept(noexcept(T())); // #1
+//
+//   template
+//   void f(T*) noexcept; // #2
+//
+//   template<>
+//   void f(int*) noexcept; // explicit specialization of #2
+//
+// Although there is no corresponding wording in the standard, this seems
+// to be the intended behavior given the definition of
+// 'deduction substitution loci' in [temp.deduct].
+::MarkUsedTemplateParameters(
+S.Context,
+S.Context.getFunctionTypeWithExceptionSpec(FD2->getType(), EST_None),
+/*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters);
 break;
   }
 
diff --git 
a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp 
b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp
new file mode 100644
index 0..cc1d4ecda2ecc
--- /dev/null
+++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+template
+struct A { };
+
+constexpr A a;
+constexpr A b;
+
+constexpr int* x = nullptr;
+constexpr short* y = nullptr;
+
+namespace ExplicitArgs {
+  template
+  constexpr int f(U) noexcept(noexcept(T())) {
+return 0;
+  }
+
+  template
+  constexpr int f(T*) noexcept {
+return 1;
+  }
+
+  template<>
+  constexpr int f(int*) noexcept {
+return 2;
+  }
+
+  static_assert(f(1) == 0);
+  static_assert(f(y) == 1);
+  static_assert(f(x) == 2);
+
+  template
+  constexpr int g(U*) noexcept(noexcept(T())) {
+return 3;
+  }
+
+  template
+  constexpr int g(T) noexcept {
+return 4;
+  }
+
+  template<>
+  constexpr int g(int*) noexcept {
+return 5;
+  }
+
+  static_assert(g(y) == 3);
+  static_assert(g(1) == 4);
+  static_assert(g(x) == 5);
+} // namespace ExplicitArgs
+
+namespace DeducedArgs {
+  template
+  constexpr int f(T, A) noexcept(B) {
+return 0;
+  }
+
+  template
+  constexpr int f(T*, A) noexcept(B && B) {
+return 1;
+  }
+
+  template<>
+  constexpr int f(int*, A) {
+return 2;
+  }
+
+  static_assert(f(x, a) == 0);
+  static_assert(f(y, a) == 1);
+  static_assert(f(x, a) == 2);
+} // namespace DeducedArgs

>From 

[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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


@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
   switch (TPOC) {
   case TPOC_Call:
 for (unsigned I = 0, N = Args2.size(); I != N; ++I)
-  ::MarkUsedTemplateParameters(S.Context, Args2[I], false,
-   TemplateParams->getDepth(),
-   UsedParameters);
+  ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false,
+   TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Conversion:
-::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
+::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(),
+ /*OnlyDeduced=*/false,
  TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Other:
-::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
- TemplateParams->getDepth(),
- UsedParameters);
+// We do not deduce template arguments from the exception specification
+// when determining the primary template of a function template
+// specialization or when taking the address of a function template.
+// Therefore, we do not mark template parameters in the exception
+// specification as used during partial ordering to prevent the following
+// from being ambiguous:
+//
+//   template
+//   void f(U) noexcept(noexcept(T())); // #1
+//
+//   template
+//   void f(T*) noexcept; // #2
+//
+//   template<>
+//   void f(int*) noexcept; // explicit specialization of #2
+//
+// Although there is no corresponding wording in the standard, this seems

sdkrystian wrote:

I've seen it take anywhere from a day to a month. I'll be sure to update this 
once the issue is opened!

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


[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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


@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
   switch (TPOC) {
   case TPOC_Call:
 for (unsigned I = 0, N = Args2.size(); I != N; ++I)
-  ::MarkUsedTemplateParameters(S.Context, Args2[I], false,
-   TemplateParams->getDepth(),
-   UsedParameters);
+  ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false,
+   TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Conversion:
-::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
+::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(),
+ /*OnlyDeduced=*/false,
  TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Other:
-::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
- TemplateParams->getDepth(),
- UsedParameters);
+// We do not deduce template arguments from the exception specification
+// when determining the primary template of a function template
+// specialization or when taking the address of a function template.
+// Therefore, we do not mark template parameters in the exception
+// specification as used during partial ordering to prevent the following
+// from being ambiguous:
+//
+//   template
+//   void f(U) noexcept(noexcept(T())); // #1
+//
+//   template
+//   void f(T*) noexcept; // #2
+//
+//   template<>
+//   void f(int*) noexcept; // explicit specialization of #2
+//
+// Although there is no corresponding wording in the standard, this seems

erichkeane wrote:

Jens is usually really quick at assigning a core issue, right?  That said, you 
can merge this before getting one as long as you come back afterwards and fill 
it in.

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


[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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


@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
   switch (TPOC) {
   case TPOC_Call:
 for (unsigned I = 0, N = Args2.size(); I != N; ++I)
-  ::MarkUsedTemplateParameters(S.Context, Args2[I], false,
-   TemplateParams->getDepth(),
-   UsedParameters);
+  ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false,
+   TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Conversion:
-::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
+::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(),
+ /*OnlyDeduced=*/false,
  TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Other:
-::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
- TemplateParams->getDepth(),
- UsedParameters);
+// We do not deduce template arguments from the exception specification
+// when determining the primary template of a function template
+// specialization or when taking the address of a function template.
+// Therefore, we do not mark template parameters in the exception
+// specification as used during partial ordering to prevent the following
+// from being ambiguous:
+//
+//   template
+//   void f(U) noexcept(noexcept(T())); // #1
+//
+//   template
+//   void f(T*) noexcept; // #2
+//
+//   template<>
+//   void f(int*) noexcept; // explicit specialization of #2
+//
+// Although there is no corresponding wording in the standard, this seems

sdkrystian wrote:

@erichkeane Filed an issue [here](https://github.com/cplusplus/CWG/issues/537). 
It might be a little while before an actual core issue is opened, so would it 
be alright to merge this before that happens?

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


[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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

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

LGTM other than including the CWG issue to the comment.  Feel free to merge 
once that is in place.

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


[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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

sdkrystian wrote:

@erichkeane Release note added

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


[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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

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

>From eea39228271166b4d8f39b32d7866cb33dffdd0b Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Wed, 8 May 2024 08:43:23 -0400
Subject: [PATCH 1/2] [Clang][Sema] Do not mark template parameters in the
 exception specification as used during partial ordering

---
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 36 +++---
 .../temp.deduct/temp.deduct.partial/p3.cpp| 72 +++
 2 files changed, 100 insertions(+), 8 deletions(-)
 create mode 100644 
clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index fe7e35d841510..c17c5838803a8 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5453,7 +5453,7 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
 // is used.
 if (DeduceTemplateArgumentsByTypeMatch(
 S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced,
-TDF_None,
+TDF_AllowCompatibleFunctionType,
 /*PartialOrdering=*/true) != TemplateDeductionResult::Success)
   return false;
 break;
@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
   switch (TPOC) {
   case TPOC_Call:
 for (unsigned I = 0, N = Args2.size(); I != N; ++I)
-  ::MarkUsedTemplateParameters(S.Context, Args2[I], false,
-   TemplateParams->getDepth(),
-   UsedParameters);
+  ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false,
+   TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Conversion:
-::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
+::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(),
+ /*OnlyDeduced=*/false,
  TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Other:
-::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
- TemplateParams->getDepth(),
- UsedParameters);
+// We do not deduce template arguments from the exception specification
+// when determining the primary template of a function template
+// specialization or when taking the address of a function template.
+// Therefore, we do not mark template parameters in the exception
+// specification as used during partial ordering to prevent the following
+// from being ambiguous:
+//
+//   template
+//   void f(U) noexcept(noexcept(T())); // #1
+//
+//   template
+//   void f(T*) noexcept; // #2
+//
+//   template<>
+//   void f(int*) noexcept; // explicit specialization of #2
+//
+// Although there is no corresponding wording in the standard, this seems
+// to be the intended behavior given the definition of
+// 'deduction substitution loci' in [temp.deduct].
+::MarkUsedTemplateParameters(
+S.Context,
+S.Context.getFunctionTypeWithExceptionSpec(FD2->getType(), EST_None),
+/*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters);
 break;
   }
 
diff --git 
a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp 
b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp
new file mode 100644
index 0..cc1d4ecda2ecc
--- /dev/null
+++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+template
+struct A { };
+
+constexpr A a;
+constexpr A b;
+
+constexpr int* x = nullptr;
+constexpr short* y = nullptr;
+
+namespace ExplicitArgs {
+  template
+  constexpr int f(U) noexcept(noexcept(T())) {
+return 0;
+  }
+
+  template
+  constexpr int f(T*) noexcept {
+return 1;
+  }
+
+  template<>
+  constexpr int f(int*) noexcept {
+return 2;
+  }
+
+  static_assert(f(1) == 0);
+  static_assert(f(y) == 1);
+  static_assert(f(x) == 2);
+
+  template
+  constexpr int g(U*) noexcept(noexcept(T())) {
+return 3;
+  }
+
+  template
+  constexpr int g(T) noexcept {
+return 4;
+  }
+
+  template<>
+  constexpr int g(int*) noexcept {
+return 5;
+  }
+
+  static_assert(g(y) == 3);
+  static_assert(g(1) == 4);
+  static_assert(g(x) == 5);
+} // namespace ExplicitArgs
+
+namespace DeducedArgs {
+  template
+  constexpr int f(T, A) noexcept(B) {
+return 0;
+  }
+
+  template
+  constexpr int f(T*, A) noexcept(B && B) {
+return 1;
+  }
+
+  template<>
+  constexpr int f(int*, A) {
+return 2;
+  }
+
+  static_assert(f(x, a) == 0);
+  static_assert(f(y, a) == 1);
+  static_assert(f(x, a) == 2);
+} // namespace DeducedArgs

>From 

[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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


@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
   switch (TPOC) {
   case TPOC_Call:
 for (unsigned I = 0, N = Args2.size(); I != N; ++I)
-  ::MarkUsedTemplateParameters(S.Context, Args2[I], false,
-   TemplateParams->getDepth(),
-   UsedParameters);
+  ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false,
+   TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Conversion:
-::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
+::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(),
+ /*OnlyDeduced=*/false,
  TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Other:
-::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
- TemplateParams->getDepth(),
- UsedParameters);
+// We do not deduce template arguments from the exception specification
+// when determining the primary template of a function template
+// specialization or when taking the address of a function template.
+// Therefore, we do not mark template parameters in the exception
+// specification as used during partial ordering to prevent the following
+// from being ambiguous:
+//
+//   template
+//   void f(U) noexcept(noexcept(T())); // #1
+//
+//   template
+//   void f(T*) noexcept; // #2
+//
+//   template<>
+//   void f(int*) noexcept; // explicit specialization of #2
+//
+// Although there is no corresponding wording in the standard, this seems

sdkrystian wrote:

I'll open it tomorrow 

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


[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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


@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
   switch (TPOC) {
   case TPOC_Call:
 for (unsigned I = 0, N = Args2.size(); I != N; ++I)
-  ::MarkUsedTemplateParameters(S.Context, Args2[I], false,
-   TemplateParams->getDepth(),
-   UsedParameters);
+  ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false,
+   TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Conversion:
-::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
+::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(),
+ /*OnlyDeduced=*/false,
  TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Other:
-::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
- TemplateParams->getDepth(),
- UsedParameters);
+// We do not deduce template arguments from the exception specification
+// when determining the primary template of a function template
+// specialization or when taking the address of a function template.
+// Therefore, we do not mark template parameters in the exception
+// specification as used during partial ordering to prevent the following
+// from being ambiguous:
+//
+//   template
+//   void f(U) noexcept(noexcept(T())); // #1
+//
+//   template
+//   void f(T*) noexcept; // #2
+//
+//   template<>
+//   void f(int*) noexcept; // explicit specialization of #2
+//
+// Although there is no corresponding wording in the standard, this seems

erichkeane wrote:

Please file a core issue here!  It would be great to get this fixed in CWG.  
@Endilll or @shafik  can help with that if you need it.  Also, put the CWG 
issue # in this comment once we have it.

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


[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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

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

This probably also needs a release note.

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


[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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

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


[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

2024-05-08 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Krystian Stasiowski (sdkrystian)


Changes

We do not deduce template arguments from the exception specification when 
determining the primary template of a function template specialization or when 
taking the address of a function template. Therefore, this patch changes 
`isAtLeastAsSpecializedAs` such that we do not mark template parameters in the 
exception specification as 'used' during partial ordering (per 
[[temp.deduct.partial] p12](http://eel.is/c++draft/temp.deduct.partial#12)) to prevent the following from being ambiguous:

```cpp
templatetypename T, typename U
void f(U) noexcept(noexcept(T())); // #1

templatetypename T
void f(T*) noexcept; // #2

template
void fint(int*) noexcept; // currently ambiguous, selects #2 
with this patch applied 
```

Although there is no corresponding wording in the standard, this seems to be 
the intended behavior given the definition of _deduction substitution loci_ in 
[[temp.deduct.general] p7](http://eel.is/c++draft/temp.deduct.general#7) (and EDG does the same thing). 

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


2 Files Affected:

- (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+28-8) 
- (added) 
clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp (+72) 


``diff
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index fe7e35d841510..c17c5838803a8 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5453,7 +5453,7 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
 // is used.
 if (DeduceTemplateArgumentsByTypeMatch(
 S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced,
-TDF_None,
+TDF_AllowCompatibleFunctionType,
 /*PartialOrdering=*/true) != TemplateDeductionResult::Success)
   return false;
 break;
@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
   switch (TPOC) {
   case TPOC_Call:
 for (unsigned I = 0, N = Args2.size(); I != N; ++I)
-  ::MarkUsedTemplateParameters(S.Context, Args2[I], false,
-   TemplateParams->getDepth(),
-   UsedParameters);
+  ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false,
+   TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Conversion:
-::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
+::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(),
+ /*OnlyDeduced=*/false,
  TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Other:
-::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
- TemplateParams->getDepth(),
- UsedParameters);
+// We do not deduce template arguments from the exception specification
+// when determining the primary template of a function template
+// specialization or when taking the address of a function template.
+// Therefore, we do not mark template parameters in the exception
+// specification as used during partial ordering to prevent the following
+// from being ambiguous:
+//
+//   template
+//   void f(U) noexcept(noexcept(T())); // #1
+//
+//   template
+//   void f(T*) noexcept; // #2
+//
+//   template<>
+//   void f(int*) noexcept; // explicit specialization of #2
+//
+// Although there is no corresponding wording in the standard, this seems
+// to be the intended behavior given the definition of
+// 'deduction substitution loci' in [temp.deduct].
+::MarkUsedTemplateParameters(
+S.Context,
+S.Context.getFunctionTypeWithExceptionSpec(FD2->getType(), EST_None),
+/*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters);
 break;
   }
 
diff --git 
a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp 
b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp
new file mode 100644
index 0..cc1d4ecda2ecc
--- /dev/null
+++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+template
+struct A { };
+
+constexpr A a;
+constexpr A b;
+
+constexpr int* x = nullptr;
+constexpr short* y = nullptr;
+
+namespace ExplicitArgs {
+  template
+  constexpr int f(U) noexcept(noexcept(T())) {
+return 0;
+  }
+
+  template
+  constexpr int f(T*) noexcept {
+return 1;
+  }
+
+  template<>
+  constexpr int f(int*) noexcept {
+return 2;
+  }
+
+  static_assert(f(1) == 0);
+  static_assert(f(y) == 1);
+  static_assert(f(x) == 2);
+
+  

[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)

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

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

We do not deduce template arguments from the exception specification when 
determining the primary template of a function template specialization or when 
taking the address of a function template. Therefore, this patch changes 
`isAtLeastAsSpecializedAs` such that we do not mark template parameters in the 
exception specification as 'used' during partial ordering (per 
[[temp.deduct.partial] p12](http://eel.is/c++draft/temp.deduct.partial#12)) to 
prevent the following from being ambiguous:

```cpp
template
void f(U) noexcept(noexcept(T())); // #1

template
void f(T*) noexcept; // #2

template<>
void f(int*) noexcept; // currently ambiguous, selects #2 with this patch 
applied 
```

Although there is no corresponding wording in the standard, this seems to be 
the intended behavior given the definition of _deduction substitution loci_ in 
[[temp.deduct.general] p7](http://eel.is/c++draft/temp.deduct.general#7) (and 
EDG does the same thing). 

>From 0ef86c6bdf8fc89e771039a0e4bae88a8ebb2702 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Wed, 8 May 2024 08:43:23 -0400
Subject: [PATCH] [Clang][Sema] Do not mark template parameters in the
 exception specification as used during partial ordering

---
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 36 +++---
 .../temp.deduct/temp.deduct.partial/p3.cpp| 72 +++
 2 files changed, 100 insertions(+), 8 deletions(-)
 create mode 100644 
clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index fe7e35d841510..c17c5838803a8 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5453,7 +5453,7 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
 // is used.
 if (DeduceTemplateArgumentsByTypeMatch(
 S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced,
-TDF_None,
+TDF_AllowCompatibleFunctionType,
 /*PartialOrdering=*/true) != TemplateDeductionResult::Success)
   return false;
 break;
@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
   switch (TPOC) {
   case TPOC_Call:
 for (unsigned I = 0, N = Args2.size(); I != N; ++I)
-  ::MarkUsedTemplateParameters(S.Context, Args2[I], false,
-   TemplateParams->getDepth(),
-   UsedParameters);
+  ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false,
+   TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Conversion:
-::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
+::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(),
+ /*OnlyDeduced=*/false,
  TemplateParams->getDepth(), UsedParameters);
 break;
 
   case TPOC_Other:
-::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
- TemplateParams->getDepth(),
- UsedParameters);
+// We do not deduce template arguments from the exception specification
+// when determining the primary template of a function template
+// specialization or when taking the address of a function template.
+// Therefore, we do not mark template parameters in the exception
+// specification as used during partial ordering to prevent the following
+// from being ambiguous:
+//
+//   template
+//   void f(U) noexcept(noexcept(T())); // #1
+//
+//   template
+//   void f(T*) noexcept; // #2
+//
+//   template<>
+//   void f(int*) noexcept; // explicit specialization of #2
+//
+// Although there is no corresponding wording in the standard, this seems
+// to be the intended behavior given the definition of
+// 'deduction substitution loci' in [temp.deduct].
+::MarkUsedTemplateParameters(
+S.Context,
+S.Context.getFunctionTypeWithExceptionSpec(FD2->getType(), EST_None),
+/*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters);
 break;
   }
 
diff --git 
a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp 
b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp
new file mode 100644
index 0..cc1d4ecda2ecc
--- /dev/null
+++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+template
+struct A { };
+
+constexpr A a;
+constexpr A b;
+
+constexpr int* x = nullptr;
+constexpr short* y = nullptr;
+
+namespace ExplicitArgs {
+  template
+  constexpr int f(U) noexcept(noexcept(T())) {
+return