Skip to content

Commit 915df1a

Browse files
authored
[Clang] Implement CWG 2707 "Deduction guides cannot have a trailing requires-clause" (#110473)
Closes #98595
1 parent f3a4def commit 915df1a

File tree

9 files changed

+50
-20
lines changed

9 files changed

+50
-20
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ Resolutions to C++ Defect Reports
205205
- Reject explicit object parameters with type ``void`` (``this void``).
206206
(`CWG2915: Explicit object parameters of type void <https://cplusplus.github.io/CWG/issues/2915.html>`_).
207207

208+
- Clang now allows trailing requires clause on explicit deduction guides.
209+
(`CWG2707: Deduction guides cannot have a trailing requires-clause <https://cplusplus.github.io/CWG/issues/2707.html>`_).
210+
208211
C Language Changes
209212
------------------
210213

clang/include/clang/AST/DeclCXX.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,9 +1965,11 @@ class CXXDeductionGuideDecl : public FunctionDecl {
19651965
ExplicitSpecifier ES,
19661966
const DeclarationNameInfo &NameInfo, QualType T,
19671967
TypeSourceInfo *TInfo, SourceLocation EndLocation,
1968-
CXXConstructorDecl *Ctor, DeductionCandidate Kind)
1968+
CXXConstructorDecl *Ctor, DeductionCandidate Kind,
1969+
Expr *TrailingRequiresClause)
19691970
: FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo,
1970-
SC_None, false, false, ConstexprSpecKind::Unspecified),
1971+
SC_None, false, false, ConstexprSpecKind::Unspecified,
1972+
TrailingRequiresClause),
19711973
Ctor(Ctor), ExplicitSpec(ES) {
19721974
if (EndLocation.isValid())
19731975
setRangeEnd(EndLocation);
@@ -1987,7 +1989,8 @@ class CXXDeductionGuideDecl : public FunctionDecl {
19871989
ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
19881990
TypeSourceInfo *TInfo, SourceLocation EndLocation,
19891991
CXXConstructorDecl *Ctor = nullptr,
1990-
DeductionCandidate Kind = DeductionCandidate::Normal);
1992+
DeductionCandidate Kind = DeductionCandidate::Normal,
1993+
Expr *TrailingRequiresClause = nullptr);
19911994

19921995
static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C,
19931996
GlobalDeclID ID);

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3050,8 +3050,6 @@ def note_is_deducible_constraint_evaluated_to_false : Note<
30503050
"cannot deduce template arguments for %0 from %1">;
30513051
def err_constrained_virtual_method : Error<
30523052
"virtual function cannot have a requires clause">;
3053-
def err_trailing_requires_clause_on_deduction_guide : Error<
3054-
"deduction guide cannot have a requires clause">;
30553053
def err_constrained_non_templated_function
30563054
: Error<"non-templated function cannot have a requires clause">;
30573055
def err_non_temp_spec_requires_clause : Error<

clang/lib/AST/DeclCXX.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2211,17 +2211,18 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create(
22112211
ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
22122212
ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
22132213
TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor,
2214-
DeductionCandidate Kind) {
2215-
return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T,
2216-
TInfo, EndLocation, Ctor, Kind);
2214+
DeductionCandidate Kind, Expr *TrailingRequiresClause) {
2215+
return new (C, DC)
2216+
CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T, TInfo,
2217+
EndLocation, Ctor, Kind, TrailingRequiresClause);
22172218
}
22182219

22192220
CXXDeductionGuideDecl *
22202221
CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
22212222
return new (C, ID) CXXDeductionGuideDecl(
22222223
C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(),
22232224
QualType(), nullptr, SourceLocation(), nullptr,
2224-
DeductionCandidate::Normal);
2225+
DeductionCandidate::Normal, nullptr);
22252226
}
22262227

22272228
RequiresExprBodyDecl *RequiresExprBodyDecl::Create(

clang/lib/Sema/SemaDecl.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9293,15 +9293,12 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
92939293
TrailingRequiresClause);
92949294

