-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[clang] Implement CWG2815 #132778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[clang] Implement CWG2815 #132778
Conversation
CWG2815 "Overload resolution for references/pointers to `noexcept` functions"
@llvm/pr-subscribers-clang Author: None (offsetof) ChangesCWG2815 "Overload resolution for references/pointers to Full diff: https://github.com/llvm/llvm-project/pull/132778.diff 5 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8182bccdd2da8..a3af19f79d9c3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -110,12 +110,16 @@ Resolutions to C++ Defect Reports
two releases. The improvements to template template parameter matching implemented
in the previous release, as described in P3310 and P3579, made this flag unnecessary.
+- Implemented |CWG2815|_
- Implemented `CWG2918 Consideration of constraints for address of overloaded `
`function <https://cplusplus.github.io/CWG/issues/2918.html>`_
- Bumped the ``__cpp_constexpr`` feature-test macro to ``202002L`` in C++20 mode as indicated in
`P2493R0 <https://wg21.link/P2493R0>`_.
+.. |CWG2815| replace:: CWG2815 Overload resolution for references/pointers to ``noexcept`` functions
+.. _CWG2815: https://cplusplus.github.io/CWG/issues/2815
+
C Language Changes
------------------
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 856b505e92214..da13c9c7db401 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4907,7 +4907,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
if (CheckExceptionSpecCompatibility(From, ToType))
return ExprError();
- From = ImpCastExprToType(From, ToType, CK_NoOp, VK_PRValue,
+ From = ImpCastExprToType(From, ToType.getNonReferenceType(), CK_NoOp,
+ From->getValueKind(),
/*BasePath=*/nullptr, CCK)
.get();
break;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6d8006b35dcf4..aa55bf03edaa0 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -5229,10 +5229,23 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
S.CompareReferenceRelationship(DeclLoc, T1, T2, &RefConv);
auto SetAsReferenceBinding = [&](bool BindsDirectly) {
+ // C++2c [over.ics.ref] p1:
+ // When a parameter of type "reference to cv T" binds directly
+ // to an argument expression:
+ // * If the argument expression has a type that is a derived class
+ // of the parameter type, the implicit conversion sequence is a
+ // derived-to-base conversion.
+ // * Otherwise, if the type of the argument is possibly cv-qualified T,
+ // or if T is an array type of unknown bound with element type U
+ // and the argument has an array type of known bound whose element
+ // type is possibly cv-qualified U, the implicit conversion
+ // sequence is the identity conversion.
+ // * Otherwise, if T is a function type, the implicit conversion
+ // sequence is a function pointer conversion.
+ // * Otherwise, the implicit conversion sequence is a qualification
+ // conversion.
ICS.setStandard();
ICS.Standard.First = ICK_Identity;
- // FIXME: A reference binding can be a function conversion too. We should
- // consider that when ordering reference-to-function bindings.
ICS.Standard.Second = (RefConv & Sema::ReferenceConversions::DerivedToBase)
? ICK_Derived_To_Base
: (RefConv & Sema::ReferenceConversions::ObjC)
@@ -5242,10 +5255,12 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// FIXME: As a speculative fix to a defect introduced by CWG2352, we rank
// a reference binding that performs a non-top-level qualification
// conversion as a qualification conversion, not as an identity conversion.
- ICS.Standard.Third = (RefConv &
- Sema::ReferenceConversions::NestedQualification)
- ? ICK_Qualification
- : ICK_Identity;
+ ICS.Standard.Third =
+ (RefConv & Sema::ReferenceConversions::Function)
+ ? ICK_Function_Conversion
+ : (RefConv & Sema::ReferenceConversions::NestedQualification)
+ ? ICK_Qualification
+ : ICK_Identity;
ICS.Standard.setFromType(T2);
ICS.Standard.setToType(0, T2);
ICS.Standard.setToType(1, T1);
@@ -5273,13 +5288,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
//
// Per C++ [over.ics.ref]p4, we don't check the bit-field property here.
if (InitCategory.isLValue() && RefRelationship == Sema::Ref_Compatible) {
- // C++ [over.ics.ref]p1:
- // When a parameter of reference type binds directly (8.5.3)
- // to an argument expression, the implicit conversion sequence
- // is the identity conversion, unless the argument expression
- // has a type that is a derived class of the parameter type,
- // in which case the implicit conversion sequence is a
- // derived-to-base Conversion (13.3.3.1).
SetAsReferenceBinding(/*BindsDirectly=*/true);
// Nothing more to do: the inaccessibility/ambiguity check for
diff --git a/clang/test/CXX/drs/cwg28xx.cpp b/clang/test/CXX/drs/cwg28xx.cpp
index b32e649374893..3f65b7b7e46da 100644
--- a/clang/test/CXX/drs/cwg28xx.cpp
+++ b/clang/test/CXX/drs/cwg28xx.cpp
@@ -47,6 +47,28 @@ void f() {
#endif
} // namespace cwg2813
+namespace cwg2815 { // cwg2815: 21
+#if __cpp_noexcept_function_type >= 201510
+int arg() noexcept;
+
+int f(int (&)() noexcept);
+void f(int (&)());
+int i = f(arg);
+
+int g(int (*)() noexcept);
+void g(int (&)());
+int j = g(arg);
+
+int h(int (&)() noexcept);
+void h(int (*)());
+int k = h(arg);
+
+int a(int (*)()); // expected-note {{candidate function}}
+int a(int (&)()); // expected-note {{candidate function}}
+int x = a(arg); // expected-error {{call to 'a' is ambiguous}}
+#endif
+} // namespace cwg2815
+
namespace cwg2819 { // cwg2819: 19 c++26
#if __cplusplus >= 201103L
// CWG 2024-04-19: This issue is not a DR.
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 16a9b26052f87..4590bcec6df9e 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -12529,11 +12529,11 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td>Direct or copy initialization for omitted aggregate initializers</td>
<td class="unknown" align="center">Unknown</td>
</tr>
- <tr class="open" id="2117">
+ <tr id="2117">
<td><a href="https://cplusplus.github.io/CWG/issues/2117.html">2117</a></td>
- <td>open</td>
+ <td>NAD</td>
<td>Explicit specializations and <TT>constexpr</TT> function templates</td>
- <td align="center">Not resolved</td>
+ <td class="unknown" align="center">Unknown</td>
</tr>
<tr class="open" id="2118">
<td><a href="https://cplusplus.github.io/CWG/issues/2118.html">2118</a></td>
@@ -16738,7 +16738,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2815.html">2815</a></td>
<td>DR</td>
<td>Overload resolution for references/pointers to <TT>noexcept</TT> functions</td>
- <td class="unknown" align="center">Unknown</td>
+ <td class="unreleased" align="center">Clang 21</td>
</tr>
<tr class="open" id="2816">
<td><a href="https://cplusplus.github.io/CWG/issues/2816.html">2816</a></td>
@@ -17909,6 +17909,42 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td>open</td>
<td>Missing Annex C entry for <TT>void</TT> object declarations</td>
<td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="3009">
+ <td><a href="https://cplusplus.github.io/CWG/issues/3009.html">3009</a></td>
+ <td>open</td>
+ <td>Unclear rules for constant initialization</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="3010">
+ <td><a href="https://cplusplus.github.io/CWG/issues/3010.html">3010</a></td>
+ <td>open</td>
+ <td>constexpr placement-new should require transparent replaceability</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="3011">
+ <td><a href="https://cplusplus.github.io/CWG/issues/3011.html">3011</a></td>
+ <td>open</td>
+ <td>Parenthesized aggregate initialization for <I>new-expression</I>s</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="3012">
+ <td><a href="https://cplusplus.github.io/CWG/issues/3012.html">3012</a></td>
+ <td>open</td>
+ <td>Deviating <TT>constexpr</TT> or <TT>consteval</TT> across translation units</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="3013">
+ <td><a href="https://cplusplus.github.io/CWG/issues/3013.html">3013</a></td>
+ <td>open</td>
+ <td>Disallowing macros for <TT>#embed</TT> parameters</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="3014">
+ <td><a href="https://cplusplus.github.io/CWG/issues/3014.html">3014</a></td>
+ <td>open</td>
+ <td>Comma-delimited vs. comma-separated output for <TT>#embed</TT></td>
+ <td align="center">Not resolved</td>
</tr></table>
</div>
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
clang/www/cxx_dr_status.html
Outdated
<tr class="open" id="2117"> | ||
<tr id="2117"> | ||
<td><a href="https://cplusplus.github.io/CWG/issues/2117.html">2117</a></td> | ||
<td>open</td> | ||
<td>NAD</td> | ||
<td>Explicit specializations and <TT>constexpr</TT> function templates</td> | ||
<td align="center">Not resolved</td> | ||
<td class="unknown" align="center">Unknown</td> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you leave out unrelated changes?
17912~17947 ditto
clang/lib/Sema/SemaOverload.cpp
Outdated
@@ -5229,10 +5229,23 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, | |||
S.CompareReferenceRelationship(DeclLoc, T1, T2, &RefConv); | |||
|
|||
auto SetAsReferenceBinding = [&](bool BindsDirectly) { | |||
// C++2c [over.ics.ref] p1: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not apply only to c++26, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right - the wording appears first in C++26 but the relevant changes are DRs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe
// C++2c [over.ics.ref] p1: | |
// C++26 [over.ics.ref]p1 (CWG2815): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a reference to CWG2803 and CWG2815.
clang/lib/Sema/SemaOverload.cpp
Outdated
ICS.Standard.Third = | ||
(RefConv & Sema::ReferenceConversions::Function) | ||
? ICK_Function_Conversion | ||
: (RefConv & Sema::ReferenceConversions::NestedQualification) | ||
? ICK_Qualification | ||
: ICK_Identity; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is getting complicated. How about
if (RefConv & Sema::ReferenceConversions::Function)
ICS.Standard.Third = ICK_Function_Conversion;
else if (RefConv & Sema::ReferenceConversions::NestedQualification)
ICS.Standard.Third = ICK_Qualification;
else
ICS.Standard.Third = ICK_Qualification
clang/docs/ReleaseNotes.rst
Outdated
@@ -110,12 +110,16 @@ Resolutions to C++ Defect Reports | |||
two releases. The improvements to template template parameter matching implemented | |||
in the previous release, as described in P3310 and P3579, made this flag unnecessary. | |||
|
|||
- Implemented |CWG2815|_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use a simple link as done just below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done (at the cost of fancy formatting for "noexcept
").
clang/lib/Sema/SemaOverload.cpp
Outdated
@@ -5229,10 +5229,23 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, | |||
S.CompareReferenceRelationship(DeclLoc, T1, T2, &RefConv); | |||
|
|||
auto SetAsReferenceBinding = [&](bool BindsDirectly) { | |||
// C++2c [over.ics.ref] p1: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe
// C++2c [over.ics.ref] p1: | |
// C++26 [over.ics.ref]p1 (CWG2815): |
clang/test/CXX/drs/cwg28xx.cpp
Outdated
namespace cwg2815 { // cwg2815: 21 | ||
#if __cpp_noexcept_function_type >= 201510 | ||
int arg() noexcept; | ||
|
||
int f(int (&)() noexcept); | ||
void f(int (&)()); | ||
int i = f(arg); | ||
|
||
int g(int (*)() noexcept); | ||
void g(int (&)()); | ||
int j = g(arg); | ||
|
||
int h(int (&)() noexcept); | ||
void h(int (*)()); | ||
int k = h(arg); | ||
|
||
int a(int (*)()); // expected-note {{candidate function}} | ||
int a(int (&)()); // expected-note {{candidate function}} | ||
int x = a(arg); // expected-error {{call to 'a' is ambiguous}} | ||
#endif | ||
} // namespace cwg2815 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you test which overload is called (for example by making them constexpr and checking a return value with static assert)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's already being tested with return types - the wrong overloads all return void
.
Replace feature-test macro with `__cplusplus`
clang/test/CXX/drs/cwg28xx.cpp
Outdated
int a(int (*)()); // expected-note {{candidate function}} | ||
int a(int (&)()); // expected-note {{candidate function}} | ||
int x = a(arg); // expected-error {{call to 'a' is ambiguous}} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of these tests except f
should pass in c++11, right?
I think only f
should be in the #if __cplusplus >= 201703L
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
f
, g
and h
would fail in standard versions without noexcept
in the type system (pre-C++17).
int a(int (&)()); | ||
int x = a(arg); | ||
// expected-error@-1 {{call to 'a' is ambiguous}} | ||
// expected-note@-4 {{candidate function}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// expected-note@-4 {{candidate function}} | |
// expected-note@#cwg2815-a-ptr {{candidate function}} |
As you've experienced yourself, maintaining relative line offsets is annoying. Counting lines outside of very trivial cases it annoying for reviewers, too.
CWG2815 "Overload resolution for references/pointers to
noexcept
functions"