[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).
This commit is contained in:
parent
0ad275c158
commit
a68d20e986
@ -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.
|
||||
|
||||
|
@ -2022,6 +2022,8 @@ public:
|
||||
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 @@ public:
|
||||
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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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
|
||||
|
@ -14376,7 +14376,7 @@ and <I>POD class</I></td>
|
||||
<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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user