[Concepts] Type Constraints
Add support for type-constraints in template type parameters.
Also add support for template type parameters as pack expansions (where the type constraint can now contain an unexpanded parameter pack).
Differential Revision: https://reviews.llvm.org/D44352
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 3bcc9ad..96a7d5a 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2313,7 +2313,20 @@
D->setDeclaredWithTypename(Record.readInt());
- // TODO: Concepts: Immediately introduced constraint
+ if (Record.readInt()) {
+ NestedNameSpecifierLoc NNS = Record.readNestedNameSpecifierLoc();
+ DeclarationNameInfo DN = Record.readDeclarationNameInfo();
+ ConceptDecl *NamedConcept = cast<ConceptDecl>(Record.readDecl());
+ const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
+ if (Record.readInt())
+ ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
+ Expr *ImmediatelyDeclaredConstraint = Record.readExpr();
+ D->setTypeConstraint(NNS, DN, /*FoundDecl=*/nullptr, NamedConcept,
+ ArgsAsWritten, ImmediatelyDeclaredConstraint);
+ if ((D->ExpandedParameterPack = Record.readInt()))
+ D->NumExpanded = Record.readInt();
+ }
+
if (Record.readInt())
D->setDefaultArgument(readTypeSourceInfo());
}
@@ -3800,9 +3813,12 @@
case DECL_FUNCTION_TEMPLATE:
D = FunctionTemplateDecl::CreateDeserialized(Context, ID);
break;
- case DECL_TEMPLATE_TYPE_PARM:
- D = TemplateTypeParmDecl::CreateDeserialized(Context, ID);
+ case DECL_TEMPLATE_TYPE_PARM: {
+ bool HasTypeConstraint = Record.readInt();
+ D = TemplateTypeParmDecl::CreateDeserialized(Context, ID,
+ HasTypeConstraint);
break;
+ }
case DECL_NON_TYPE_TEMPLATE_PARM:
D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID);
break;
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 5335021..f558c26 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -730,15 +730,13 @@
unsigned NumTemplateArgs = Record.readInt();
E->NestedNameSpec = Record.readNestedNameSpecifierLoc();
E->TemplateKWLoc = Record.readSourceLocation();
- E->ConceptNameLoc = Record.readSourceLocation();
- E->FoundDecl = readDeclAs<NamedDecl>();
+ E->ConceptName = Record.readDeclarationNameInfo();
E->NamedConcept = readDeclAs<ConceptDecl>();
- const ASTTemplateArgumentListInfo *ArgsAsWritten =
- Record.readASTTemplateArgumentListInfo();
+ E->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
llvm::SmallVector<TemplateArgument, 4> Args;
for (unsigned I = 0; I < NumTemplateArgs; ++I)
Args.push_back(Record.readTemplateArgument());
- E->setTemplateArguments(ArgsAsWritten, Args);
+ E->setTemplateArguments(Args);
ConstraintSatisfaction Satisfaction;
Satisfaction.IsSatisfied = Record.readInt();
if (!Satisfaction.IsSatisfied) {
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 6b8a9d9..b2a8c11 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1637,10 +1637,26 @@
}
void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ Record.push_back(D->hasTypeConstraint());
VisitTypeDecl(D);
Record.push_back(D->wasDeclaredWithTypename());
- // TODO: Concepts - constrained parameters.
+
+ const TypeConstraint *TC = D->getTypeConstraint();
+ Record.push_back(TC != nullptr);
+ if (TC) {
+ Record.AddNestedNameSpecifierLoc(TC->getNestedNameSpecifierLoc());
+ Record.AddDeclarationNameInfo(TC->getConceptNameInfo());
+ Record.AddDeclRef(TC->getNamedConcept());
+ Record.push_back(TC->getTemplateArgsAsWritten() != nullptr);
+ if (TC->getTemplateArgsAsWritten())
+ Record.AddASTTemplateArgumentListInfo(TC->getTemplateArgsAsWritten());
+ Record.AddStmt(TC->getImmediatelyDeclaredConstraint());
+ Record.push_back(D->isExpandedParameterPack());
+ if (D->isExpandedParameterPack())
+ Record.push_back(D->getNumExpansionParameters());
+ }
+
bool OwnsDefaultArg = D->hasDefaultArgument() &&
!D->defaultArgumentWasInherited();
Record.push_back(OwnsDefaultArg);
@@ -1670,7 +1686,6 @@
Code = serialization::DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK;
} else {
- // TODO: Concepts - constrained parameters.
// Rest of NonTypeTemplateParmDecl.
Record.push_back(D->isParameterPack());
bool OwnsDefaultArg = D->hasDefaultArgument() &&
@@ -1700,7 +1715,6 @@
Record.AddTemplateParameterList(D->getExpansionTemplateParameters(I));
Code = serialization::DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK;
} else {
- // TODO: Concepts - constrained parameters.
// Rest of TemplateTemplateParmDecl.
Record.push_back(D->isParameterPack());
bool OwnsDefaultArg = D->hasDefaultArgument() &&
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index e671c78..9231f3b 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -395,8 +395,7 @@
Record.push_back(TemplateArgs.size());
Record.AddNestedNameSpecifierLoc(E->getNestedNameSpecifierLoc());
Record.AddSourceLocation(E->getTemplateKWLoc());
- Record.AddSourceLocation(E->getConceptNameLoc());
- Record.AddDeclRef(E->getFoundDecl());
+ Record.AddDeclarationNameInfo(E->getConceptNameInfo());
Record.AddDeclRef(E->getNamedConcept());
Record.AddASTTemplateArgumentListInfo(E->getTemplateArgsAsWritten());
for (const TemplateArgument &Arg : TemplateArgs)