@@ -1079,6 +1079,9 @@ bool Sema::CheckTypeConstraint(TemplateIdAnnotation *TypeConstr) {
1079
1079
return true ;
1080
1080
}
1081
1081
1082
+ if (CheckConceptUseInDefinition (CD, TypeConstr->TemplateNameLoc ))
1083
+ return true ;
1084
+
1082
1085
bool WereArgsSpecified = TypeConstr->LAngleLoc .isValid ();
1083
1086
1084
1087
if (!WereArgsSpecified &&
@@ -8447,10 +8450,9 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
8447
8450
return NewDecl;
8448
8451
}
8449
8452
8450
- Decl *Sema::ActOnConceptDefinition (
8453
+ ConceptDecl *Sema::ActOnStartConceptDefinition (
8451
8454
Scope *S, MultiTemplateParamsArg TemplateParameterLists,
8452
- const IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr,
8453
- const ParsedAttributesView &Attrs) {
8455
+ const IdentifierInfo *Name, SourceLocation NameLoc) {
8454
8456
DeclContext *DC = CurContext;
8455
8457
8456
8458
if (!DC->getRedeclContext ()->isFileContext ()) {
@@ -8486,11 +8488,8 @@ Decl *Sema::ActOnConceptDefinition(
8486
8488
}
8487
8489
}
8488
8490
8489
- if (DiagnoseUnexpandedParameterPack (ConstraintExpr))
8490
- return nullptr ;
8491
-
8492
8491
ConceptDecl *NewDecl =
8493
- ConceptDecl::Create (Context, DC, NameLoc, Name, Params, ConstraintExpr );
8492
+ ConceptDecl::Create (Context, DC, NameLoc, Name, Params);
8494
8493
8495
8494
if (NewDecl->hasAssociatedConstraints ()) {
8496
8495
// C++2a [temp.concept]p4:
@@ -8499,23 +8498,63 @@ Decl *Sema::ActOnConceptDefinition(
8499
8498
NewDecl->setInvalidDecl ();
8500
8499
}
8501
8500
8501
+ DeclarationNameInfo NameInfo (NewDecl->getDeclName (), NewDecl->getBeginLoc ());
8502
+ LookupResult Previous (*this , NameInfo, LookupOrdinaryName,
8503
+ forRedeclarationInCurContext ());
8504
+ LookupName (Previous, S);
8505
+ FilterLookupForScope (Previous, CurContext, S, /* ConsiderLinkage=*/ false ,
8506
+ /* AllowInlineNamespace*/ false );
8507
+
8508
+ // We cannot properly handle redeclarations until we parse the constraint
8509
+ // expression, so only inject the name if we are sure we are not redeclaring a
8510
+ // symbol
8511
+ if (Previous.empty ())
8512
+ PushOnScopeChains (NewDecl, S, true );
8513
+
8514
+ return NewDecl;
8515
+ }
8516
+
8517
+ static bool RemoveLookupResult (LookupResult &R, NamedDecl *C) {
8518
+ bool Found = false ;
8519
+ LookupResult::Filter F = R.makeFilter ();
8520
+ while (F.hasNext ()) {
8521
+ NamedDecl *D = F.next ();
8522
+ if (D == C) {
8523
+ F.erase ();
8524
+ Found = true ;
8525
+ break ;
8526
+ }
8527
+ }
8528
+ F.done ();
8529
+ return Found;
8530
+ }
8531
+
8532
+ ConceptDecl *
8533
+ Sema::ActOnFinishConceptDefinition (Scope *S, ConceptDecl *C,
8534
+ Expr *ConstraintExpr,
8535
+ const ParsedAttributesView &Attrs) {
8536
+ assert (!C->hasDefinition () && " Concept already defined" );
8537
+ if (DiagnoseUnexpandedParameterPack (ConstraintExpr))
8538
+ return nullptr ;
8539
+ C->setDefinition (ConstraintExpr);
8540
+ ProcessDeclAttributeList (S, C, Attrs);
8541
+
8502
8542
// Check for conflicting previous declaration.
8503
- DeclarationNameInfo NameInfo (NewDecl ->getDeclName (), NameLoc );
8543
+ DeclarationNameInfo NameInfo (C ->getDeclName (), C-> getBeginLoc () );
8504
8544
LookupResult Previous (*this , NameInfo, LookupOrdinaryName,
8505
8545
forRedeclarationInCurContext ());
8506
8546
LookupName (Previous, S);
8507
- FilterLookupForScope (Previous, DC, S, /* ConsiderLinkage=*/ false ,
8508
- /* AllowInlineNamespace*/ false );
8547
+ FilterLookupForScope (Previous, CurContext, S, /* ConsiderLinkage=*/ false ,
8548
+ /* AllowInlineNamespace*/ false );
8549
+ bool WasAlreadyAdded = RemoveLookupResult (Previous, C);
8509
8550
bool AddToScope = true ;
8510
- CheckConceptRedefinition (NewDecl , Previous, AddToScope);
8551
+ CheckConceptRedefinition (C , Previous, AddToScope);
8511
8552
8512
- ActOnDocumentableDecl (NewDecl);
8513
- if (AddToScope)
8514
- PushOnScopeChains (NewDecl, S);
8515
-
8516
- ProcessDeclAttributeList (S, NewDecl, Attrs);
8553
+ ActOnDocumentableDecl (C);
8554
+ if (!WasAlreadyAdded && AddToScope)
8555
+ PushOnScopeChains (C, S);
8517
8556
8518
- return NewDecl ;
8557
+ return C ;
8519
8558
}
8520
8559
8521
8560
void Sema::CheckConceptRedefinition (ConceptDecl *NewDecl,
@@ -8560,6 +8599,16 @@ void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl,
8560
8599
Context.setPrimaryMergedDecl (NewDecl, OldConcept->getCanonicalDecl ());
8561
8600
}
8562
8601
8602
+ bool Sema::CheckConceptUseInDefinition (ConceptDecl *Concept,
8603
+ SourceLocation Loc) {
8604
+ if (!Concept->isInvalidDecl () && !Concept->hasDefinition ()) {
8605
+ Diag (Loc, diag::err_recursive_concept) << Concept;
8606
+ Diag (Concept->getLocation (), diag::note_declared_at);
8607
+ return true ;
8608
+ }
8609
+ return false ;
8610
+ }
8611
+
8563
8612
// / \brief Strips various properties off an implicit instantiation
8564
8613
// / that has just been explicitly specialized.
8565
8614
static void StripImplicitInstantiation (NamedDecl *D, bool MinGW) {
0 commit comments