https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/111179
>From fc3e60d2c1d038ae3f3ef2e4ec3e86605cfb0f69 Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Fri, 4 Oct 2024 23:42:30 +0800 Subject: [PATCH 1/3] [Clang][Parser] Remove the concept from the DeclContext if the definition is invalid --- clang/include/clang/Sema/Sema.h | 2 +- clang/lib/Parse/ParseTemplate.cpp | 10 +++++++++- clang/lib/Sema/SemaTemplate.cpp | 6 ++++-- clang/test/SemaTemplate/concepts.cpp | 14 ++++++++++++++ 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index bede971ce0191b..eea3cf4e43cde8 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11995,7 +11995,7 @@ class Sema final : public SemaBase { ConceptDecl *ActOnStartConceptDefinition( Scope *S, MultiTemplateParamsArg TemplateParameterLists, - const IdentifierInfo *Name, SourceLocation NameLoc); + const IdentifierInfo *Name, SourceLocation NameLoc, bool &AddedToScope); ConceptDecl *ActOnFinishConceptDefinition(Scope *S, ConceptDecl *C, Expr *ConstraintExpr, diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index de29652abbfd95..9ddabdf5172e41 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -322,13 +322,19 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo, // [C++26][basic.scope.pdecl]/p13 // The locus of a concept-definition is immediately after its concept-name. + bool AddedToScope = false; ConceptDecl *D = Actions.ActOnStartConceptDefinition( - getCurScope(), *TemplateInfo.TemplateParams, Id, IdLoc); + getCurScope(), *TemplateInfo.TemplateParams, Id, IdLoc, AddedToScope); ParsedAttributes Attrs(AttrFactory); MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs); if (!TryConsumeToken(tok::equal)) { + // The expression is unset until ActOnFinishConceptDefinition(), so remove + // the invalid declaration from the future lookup such that the evaluation + // wouldn't have to handle empty expressions. + if (AddedToScope) + Actions.CurContext->removeDecl(D); Diag(Tok.getLocation(), diag::err_expected) << tok::equal; SkipUntil(tok::semi); return nullptr; @@ -337,6 +343,8 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo, ExprResult ConstraintExprResult = Actions.CorrectDelayedTyposInExpr(ParseConstraintExpression()); if (ConstraintExprResult.isInvalid()) { + if (AddedToScope) + Actions.CurContext->removeDecl(D); SkipUntil(tok::semi); return nullptr; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index eeaa1ebd7ba83a..2d8b47ea2474be 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8632,7 +8632,7 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S, ConceptDecl *Sema::ActOnStartConceptDefinition( Scope *S, MultiTemplateParamsArg TemplateParameterLists, - const IdentifierInfo *Name, SourceLocation NameLoc) { + const IdentifierInfo *Name, SourceLocation NameLoc, bool &AddedToScope) { DeclContext *DC = CurContext; if (!DC->getRedeclContext()->isFileContext()) { @@ -8688,8 +8688,10 @@ ConceptDecl *Sema::ActOnStartConceptDefinition( // We cannot properly handle redeclarations until we parse the constraint // expression, so only inject the name if we are sure we are not redeclaring a // symbol - if (Previous.empty()) + if (Previous.empty()) { PushOnScopeChains(NewDecl, S, true); + AddedToScope = true; + } return NewDecl; } diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index a98ca3939222bd..9d29cc59d3ab96 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1151,3 +1151,17 @@ int test() { } } + +namespace GH109780 { + +template <typename T> +concept Concept; // expected-error {{expected '='}} + +bool val = Concept<int>; // expected-error {{use of undeclared identifier 'Concept'}} + +template <typename T> +concept C = invalid; // expected-error {{use of undeclared identifier 'invalid'}} + +bool val2 = C<int>; // expected-error {{use of undeclared identifier 'C'}} + +} // namespace GH109780 >From 3c2edaf8be00adf87808b24d1d1e66adbada446b Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Mon, 7 Oct 2024 20:42:12 +0800 Subject: [PATCH 2/3] Revert "[Clang][Parser] Remove the concept from the DeclContext if the definition is invalid" This reverts commit fc3e60d2c1d038ae3f3ef2e4ec3e86605cfb0f69. --- clang/include/clang/Sema/Sema.h | 2 +- clang/lib/Parse/ParseTemplate.cpp | 10 +--------- clang/lib/Sema/SemaTemplate.cpp | 6 ++---- clang/test/SemaTemplate/concepts.cpp | 14 -------------- 4 files changed, 4 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index eea3cf4e43cde8..bede971ce0191b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11995,7 +11995,7 @@ class Sema final : public SemaBase { ConceptDecl *ActOnStartConceptDefinition( Scope *S, MultiTemplateParamsArg TemplateParameterLists, - const IdentifierInfo *Name, SourceLocation NameLoc, bool &AddedToScope); + const IdentifierInfo *Name, SourceLocation NameLoc); ConceptDecl *ActOnFinishConceptDefinition(Scope *S, ConceptDecl *C, Expr *ConstraintExpr, diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 9ddabdf5172e41..de29652abbfd95 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -322,19 +322,13 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo, // [C++26][basic.scope.pdecl]/p13 // The locus of a concept-definition is immediately after its concept-name. - bool AddedToScope = false; ConceptDecl *D = Actions.ActOnStartConceptDefinition( - getCurScope(), *TemplateInfo.TemplateParams, Id, IdLoc, AddedToScope); + getCurScope(), *TemplateInfo.TemplateParams, Id, IdLoc); ParsedAttributes Attrs(AttrFactory); MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs); if (!TryConsumeToken(tok::equal)) { - // The expression is unset until ActOnFinishConceptDefinition(), so remove - // the invalid declaration from the future lookup such that the evaluation - // wouldn't have to handle empty expressions. - if (AddedToScope) - Actions.CurContext->removeDecl(D); Diag(Tok.getLocation(), diag::err_expected) << tok::equal; SkipUntil(tok::semi); return nullptr; @@ -343,8 +337,6 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo, ExprResult ConstraintExprResult = Actions.CorrectDelayedTyposInExpr(ParseConstraintExpression()); if (ConstraintExprResult.isInvalid()) { - if (AddedToScope) - Actions.CurContext->removeDecl(D); SkipUntil(tok::semi); return nullptr; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 2d8b47ea2474be..eeaa1ebd7ba83a 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8632,7 +8632,7 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S, ConceptDecl *Sema::ActOnStartConceptDefinition( Scope *S, MultiTemplateParamsArg TemplateParameterLists, - const IdentifierInfo *Name, SourceLocation NameLoc, bool &AddedToScope) { + const IdentifierInfo *Name, SourceLocation NameLoc) { DeclContext *DC = CurContext; if (!DC->getRedeclContext()->isFileContext()) { @@ -8688,10 +8688,8 @@ ConceptDecl *Sema::ActOnStartConceptDefinition( // We cannot properly handle redeclarations until we parse the constraint // expression, so only inject the name if we are sure we are not redeclaring a // symbol - if (Previous.empty()) { + if (Previous.empty()) PushOnScopeChains(NewDecl, S, true); - AddedToScope = true; - } return NewDecl; } diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index 9d29cc59d3ab96..a98ca3939222bd 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1151,17 +1151,3 @@ int test() { } } - -namespace GH109780 { - -template <typename T> -concept Concept; // expected-error {{expected '='}} - -bool val = Concept<int>; // expected-error {{use of undeclared identifier 'Concept'}} - -template <typename T> -concept C = invalid; // expected-error {{use of undeclared identifier 'invalid'}} - -bool val2 = C<int>; // expected-error {{use of undeclared identifier 'C'}} - -} // namespace GH109780 >From 3db6376f7fa9f42ad8e2f2fc164c473eda13f382 Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Mon, 7 Oct 2024 20:46:49 +0800 Subject: [PATCH 3/3] Invalidate declarations --- clang/lib/Parse/ParseTemplate.cpp | 4 ++++ clang/test/SemaTemplate/concepts.cpp | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index de29652abbfd95..0953cfc3c017ef 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -331,6 +331,8 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo, if (!TryConsumeToken(tok::equal)) { Diag(Tok.getLocation(), diag::err_expected) << tok::equal; SkipUntil(tok::semi); + if (D) + D->setInvalidDecl(); return nullptr; } @@ -338,6 +340,8 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo, Actions.CorrectDelayedTyposInExpr(ParseConstraintExpression()); if (ConstraintExprResult.isInvalid()) { SkipUntil(tok::semi); + if (D) + D->setInvalidDecl(); return nullptr; } diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index a98ca3939222bd..312469313fc535 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1151,3 +1151,17 @@ int test() { } } + +namespace GH109780 { + +template <typename T> +concept Concept; // expected-error {{expected '='}} + +bool val = Concept<int>; + +template <typename T> +concept C = invalid; // expected-error {{use of undeclared identifier 'invalid'}} + +bool val2 = C<int>; + +} // namespace GH109780 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits