summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rwxr-xr-xclang/lib/Sema/SemaTemplateInstantiateDecl.cpp84
1 files changed, 79 insertions, 5 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 98e05f09919..ce94c036eb1 100755
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1845,6 +1845,18 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
return nullptr;
}
+ // FIXME: Concepts: Do not substitute into constraint expressions
+ Expr *TrailingRequiresClause = D->getTrailingRequiresClause();
+ if (TrailingRequiresClause) {
+ ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause,
+ TemplateArgs);
+ if (SubstRC.isInvalid())
+ return nullptr;
+ TrailingRequiresClause = SubstRC.get();
+ if (!SemaRef.CheckConstraintExpression(TrailingRequiresClause))
+ return nullptr;
+ }
+
// If we're instantiating a local function declaration, put the result
// in the enclosing namespace; otherwise we need to find the instantiated
// context.
@@ -1881,7 +1893,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
Function = FunctionDecl::Create(
SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo,
D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(),
- D->hasWrittenPrototype(), D->getConstexprKind());
+ D->hasWrittenPrototype(), D->getConstexprKind(),
+ TrailingRequiresClause);
Function->setRangeEnd(D->getSourceRange().getEnd());
}
@@ -1908,6 +1921,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
Params[P]->setOwningFunction(Function);
Function->setParams(Params);
+ if (TrailingRequiresClause)
+ Function->setTrailingRequiresClause(TrailingRequiresClause);
+
if (TemplateParams) {
// Our resulting instantiation is actually a function template, since we
// are substituting only the outer template parameters. For example, given
@@ -2167,6 +2183,18 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
return nullptr;
}
+ // FIXME: Concepts: Do not substitute into constraint expressions
+ Expr *TrailingRequiresClause = D->getTrailingRequiresClause();
+ if (TrailingRequiresClause) {
+ ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause,
+ TemplateArgs);
+ if (SubstRC.isInvalid())
+ return nullptr;
+ TrailingRequiresClause = SubstRC.get();
+ if (!SemaRef.CheckConstraintExpression(TrailingRequiresClause))
+ return nullptr;
+ }
+
DeclContext *DC = Owner;
if (isFriend) {
if (QualifierLoc) {
@@ -2199,23 +2227,27 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
Method = CXXConstructorDecl::Create(
SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo,
InstantiatedExplicitSpecifier, Constructor->isInlineSpecified(), false,
- Constructor->getConstexprKind());
+ Constructor->getConstexprKind(), InheritedConstructor(),
+ TrailingRequiresClause);
Method->setRangeEnd(Constructor->getEndLoc());
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
Method = CXXDestructorDecl::Create(
SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo,
- Destructor->isInlineSpecified(), false, Destructor->getConstexprKind());
+ Destructor->isInlineSpecified(), false, Destructor->getConstexprKind(),
+ TrailingRequiresClause);
Method->setRangeEnd(Destructor->getEndLoc());
} else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
Method = CXXConversionDecl::Create(
SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo,
Conversion->isInlineSpecified(), InstantiatedExplicitSpecifier,
- Conversion->getConstexprKind(), Conversion->getEndLoc());
+ Conversion->getConstexprKind(), Conversion->getEndLoc(),
+ TrailingRequiresClause);
} else {
StorageClass SC = D->isStatic() ? SC_Static : SC_None;
Method = CXXMethodDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo,
T, TInfo, SC, D->isInlineSpecified(),
- D->getConstexprKind(), D->getEndLoc());
+ D->getConstexprKind(), D->getEndLoc(),
+ TrailingRequiresClause);
}
if (D->isInlined())
@@ -4117,6 +4149,48 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
TemplateArgs);
}
+bool Sema::CheckInstantiatedFunctionTemplateConstraints(
+ SourceLocation PointOfInstantiation, FunctionDecl *Decl,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ ConstraintSatisfaction &Satisfaction) {
+ // In most cases we're not going to have constraints, so check for that first.
+ FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
+ // Note - code synthesis context for the constraints check is created
+ // inside CheckConstraintsSatisfaction.
+ SmallVector<const Expr *, 3> TemplateAC;
+ Template->getAssociatedConstraints(TemplateAC);
+ if (TemplateAC.empty()) {
+ Satisfaction.IsSatisfied = true;
+ return false;
+ }
+
+ // Enter the scope of this instantiation. We don't use
+ // PushDeclContext because we don't have a scope.
+ Sema::ContextRAII savedContext(*this, Decl);
+ LocalInstantiationScope Scope(*this);
+
+ MultiLevelTemplateArgumentList MLTAL =
+ getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true);
+
+ // If this is not an explicit specialization - we need to get the instantiated
+ // version of the template arguments and add them to scope for the
+ // substitution.
+ if (Decl->isTemplateInstantiation()) {
+ InstantiatingTemplate Inst(*this, Decl->getPointOfInstantiation(),
+ InstantiatingTemplate::ConstraintsCheck{}, Decl->getPrimaryTemplate(),
+ MLTAL.getInnermost(), SourceRange());
+ if (Inst.isInvalid())
+ return true;
+ if (addInstantiatedParametersToScope(*this, Decl,
+ Decl->getTemplateInstantiationPattern(),
+ Scope, MLTAL))
+ return true;
+ }
+
+ return CheckConstraintSatisfaction(Template, TemplateAC, TemplateArgs,
+ PointOfInstantiation, Satisfaction);
+}
+
/// Initializes the common fields of an instantiation function
/// declaration (New) from the corresponding fields of its template (Tmpl).
///
OpenPOWER on IntegriCloud