92959295
} else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
9296-
if (TrailingRequiresClause)
9297-
SemaRef.Diag(TrailingRequiresClause->getBeginLoc(),
9298-
diag::err_trailing_requires_clause_on_deduction_guide)
9299-
<< TrailingRequiresClause->getSourceRange();
93009296
if (SemaRef.CheckDeductionGuideDeclarator(D, R, SC))
93019297
return nullptr;
9302-
return CXXDeductionGuideDecl::Create(SemaRef.Context, DC, D.getBeginLoc(),
9303-
ExplicitSpecifier, NameInfo, R, TInfo,
9304-
D.getEndLoc());
9298+
return CXXDeductionGuideDecl::Create(
9299+
SemaRef.Context, DC, D.getBeginLoc(), ExplicitSpecifier, NameInfo, R,
9300+
TInfo, D.getEndLoc(), /*Ctor=*/nullptr,
9301+
/*Kind=*/DeductionCandidate::Normal, TrailingRequiresClause);
93059302
} else if (DC->isRecord()) {
93069303
// If the name of the function is the same as the name of the record,
93079304
// then this must be an invalid constructor that has a return type.

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2233,7 +2233,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
22332233
SemaRef.Context, DC, D->getInnerLocStart(),
22342234
InstantiatedExplicitSpecifier, NameInfo, T, TInfo,
22352235
D->getSourceRange().getEnd(), DGuide->getCorrespondingConstructor(),
2236-
DGuide->getDeductionCandidateKind());
2236+
DGuide->getDeductionCandidateKind(), TrailingRequiresClause);
22372237
Function->setAccess(D->getAccess());
22382238
} else {
22392239
Function = FunctionDecl::Create(

clang/test/CXX/dcl/dcl.decl/p3.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,4 @@ struct R {
6565
};
6666

6767
template<typename T>
68-
R(T) -> R<T> requires true; // expected-error{{deduction guide cannot have a requires clause}}
68+
R(T) -> R<T> requires true;

clang/test/CXX/drs/cwg27xx.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,31 @@ static_assert(false, f().s);
201201
#endif
202202
} // namespace cwg2798
203203

204+
namespace cwg2707 { // cwg2707: 20
205+
206+
#if __cplusplus >= 202002L
207+
208+
template <class T, unsigned N> struct A {
209+
T value[N];
210+
};
211+
212+
template <typename... T>
213+
A(T...) -> A<int, sizeof...(T)> requires (sizeof...(T) == 2);
214+
215+
// Brace elision is not allowed for synthesized CTAD guides if the array size
216+
// is value-dependent.
217+
// So this should pick up our explicit deduction guide.
218+
A a = {1, 2};
219+
220+
A b = {3, 4, 5};
221+
// expected-error@-1 {{no viable constructor or deduction guide}} \
222+
// expected-note@-13 {{candidate function template not viable}} \
223+
// expected-note@-13 {{implicit deduction guide}} \
224+
// expected-note@-8 {{constraints not satisfied}} \
225+
// expected-note@-8 {{because 'sizeof...(T) == 2' (3 == 2) evaluated to false}} \
226+
// expected-note@-13 {{candidate function template not viable}} \
227+
// expected-note@-13 {{implicit deduction guide}}
228+
229+
#endif
230+
231+
} // namespace cwg2707

clang/www/cxx_dr_status.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16089,7 +16089,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
1608916089
<td><a href="https://cplusplus.github.io/CWG/issues/2707.html">2707</a></td>
1609016090
<td>DRWP</td>
1609116091
<td>Deduction guides cannot have a trailing <I>requires-clause</I></td>
16092-
<td class="unknown" align="center">Unknown</td>
16092+
<td class="unreleased" align="center">Clang 20</td>
1609316093
</tr>
1609416094
<tr id="2708">
1609516095
<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>
1733417334
<td><a href="https://cplusplus.github.io/CWG/issues/2913.html">2913</a></td>
1733517335
<td>tentatively ready</td>
1733617336
<td>Grammar for <I>deduction-guide</I> has <I>requires-clause</I> in the wrong position</td>
17337-
<td align="center">Not resolved</td>
17337+
<td class="unreleased" align="center">Clang 20</td>
1733817338
</tr>
1733917339
<tr class="open" id="2914">
1734017340
<td><a href="https://cplusplus.github.io/CWG/issues/2914.html">2914</a></td>

0 commit comments

Comments
 (0)