summaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorSaar Raz <saar@raz.email>2019-10-15 18:44:06 +0000
committerSaar Raz <saar@raz.email>2019-10-15 18:44:06 +0000
commitcf4a18c6aa180512c2f9b2a88450492b9c89c3c8 (patch)
treea8f878dad9ce11e042bd5a9388610e90425997f9 /lib/Sema
parentea4934045aa895f450dae600d12b7f5582915598 (diff)
downloadclang-cf4a18c6aa180512c2f9b2a88450492b9c89c3c8.tar.gz
[Concept] Associated Constraints Infrastructure
Add code to correctly calculate the associated constraints of a template (no enforcement yet). D41284 on Phabricator. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@374938 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaConcept.cpp2
-rw-r--r--lib/Sema/SemaTemplate.cpp92
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp15
3 files changed, 48 insertions, 61 deletions
diff --git a/lib/Sema/SemaConcept.cpp b/lib/Sema/SemaConcept.cpp
index 3131609390..848ccf5434 100644
--- a/lib/Sema/SemaConcept.cpp
+++ b/lib/Sema/SemaConcept.cpp
@@ -122,4 +122,4 @@ Sema::CalculateConstraintSatisfaction(ConceptDecl *NamedConcept,
IsSatisfied = EvalResult.Val.getInt().getBoolValue();
return false;
-}
+} \ No newline at end of file
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index cb756eb30f..2871511466 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -45,27 +45,7 @@ clang::getTemplateParamsRange(TemplateParameterList const * const *Ps,
return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc());
}
-namespace clang {
-/// [temp.constr.decl]p2: A template's associated constraints are
-/// defined as a single constraint-expression derived from the introduced
-/// constraint-expressions [ ... ].
-///
-/// \param Params The template parameter list and optional requires-clause.
-///
-/// \param FD The underlying templated function declaration for a function
-/// template.
-static Expr *formAssociatedConstraints(TemplateParameterList *Params,
- FunctionDecl *FD);
-}
-
-static Expr *clang::formAssociatedConstraints(TemplateParameterList *Params,
- FunctionDecl *FD) {
- // FIXME: Concepts: collect additional introduced constraint-expressions
- assert(!FD && "Cannot collect constraints from function declaration yet.");
- return Params->getRequiresClause();
-}
-
-/// Determine whether the declaration found is acceptable as the name
+/// \brief Determine whether the declaration found is acceptable as the name
/// of a template and, if so, return that template declaration. Otherwise,
/// returns null.
///
@@ -1533,9 +1513,6 @@ DeclResult Sema::CheckClassTemplate(
}
}
- // TODO Memory management; associated constraints are not always stored.
- Expr *const CurAC = formAssociatedConstraints(TemplateParams, nullptr);
-
if (PrevClassTemplate) {
// Ensure that the template parameter lists are compatible. Skip this check
// for a friend in a dependent context: the template parameter list itself
@@ -1547,30 +1524,6 @@ DeclResult Sema::CheckClassTemplate(
TPL_TemplateMatch))
return true;
- // Check for matching associated constraints on redeclarations.
- const Expr *const PrevAC = PrevClassTemplate->getAssociatedConstraints();
- const bool RedeclACMismatch = [&] {
- if (!(CurAC || PrevAC))
- return false; // Nothing to check; no mismatch.
- if (CurAC && PrevAC) {
- llvm::FoldingSetNodeID CurACInfo, PrevACInfo;
- CurAC->Profile(CurACInfo, Context, /*Canonical=*/true);
- PrevAC->Profile(PrevACInfo, Context, /*Canonical=*/true);
- if (CurACInfo == PrevACInfo)
- return false; // All good; no mismatch.
- }
- return true;
- }();
-
- if (RedeclACMismatch) {
- Diag(CurAC ? CurAC->getBeginLoc() : NameLoc,
- diag::err_template_different_associated_constraints);
- Diag(PrevAC ? PrevAC->getBeginLoc() : PrevClassTemplate->getLocation(),
- diag::note_template_prev_declaration)
- << /*declaration*/ 0;
- return true;
- }
-
// C++ [temp.class]p4:
// In a redeclaration, partial specialization, explicit
// specialization or explicit instantiation of a class template,
@@ -1674,15 +1627,10 @@ DeclResult Sema::CheckClassTemplate(
AddMsStructLayoutForRecord(NewClass);
}
- // Attach the associated constraints when the declaration will not be part of
- // a decl chain.
- Expr *const ACtoAttach =
- PrevClassTemplate && ShouldAddRedecl ? nullptr : CurAC;
-
ClassTemplateDecl *NewTemplate
= ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
DeclarationName(Name), TemplateParams,
- NewClass, ACtoAttach);
+ NewClass);
if (ShouldAddRedecl)
NewTemplate->setPreviousDecl(PrevClassTemplate);
@@ -7266,6 +7214,9 @@ static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
TemplateArgLoc);
}
+ // TODO: Concepts: Match immediately-introduced-constraint for type
+ // constraints
+
return true;
}
@@ -7291,6 +7242,15 @@ void DiagnoseTemplateParameterListArityMismatch(Sema &S,
<< SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
}
+static void
+DiagnoseTemplateParameterListRequiresClauseMismatch(Sema &S,
+ TemplateParameterList *New,
+ TemplateParameterList *Old){
+ S.Diag(New->getTemplateLoc(), diag::err_template_different_requires_clause);
+ S.Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration)
+ << /*declaration*/0;
+}
+
/// Determine whether the given template parameter lists are
/// equivalent.
///
@@ -7380,6 +7340,27 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
return false;
}
+ if (Kind != TPL_TemplateTemplateArgumentMatch) {
+ const Expr *NewRC = New->getRequiresClause();
+ const Expr *OldRC = Old->getRequiresClause();
+ if (!NewRC != !OldRC) {
+ if (Complain)
+ DiagnoseTemplateParameterListRequiresClauseMismatch(*this, New, Old);
+ return false;
+ }
+
+ if (NewRC) {
+ llvm::FoldingSetNodeID OldRCID, NewRCID;
+ OldRC->Profile(OldRCID, Context, /*Canonical=*/true);
+ NewRC->Profile(NewRCID, Context, /*Canonical=*/true);
+ if (OldRCID != NewRCID) {
+ if (Complain)
+ DiagnoseTemplateParameterListRequiresClauseMismatch(*this, New, Old);
+ return false;
+ }
+ }
+ }
+
return true;
}
@@ -8089,10 +8070,9 @@ Decl *Sema::ActOnConceptDefinition(Scope *S,
TemplateParameterLists.front(),
ConstraintExpr);
- if (NewDecl->getAssociatedConstraints()) {
+ if (NewDecl->hasAssociatedConstraints()) {
// C++2a [temp.concept]p4:
// A concept shall not have associated constraints.
- // TODO: Make a test once we have actual associated constraints.
Diag(NameLoc, diag::err_concept_no_associated_constraints);
NewDecl->setInvalidDecl();
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 818548cb62..d1ad304e62 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3515,14 +3515,21 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
if (Invalid)
return nullptr;
- // Note: we substitute into associated constraints later
- Expr *const UninstantiatedRequiresClause = L->getRequiresClause();
+ // FIXME: Concepts: Substitution into requires clause should only happen when
+ // checking satisfaction.
+ Expr *InstRequiresClause = nullptr;
+ if (Expr *E = L->getRequiresClause()) {
+ ExprResult Res = SemaRef.SubstExpr(E, TemplateArgs);
+ if (Res.isInvalid() || !Res.isUsable()) {
+ return nullptr;
+ }
+ InstRequiresClause = Res.get();
+ }
TemplateParameterList *InstL
= TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
L->getLAngleLoc(), Params,
- L->getRAngleLoc(),
- UninstantiatedRequiresClause);
+ L->getRAngleLoc(), InstRequiresClause);
return InstL;
}