Skip to content

Commit

Permalink
[Clang][Parser] Remove the concept from the DeclContext if the defini…
Browse files Browse the repository at this point in the history
…tion is invalid
  • Loading branch information
zyn0217 committed Oct 4, 2024
1 parent b837c9e commit fc3e60d
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 4 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 9 additions & 1 deletion clang/lib/Parse/ParseTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down Expand Up @@ -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;
}
Expand Down
14 changes: 14 additions & 0 deletions clang/test/SemaTemplate/concepts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit fc3e60d

Please sign in to comment.