diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 35c31452cef41..9fd1cb0906205 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 `_). +- Clang now allows trailing requires clause on explicit deduction guides. + (`CWG2707: Deduction guides cannot have a trailing requires-clause `_). + C Language Changes ------------------ diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 252e6e9256414..2693cc0e95b4b 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 9e8f152852fd1..0f591022e6854 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 01143391edab4..f5a0aa8f82512 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 1bf0e800a3622..0e536f71a2f70 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 c3cb9d5d8c2c3..1c35c7d288e32 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 f141568ba6c22..b082e1c122a09 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 -R(T) -> R requires true; // expected-error{{deduction guide cannot have a requires clause}} +R(T) -> R requires true; diff --git a/clang/test/CXX/drs/cwg27xx.cpp b/clang/test/CXX/drs/cwg27xx.cpp index 2b57dbc60aed7..581e2af822d55 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 struct A { + T value[N]; +}; + +template +A(T...) -> A 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 e5c5e50104fda..978351716ce33 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -16089,7 +16089,7 @@

C++ defect report implementation status

2707 DRWP Deduction guides cannot have a trailing requires-clause - Unknown + Clang 20 2708 @@ -17334,7 +17334,7 @@

C++ defect report implementation status

2913 tentatively ready Grammar for deduction-guide has requires-clause in the wrong position - Not resolved + Clang 20 2914