Author: Vlad Serebrennikov Date: 2024-05-17T16:02:44+04:00 New Revision: a68d20e986053ec571223a9f3ead3e146a27dc82
URL: https://github.com/llvm/llvm-project/commit/a68d20e986053ec571223a9f3ead3e146a27dc82 DIFF: https://github.com/llvm/llvm-project/commit/a68d20e986053ec571223a9f3ead3e146a27dc82.diff LOG: [clang] Implement CWG2428 "Deprecating a concept" (#92295) This patch allows attributes to be attached to C++20 concepts, implementing [CWG2428](https://cplusplus.github.io/CWG/issues/2428.html). Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Sema/Sema.h clang/lib/Parse/ParseTemplate.cpp clang/lib/Sema/SemaChecking.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaTemplate.cpp clang/lib/Sema/SemaType.cpp clang/test/CXX/drs/cwg24xx.cpp clang/test/SemaCXX/cxx-deprecated.cpp clang/www/cxx_dr_status.html Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 65d191b6161a4..40e41c940b6af 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -226,6 +226,9 @@ Resolutions to C++ Defect Reports - Clang now diagnoses declarative nested-name-specifiers with pack-index-specifiers. (`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers <https://cplusplus.github.io/CWG/issues/2858.html>`_). +- Clang now allows attributes on concepts. + (`CWG2428: Deprecating a concept <https://cplusplus.github.io/CWG/issues/2428.html>`_). + - P0522 implementation is enabled by default in all language versions, and provisional wording for CWG2398 is implemented. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 873592a2d430a..226987b975700 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2022,6 +2022,8 @@ class Sema final : public SemaBase { void CheckTCBEnforcement(const SourceLocation CallExprLoc, const NamedDecl *Callee); + void CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc); + private: void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, const ArraySubscriptExpr *ASE = nullptr, @@ -9356,7 +9358,8 @@ class Sema final : public SemaBase { Decl *ActOnConceptDefinition(Scope *S, MultiTemplateParamsArg TemplateParameterLists, const IdentifierInfo *Name, - SourceLocation NameLoc, Expr *ConstraintExpr); + SourceLocation NameLoc, Expr *ConstraintExpr, + const ParsedAttributesView &Attrs); void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous, bool &AddToScope); diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 665253a6674d2..8f841be422dd8 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -167,9 +167,13 @@ Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization( LastParamListWasEmpty); // Parse the actual template declaration. - if (Tok.is(tok::kw_concept)) - return Actions.ConvertDeclToDeclGroup( - ParseConceptDefinition(TemplateInfo, DeclEnd)); + if (Tok.is(tok::kw_concept)) { + Decl *ConceptDecl = ParseConceptDefinition(TemplateInfo, DeclEnd); + // We need to explicitly pass ConceptDecl to ParsingDeclRAIIObject, so that + // delayed diagnostics (e.g. warn_deprecated) have a Decl to work with. + ParsingTemplateParams.complete(ConceptDecl); + return Actions.ConvertDeclToDeclGroup(ConceptDecl); + } return ParseDeclarationAfterTemplate( Context, TemplateInfo, ParsingTemplateParams, DeclEnd, AccessAttrs, AS); @@ -316,7 +320,8 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo, const IdentifierInfo *Id = Result.Identifier; SourceLocation IdLoc = Result.getBeginLoc(); - DiagnoseAndSkipCXX11Attributes(); + ParsedAttributes Attrs(AttrFactory); + MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs); if (!TryConsumeToken(tok::equal)) { Diag(Tok.getLocation(), diag::err_expected) << tok::equal; @@ -335,8 +340,8 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo, ExpectAndConsumeSemi(diag::err_expected_semi_declaration); Expr *ConstraintExpr = ConstraintExprResult.get(); return Actions.ActOnConceptDefinition(getCurScope(), - *TemplateInfo.TemplateParams, - Id, IdLoc, ConstraintExpr); + *TemplateInfo.TemplateParams, Id, IdLoc, + ConstraintExpr, Attrs); } /// ParseTemplateParameters - Parses a template-parameter-list enclosed in diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index ecd1821651140..f2dc8e9dd0050 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -8092,6 +8092,12 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc); } +void Sema::CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc) { + if (ConceptDecl *Decl = AutoT->getTypeConstraintConcept()) { + DiagnoseUseOfDecl(Decl, Loc); + } +} + /// CheckConstructorCall - Check a constructor call for correctness and safety /// properties not enforced by the C type system. void Sema::CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 0dbdf923df95a..bb0bee0d234c5 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7573,6 +7573,11 @@ NamedDecl *Sema::ActOnVariableDeclarator( tryToFixVariablyModifiedVarType(TInfo, R, D.getIdentifierLoc(), /*DiagID=*/0); + if (const AutoType *AutoT = R->getAs<AutoType>()) + CheckConstrainedAuto( + AutoT, + TInfo->getTypeLoc().getContainedAutoTypeLoc().getConceptNameLoc()); + bool IsMemberSpecialization = false; bool IsVariableTemplateSpecialization = false; bool IsPartialSpecialization = false; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 1b3f1e8bf80f4..0462d3520037f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5653,6 +5653,8 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, /*UpdateArgsWithConversions=*/false)) return ExprError(); + DiagnoseUseOfDecl(NamedConcept, ConceptNameInfo.getLoc()); + auto *CSD = ImplicitConceptSpecializationDecl::Create( Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(), CanonicalConverted); @@ -9859,7 +9861,8 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S, Decl *Sema::ActOnConceptDefinition( Scope *S, MultiTemplateParamsArg TemplateParameterLists, - const IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr) { + const IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr, + const ParsedAttributesView &Attrs) { DeclContext *DC = CurContext; if (!DC->getRedeclContext()->isFileContext()) { @@ -9921,6 +9924,9 @@ Decl *Sema::ActOnConceptDefinition( ActOnDocumentableDecl(NewDecl); if (AddToScope) PushOnScopeChains(NewDecl, S); + + ProcessDeclAttributeList(S, NewDecl, Attrs); + return NewDecl; } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 9c002d56b5bd9..c19c8cc34dd3b 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -6392,6 +6392,11 @@ TypeResult Sema::ActOnTypeName(Declarator &D) { CheckExtraCXXDefaultArguments(D); } + if (const AutoType *AutoT = T->getAs<AutoType>()) + CheckConstrainedAuto( + AutoT, + TInfo->getTypeLoc().getContainedAutoTypeLoc().getConceptNameLoc()); + return CreateParsedType(T, TInfo); } diff --git a/clang/test/CXX/drs/cwg24xx.cpp b/clang/test/CXX/drs/cwg24xx.cpp index 75e1a614765c5..4c7b1506e86ea 100644 --- a/clang/test/CXX/drs/cwg24xx.cpp +++ b/clang/test/CXX/drs/cwg24xx.cpp @@ -45,6 +45,48 @@ void fallthrough(int n) { #endif } +namespace cwg2428 { // cwg2428: 19 +#if __cplusplus >= 202002L +template <typename> +concept C [[deprecated]] = true; // #cwg2428-C + +template <typename> +[[deprecated]] concept C2 = true; +// expected-error@-1 {{expected unqualified-id}} + +template <typename T> +concept C3 = C<T>; +// expected-warning@-1 {{'C' is deprecated}} +// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} + +template <typename T, C U> +// expected-warning@-1 {{'C' is deprecated}} +// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} +requires C<T> +// expected-warning@-1 {{'C' is deprecated}} +// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} +void f() { + bool b = C<int>; + // expected-warning@-1 {{'C' is deprecated}} + // expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} +}; + +void g(C auto a) {}; +// expected-warning@-1 {{'C' is deprecated}} +// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} + +template <typename T> +auto h() -> C auto { +// expected-warning@-1 {{'C' is deprecated}} +// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} + C auto foo = T(); + // expected-warning@-1 {{'C' is deprecated}} + // expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} + return foo; +} +#endif +} // namespace cwg2428 + namespace cwg2430 { // cwg2430: 2.7 struct S { S f(S s) { return s; } diff --git a/clang/test/SemaCXX/cxx-deprecated.cpp b/clang/test/SemaCXX/cxx-deprecated.cpp index aa4501d53197a..81eb07608300d 100644 --- a/clang/test/SemaCXX/cxx-deprecated.cpp +++ b/clang/test/SemaCXX/cxx-deprecated.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s namespace [[deprecated]] {} // expected-warning {{'deprecated' attribute on anonymous namespace ignored}} @@ -27,3 +27,13 @@ namespace M = N; // expected-warning {{'N' is deprecated}} // Shouldn't diag: [[nodiscard, deprecated("")]] int PR37935(); + +namespace cxx20_concept { +template <typename> +concept C __attribute__((deprecated)) = true; // #C + +template <C T> +// expected-warning@-1 {{'C' is deprecated}} +// expected-note@#C {{'C' has been explicitly marked deprecated here}} +void f(); +} // namespace cxx20_concept diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 2ed79fa21db26..5d517d358672c 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -14376,7 +14376,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/2428.html">2428</a></td> <td>C++23</td> <td>Deprecating a concept</td> - <td class="unknown" align="center">Unknown</td> + <td class="unreleased" align="center">Clang 19</td> </tr> <tr id="2429"> <td><a href="https://cplusplus.github.io/CWG/issues/2429.html">2429</a></td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits