-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Clang][Parser] Don't evaluate concept when its definition is invalid #111179
Conversation
@llvm/pr-subscribers-clang Author: Younan Zhang (zyn0217) ChangesSince #103867, the nullness of the concept declaration has been turned to represent a state in which the concept definition is being parsed and used for self-reference checking. However, that PR missed a case where such a definition could be invalid and thus, the definition should not be found. Otherwise, the assumption in the evaluation would fail. This PR fixes it by removing the definition from the DeclContext in such situations. Fixes #109780 Full diff: https://github.com/llvm/llvm-project/pull/111179.diff 4 Files Affected:
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
|
…e definition is invalid" This reverts commit fc3e60d.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…llvm#111179) Since llvm#103867, the nullness of the concept declaration has been turned to represent a state in which the concept definition is being parsed and used for self-reference checking. However, PR missed a case where such a definition could be invalid, and we shall inhibit making it into evaluation. Fixes llvm#109780
The ASTWriter currently assumes template type constraints to be initialized ((bool)getTypeConstraint() == hasTypeConstraint()). The attached test case presents a scenario where that doesn't apply, and is a regression test for issues llvm#99036 and llvm#109354. This patch removes the assumption and adds another boolean to the serialization, to explicitly encode whether the type constraint has been initialized. The same issue was incidentally fixed on the main branch by llvm#111179.
The ASTWriter currently assumes template type constraints to be initialized ((bool)getTypeConstraint() == hasTypeConstraint()). Issues llvm#99036 and llvm#109354 identified a scenario where this assertion is violated. This patch removes the assumption and adds another boolean to the serialization, to explicitly encode whether the type constraint has been initialized. The same issue was incidentally fixed on the main branch by llvm#111179. This solution avoids backporting llvm#111179 and its dependencies.
The ASTWriter currently assumes template type constraints to be initialized ((bool)getTypeConstraint() == hasTypeConstraint()). Issues llvm#99036 and llvm#109354 identified a scenario where this assertion is violated. This patch removes the assumption and adds another boolean to the serialization, to explicitly encode whether the type constraint has been initialized. The same issue was incidentally fixed on the main branch by llvm#111179. This solution avoids backporting llvm#111179 and its dependencies.
This crash looks linked to this change: #115004 |
This crash looks linked to this change: #121980 |
Since #103867, the nullness of the concept declaration has been turned to represent a state in which the concept definition is being parsed and used for self-reference checking.
However, PR missed a case where such a definition could be invalid, and we shall inhibit them from making it into evaluation.
Fixes #109780