Skip to content

Commit a68d20e

Browse files
authored
[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).
1 parent 0ad275c commit a68d20e

File tree

10 files changed

+95
-10
lines changed

10 files changed

+95
-10
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ Resolutions to C++ Defect Reports
226226
- Clang now diagnoses declarative nested-name-specifiers with pack-index-specifiers.
227227
(`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers <https://cplusplus.github.io/CWG/issues/2858.html>`_).
228228

229+
- Clang now allows attributes on concepts.
230+
(`CWG2428: Deprecating a concept <https://cplusplus.github.io/CWG/issues/2428.html>`_).
231+
229232
- P0522 implementation is enabled by default in all language versions, and
230233
provisional wording for CWG2398 is implemented.
231234

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2022,6 +2022,8 @@ class Sema final : public SemaBase {
20222022
void CheckTCBEnforcement(const SourceLocation CallExprLoc,
20232023
const NamedDecl *Callee);
20242024

2025+
void CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc);
2026+
20252027
private:
20262028
void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
20272029
const ArraySubscriptExpr *ASE = nullptr,
@@ -9356,7 +9358,8 @@ class Sema final : public SemaBase {
93569358
Decl *ActOnConceptDefinition(Scope *S,
93579359
MultiTemplateParamsArg TemplateParameterLists,
93589360
const IdentifierInfo *Name,
9359-
SourceLocation NameLoc, Expr *ConstraintExpr);
9361+
SourceLocation NameLoc, Expr *ConstraintExpr,
9362+
const ParsedAttributesView &Attrs);
93609363

93619364
void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous,
93629365
bool &AddToScope);

clang/lib/Parse/ParseTemplate.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,13 @@ Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization(
167167
LastParamListWasEmpty);
168168

169169
// Parse the actual template declaration.
170-
if (Tok.is(tok::kw_concept))
171-
return Actions.ConvertDeclToDeclGroup(
172-
ParseConceptDefinition(TemplateInfo, DeclEnd));
170+
if (Tok.is(tok::kw_concept)) {
171+
Decl *ConceptDecl = ParseConceptDefinition(TemplateInfo, DeclEnd);
172+
// We need to explicitly pass ConceptDecl to ParsingDeclRAIIObject, so that
173+
// delayed diagnostics (e.g. warn_deprecated) have a Decl to work with.
174+
ParsingTemplateParams.complete(ConceptDecl);
175+
return Actions.ConvertDeclToDeclGroup(ConceptDecl);
176+
}
173177

174178
return ParseDeclarationAfterTemplate(
175179
Context, TemplateInfo, ParsingTemplateParams, DeclEnd, AccessAttrs, AS);
@@ -316,7 +320,8 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,
316320
const IdentifierInfo *Id = Result.Identifier;
317321
SourceLocation IdLoc = Result.getBeginLoc();
318322

319-
DiagnoseAndSkipCXX11Attributes();
323+
ParsedAttributes Attrs(AttrFactory);
324+
MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);
320325

321326
if (!TryConsumeToken(tok::equal)) {
322327
Diag(Tok.getLocation(), diag::err_expected) << tok::equal;
@@ -335,8 +340,8 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,
335340
ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
336341
Expr *ConstraintExpr = ConstraintExprResult.get();
337342
return Actions.ActOnConceptDefinition(getCurScope(),
338-
*TemplateInfo.TemplateParams,
339-
Id, IdLoc, ConstraintExpr);
343+
*TemplateInfo.TemplateParams, Id, IdLoc,
344+
ConstraintExpr, Attrs);
340345
}
341346

342347
/// ParseTemplateParameters - Parses a template-parameter-list enclosed in

clang/lib/Sema/SemaChecking.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8092,6 +8092,12 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
80928092
diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc);
80938093
}
80948094

8095+
void Sema::CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc) {
8096+
if (ConceptDecl *Decl = AutoT->getTypeConstraintConcept()) {
8097+
DiagnoseUseOfDecl(Decl, Loc);
8098+
}
8099+
}
8100+
80958101
/// CheckConstructorCall - Check a constructor call for correctness and safety
80968102
/// properties not enforced by the C type system.
80978103
void Sema::CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType,

clang/lib/Sema/SemaDecl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7573,6 +7573,11 @@ NamedDecl *Sema::ActOnVariableDeclarator(
75737573
tryToFixVariablyModifiedVarType(TInfo, R, D.getIdentifierLoc(),
75747574
/*DiagID=*/0);
75757575

7576+
if (const AutoType *AutoT = R->getAs<AutoType>())
7577+
CheckConstrainedAuto(
7578+
AutoT,
7579+
TInfo->getTypeLoc().getContainedAutoTypeLoc().getConceptNameLoc());
7580+
75767581
bool IsMemberSpecialization = false;
75777582
bool IsVariableTemplateSpecialization = false;
75787583
bool IsPartialSpecialization = false;

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5653,6 +5653,8 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
56535653
/*UpdateArgsWithConversions=*/false))
56545654
return ExprError();
56555655

5656+
DiagnoseUseOfDecl(NamedConcept, ConceptNameInfo.getLoc());
5657+
56565658
auto *CSD = ImplicitConceptSpecializationDecl::Create(
56575659
Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(),
56585660
CanonicalConverted);
@@ -9859,7 +9861,8 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
98599861

98609862
Decl *Sema::ActOnConceptDefinition(
98619863
Scope *S, MultiTemplateParamsArg TemplateParameterLists,
9862-
const IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr) {
9864+
const IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr,
9865+
const ParsedAttributesView &Attrs) {
98639866
DeclContext *DC = CurContext;
98649867

98659868
if (!DC->getRedeclContext()->isFileContext()) {
@@ -9921,6 +9924,9 @@ Decl *Sema::ActOnConceptDefinition(
99219924
ActOnDocumentableDecl(NewDecl);
99229925
if (AddToScope)
99239926
PushOnScopeChains(NewDecl, S);
9927+
9928+
ProcessDeclAttributeList(S, NewDecl, Attrs);
9929+
99249930
return NewDecl;
99259931
}
99269932

clang/lib/Sema/SemaType.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6392,6 +6392,11 @@ TypeResult Sema::ActOnTypeName(Declarator &D) {
63926392
CheckExtraCXXDefaultArguments(D);
63936393
}
63946394

6395+
if (const AutoType *AutoT = T->getAs<AutoType>())
6396+
CheckConstrainedAuto(
6397+
AutoT,
6398+
TInfo->getTypeLoc().getContainedAutoTypeLoc().getConceptNameLoc());
6399+
63956400
return CreateParsedType(T, TInfo);
63966401
}
63976402

clang/test/CXX/drs/cwg24xx.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,48 @@ void fallthrough(int n) {
4545
#endif
4646
}
4747

48+
namespace cwg2428 { // cwg2428: 19
49+
#if __cplusplus >= 202002L
50+
template <typename>
51+
concept C [[deprecated]] = true; // #cwg2428-C
52+
53+
template <typename>
54+
[[deprecated]] concept C2 = true;
55+
// expected-error@-1 {{expected unqualified-id}}
56+
57+
template <typename T>
58+
concept C3 = C<T>;
59+
// expected-warning@-1 {{'C' is deprecated}}
60+
// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}}
61+
62+
template <typename T, C U>
63+
// expected-warning@-1 {{'C' is deprecated}}
64+
// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}}
65+
requires C<T>
66+
// expected-warning@-1 {{'C' is deprecated}}
67+
// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}}
68+
void f() {
69+
bool b = C<int>;
70+
// expected-warning@-1 {{'C' is deprecated}}
71+
// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}}
72+
};
73+
74+
void g(C auto a) {};
75+
// expected-warning@-1 {{'C' is deprecated}}
76+
// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}}
77+
78+
template <typename T>
79+
auto h() -> C auto {
80+
// expected-warning@-1 {{'C' is deprecated}}
81+
// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}}
82+
C auto foo = T();
83+
// expected-warning@-1 {{'C' is deprecated}}
84+
// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}}
85+
return foo;
86+
}
87+
#endif
88+
} // namespace cwg2428
89+
4890
namespace cwg2430 { // cwg2430: 2.7
4991
struct S {
5092
S f(S s) { return s; }

clang/test/SemaCXX/cxx-deprecated.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
1+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
22

33
namespace [[deprecated]] {} // expected-warning {{'deprecated' attribute on anonymous namespace ignored}}
44

@@ -27,3 +27,13 @@ namespace M = N; // expected-warning {{'N' is deprecated}}
2727

2828
// Shouldn't diag:
2929
[[nodiscard, deprecated("")]] int PR37935();
30+
31+
namespace cxx20_concept {
32+
template <typename>
33+
concept C __attribute__((deprecated)) = true; // #C
34+
35+
template <C T>
36+
// expected-warning@-1 {{'C' is deprecated}}
37+
// expected-note@#C {{'C' has been explicitly marked deprecated here}}
38+
void f();
39+
} // namespace cxx20_concept

clang/www/cxx_dr_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14376,7 +14376,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
1437614376
<td><a href="https://cplusplus.github.io/CWG/issues/2428.html">2428</a></td>
1437714377
<td>C++23</td>
1437814378
<td>Deprecating a concept</td>
14379-
<td class="unknown" align="center">Unknown</td>
14379+
<td class="unreleased" align="center">Clang 19</td>
1438014380
</tr>
1438114381
<tr id="2429">
1438214382
<td><a href="https://cplusplus.github.io/CWG/issues/2429.html">2429</a></td>

0 commit comments

Comments
 (0)