diff options
author | Hubert Tong <hubert.reinterpretcast@gmail.com> | 2017-02-10 02:46:19 +0000 |
---|---|---|
committer | Hubert Tong <hubert.reinterpretcast@gmail.com> | 2017-02-10 02:46:19 +0000 |
commit | eac12edf439abe24e841b4da32ace117fde582b2 (patch) | |
tree | a94917a2c5e10e482c9e47aaf14e377f50162107 /lib | |
parent | 1ef9dbfbac798d6e09edda41da9ce95537dfdd4e (diff) |
[Concepts] Class template associated constraints
Summary:
This adds associated constraints as a property of class templates.
An error is produced if redeclarations are not similarly constrained.
Reviewers: rsmith, faisalv, aaron.ballman
Reviewed By: rsmith
Subscribers: cfe-commits, nwilson
Differential Revision: https://reviews.llvm.org/D25674
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@294697 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 53 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 1 |
3 files changed, 64 insertions, 4 deletions
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index a5fbb0a3ba..22f6e18d56 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -297,10 +297,18 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl) { + NamedDecl *Decl, + Expr *AssociatedConstraints) { AdoptTemplateParameterList(Params, cast<DeclContext>(Decl)); - ClassTemplateDecl *New = new (C, DC) ClassTemplateDecl(C, DC, L, Name, - Params, Decl); + + if (!AssociatedConstraints) { + return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl); + } + + ConstrainedTemplateDeclInfo *const CTDI = new (C) ConstrainedTemplateDeclInfo; + ClassTemplateDecl *const New = + new (C, DC) ClassTemplateDecl(CTDI, C, DC, L, Name, Params, Decl); + New->setAssociatedConstraints(AssociatedConstraints); return New; } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index d0ed17cc49..9d9d1270bf 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -45,6 +45,26 @@ clang::getTemplateParamsRange(TemplateParameterList const * const *Ps, return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc()); } +namespace clang { +/// \brief [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(); +} + /// \brief Determine whether the declaration found is acceptable as the name /// of a template and, if so, return that template declaration. Otherwise, /// returns NULL. @@ -1137,6 +1157,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, } } + // 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 @@ -1148,6 +1171,29 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, 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->getLocStart() : NameLoc, + diag::err_template_different_associated_constraints); + Diag(PrevAC ? PrevAC->getLocStart() : 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, @@ -1250,10 +1296,15 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, 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); + NewClass, ACtoAttach); if (ShouldAddRedecl) NewTemplate->setPreviousDecl(PrevClassTemplate); diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 5638cdfde5..6da820f09a 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1876,6 +1876,7 @@ DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { DeclID PatternID = ReadDeclID(); NamedDecl *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID)); TemplateParameterList *TemplateParams = Record.readTemplateParameterList(); + // FIXME handle associated constraints D->init(TemplatedDecl, TemplateParams); return PatternID; |