-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[Clang] Implement CWG 2707 "Deduction guides cannot have a trailing requires-clause" #110473
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
Conversation
@llvm/pr-subscribers-clang Author: Younan Zhang (zyn0217) ChangesCloses #98595 Full diff: https://github.com/llvm/llvm-project/pull/110473.diff 9 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 35c31452cef411..9fd1cb09062059 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -205,6 +205,9 @@ Resolutions to C++ Defect Reports
- Reject explicit object parameters with type ``void`` (``this void``).
(`CWG2915: Explicit object parameters of type void <https://cplusplus.github.io/CWG/issues/2915.html>`_).
+- Clang now allows trailing requires clause on explicit deduction guides.
+ (`CWG2707: Deduction guides cannot have a trailing requires-clause <https://cplusplus.github.io/CWG/issues/2707.html>`_).
+
C Language Changes
------------------
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 252e6e92564142..2693cc0e95b4b2 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1965,9 +1965,11 @@ class CXXDeductionGuideDecl : public FunctionDecl {
ExplicitSpecifier ES,
const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, SourceLocation EndLocation,
- CXXConstructorDecl *Ctor, DeductionCandidate Kind)
+ CXXConstructorDecl *Ctor, DeductionCandidate Kind,
+ Expr *TrailingRequiresClause)
: FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo,
- SC_None, false, false, ConstexprSpecKind::Unspecified),
+ SC_None, false, false, ConstexprSpecKind::Unspecified,
+ TrailingRequiresClause),
Ctor(Ctor), ExplicitSpec(ES) {
if (EndLocation.isValid())
setRangeEnd(EndLocation);
@@ -1987,7 +1989,8 @@ class CXXDeductionGuideDecl : public FunctionDecl {
ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, SourceLocation EndLocation,
CXXConstructorDecl *Ctor = nullptr,
- DeductionCandidate Kind = DeductionCandidate::Normal);
+ DeductionCandidate Kind = DeductionCandidate::Normal,
+ Expr *TrailingRequiresClause = nullptr);
static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID);
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9e8f152852fd1e..0f591022e68541 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3050,8 +3050,6 @@ def note_is_deducible_constraint_evaluated_to_false : Note<
"cannot deduce template arguments for %0 from %1">;
def err_constrained_virtual_method : Error<
"virtual function cannot have a requires clause">;
-def err_trailing_requires_clause_on_deduction_guide : Error<
- "deduction guide cannot have a requires clause">;
def err_constrained_non_templated_function
: Error<"non-templated function cannot have a requires clause">;
def err_non_temp_spec_requires_clause : Error<
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 01143391edab40..f5a0aa8f82512e 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -2211,9 +2211,10 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create(
ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor,
- DeductionCandidate Kind) {
- return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T,
- TInfo, EndLocation, Ctor, Kind);
+ DeductionCandidate Kind, Expr *TrailingRequiresClause) {
+ return new (C, DC)
+ CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T, TInfo,
+ EndLocation, Ctor, Kind, TrailingRequiresClause);
}
CXXDeductionGuideDecl *
@@ -2221,7 +2222,7 @@ CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) CXXDeductionGuideDecl(
C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(),
QualType(), nullptr, SourceLocation(), nullptr,
- DeductionCandidate::Normal);
+ DeductionCandidate::Normal, nullptr);
}
RequiresExprBodyDecl *RequiresExprBodyDecl::Create(
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 1bf0e800a36228..0e536f71a2f70d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9293,15 +9293,12 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
TrailingRequiresClause);
} else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
- if (TrailingRequiresClause)
- SemaRef.Diag(TrailingRequiresClause->getBeginLoc(),
- diag::err_trailing_requires_clause_on_deduction_guide)
- << TrailingRequiresClause->getSourceRange();
if (SemaRef.CheckDeductionGuideDeclarator(D, R, SC))
return nullptr;
- return CXXDeductionGuideDecl::Create(SemaRef.Context, DC, D.getBeginLoc(),
- ExplicitSpecifier, NameInfo, R, TInfo,
- D.getEndLoc());
+ return CXXDeductionGuideDecl::Create(
+ SemaRef.Context, DC, D.getBeginLoc(), ExplicitSpecifier, NameInfo, R,
+ TInfo, D.getEndLoc(), /*Ctor=*/nullptr,
+ /*Kind=*/DeductionCandidate::Normal, TrailingRequiresClause);
} else if (DC->isRecord()) {
// If the name of the function is the same as the name of the record,
// then this must be an invalid constructor that has a return type.
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c3cb9d5d8c2c3d..1c35c7d288e325 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2233,7 +2233,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
SemaRef.Context, DC, D->getInnerLocStart(),
InstantiatedExplicitSpecifier, NameInfo, T, TInfo,
D->getSourceRange().getEnd(), DGuide->getCorrespondingConstructor(),
- DGuide->getDeductionCandidateKind());
+ DGuide->getDeductionCandidateKind(), TrailingRequiresClause);
Function->setAccess(D->getAccess());
} else {
Function = FunctionDecl::Create(
diff --git a/clang/test/CXX/dcl/dcl.decl/p3.cpp b/clang/test/CXX/dcl/dcl.decl/p3.cpp
index f141568ba6c221..b082e1c122a09e 100644
--- a/clang/test/CXX/dcl/dcl.decl/p3.cpp
+++ b/clang/test/CXX/dcl/dcl.decl/p3.cpp
@@ -65,4 +65,4 @@ struct R {
};
template<typename T>
-R(T) -> R<T> requires true; // expected-error{{deduction guide cannot have a requires clause}}
+R(T) -> R<T> requires true;
diff --git a/clang/test/CXX/drs/cwg27xx.cpp b/clang/test/CXX/drs/cwg27xx.cpp
index 2b57dbc60aed70..581e2af822d556 100644
--- a/clang/test/CXX/drs/cwg27xx.cpp
+++ b/clang/test/CXX/drs/cwg27xx.cpp
@@ -201,3 +201,31 @@ static_assert(false, f().s);
#endif
} // namespace cwg2798
+namespace cwg2707 { // cwg2707: 20
+
+#if __cplusplus >= 202002L
+
+template <class T, unsigned N> struct A {
+ T value[N];
+};
+
+template <typename... T>
+A(T...) -> A<int, sizeof...(T)> requires (sizeof...(T) == 2);
+
+// Brace elision is not allowed for synthesized CTAD guides if the array size
+// is value-dependent.
+// So this should pick up our explicit deduction guide.
+A a = {1, 2};
+
+A b = {3, 4, 5};
+// expected-error@-1 {{no viable constructor or deduction guide}} \
+// expected-note@-13 {{candidate function template not viable}} \
+// expected-note@-13 {{implicit deduction guide}} \
+// expected-note@-8 {{constraints not satisfied}} \
+// expected-note@-8 {{because 'sizeof...(T) == 2' (3 == 2) evaluated to false}} \
+// expected-note@-13 {{candidate function template not viable}} \
+// expected-note@-13 {{implicit deduction guide}}
+
+#endif
+
+} // namespace cwg2707
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index e5c5e50104fdaf..978351716ce33d 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -16089,7 +16089,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2707.html">2707</a></td>
<td>DRWP</td>
<td>Deduction guides cannot have a trailing <I>requires-clause</I></td>
- <td class="unknown" align="center">Unknown</td>
+ <td class="unreleased" align="center">Clang 20</td>
</tr>
<tr id="2708">
<td><a href="https://cplusplus.github.io/CWG/issues/2708.html">2708</a></td>
@@ -17334,7 +17334,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2913.html">2913</a></td>
<td>tentatively ready</td>
<td>Grammar for <I>deduction-guide</I> has <I>requires-clause</I> in the wrong position</td>
- <td align="center">Not resolved</td>
+ <td class="unreleased" align="center">Clang 20</td>
</tr>
<tr class="open" id="2914">
<td><a href="https://cplusplus.github.io/CWG/issues/2914.html">2914</a></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.
Thanks, looks good.
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.
You can use 2789 or other tests as a reference for how expected directives are written in DR tests.
@@ -201,3 +201,31 @@ static_assert(false, f().s); | |||
#endif | |||
} // namespace cwg2798 | |||
|
|||
namespace cwg2707 { // cwg2707: 20 |
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.
Given the number of the Core issue, this test should've been placed towards the beginning of the file. We keep them in the ascending order.
A a = {1, 2}; | ||
|
||
A b = {3, 4, 5}; | ||
// expected-error@-1 {{no viable constructor or deduction guide}} \ |
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 directives should reflect the #if __cplusplus >= 202002L
, i.e. since-cxx20-error
.
|
||
A b = {3, 4, 5}; | ||
// expected-error@-1 {{no viable constructor or deduction guide}} \ | ||
// expected-note@-13 {{candidate function template not viable}} \ |
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.
DR tests indeed use relative offsets, but they very intentionally avoid making readers count lines to figure out which line the diagnostic is attached to. This should be converted to bookmarks.
A b = {3, 4, 5}; | ||
// expected-error@-1 {{no viable constructor or deduction guide}} \ | ||
// expected-note@-13 {{candidate function template not viable}} \ | ||
// expected-note@-13 {{implicit deduction guide}} \ |
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.
Notes should be indented relative to the error directive they attach to.
…equires-clause" (llvm#110473) Closes llvm#98595
) This addresses comments from @Endilll in the post commit review of llvm#110473.
Closes #98595