diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rwxr-xr-x | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 84 |
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). /// |