diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -237,6 +237,9 @@ for (const auto &TP : *TPL) Visit(TP); + + if (const Expr *RC = TPL->getRequiresClause()) + Visit(RC); } void diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -168,6 +168,16 @@ return HasRequiresClause ? *getTrailingObjects() : nullptr; } + /// \brief All associated constraints derived from this template parameter + /// list, including the requires clause and any constraints derived from + /// constrained-parameters. + /// + /// The constraints in the resulting list are to be treated as if in a + /// conjunction ("and"). + void getAssociatedConstraints(llvm::SmallVectorImpl &AC) const; + + bool hasAssociatedConstraints() const; + SourceLocation getTemplateLoc() const { return TemplateLoc; } SourceLocation getLAngleLoc() const { return LAngleLoc; } SourceLocation getRAngleLoc() const { return RAngleLoc; } @@ -369,33 +379,7 @@ // Kinds of Templates //===----------------------------------------------------------------------===// -/// Stores the template parameter list and associated constraints for -/// \c TemplateDecl objects that track associated constraints. -class ConstrainedTemplateDeclInfo { - friend TemplateDecl; - -public: - ConstrainedTemplateDeclInfo() = default; - - TemplateParameterList *getTemplateParameters() const { - return TemplateParams; - } - - Expr *getAssociatedConstraints() const { return AssociatedConstraints; } - -protected: - void setTemplateParameters(TemplateParameterList *TParams) { - TemplateParams = TParams; - } - - void setAssociatedConstraints(Expr *AC) { AssociatedConstraints = AC; } - - TemplateParameterList *TemplateParams = nullptr; - Expr *AssociatedConstraints = nullptr; -}; - - -/// The base class of all kinds of template declarations (e.g., +/// \brief The base class of all kinds of template declarations (e.g., /// class, function, etc.). /// /// The TemplateDecl class stores the list of template parameters and a @@ -404,54 +388,32 @@ void anchor() override; protected: + // Construct a template decl with name, parameters, and templated element. + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl); + // Construct a template decl with the given name and parameters. // Used when there is no templated element (e.g., for tt-params). - TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC, - SourceLocation L, DeclarationName Name, - TemplateParameterList *Params) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr), - TemplateParams(CTDI) { - this->setTemplateParameters(Params); - } - TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params) - : TemplateDecl(nullptr, DK, DC, L, Name, Params) {} - - // Construct a template decl with name, parameters, and templated element. - TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC, - SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), - TemplateParams(CTDI) { - this->setTemplateParameters(Params); - } - - TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(nullptr, DK, DC, L, Name, Params, Decl) {} + : TemplateDecl(DK, DC, L, Name, Params, nullptr) {} public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { - const auto *const CTDI = - TemplateParams.dyn_cast(); - return CTDI ? CTDI->getTemplateParameters() - : TemplateParams.get(); + return TemplateParams; } - /// Get the constraint-expression from the associated requires-clause (if any) - const Expr *getRequiresClause() const { - const TemplateParameterList *const TP = getTemplateParameters(); - return TP ? TP->getRequiresClause() : nullptr; - } + /// \brief Get the total constraint-expression associated with this template, + /// including constraint-expressions derived from the requires-clause, + /// trailing requires-clause (for functions and methods) and constrained + /// template parameters. + void getAssociatedConstraints(llvm::SmallVectorImpl &AC) const; - Expr *getAssociatedConstraints() const { - const auto *const C = cast(getCanonicalDecl()); - const auto *const CTDI = - C->TemplateParams.dyn_cast(); - return CTDI ? CTDI->getAssociatedConstraints() : nullptr; - } + bool hasAssociatedConstraints() const; /// Get the underlying, templated declaration. NamedDecl *getTemplatedDecl() const { return TemplatedDecl; } @@ -470,29 +432,10 @@ protected: NamedDecl *TemplatedDecl; - - /// The template parameter list and optional requires-clause - /// associated with this declaration; alternatively, a - /// \c ConstrainedTemplateDeclInfo if the associated constraints of the - /// template are being tracked by this particular declaration. - llvm::PointerUnion - TemplateParams; + TemplateParameterList *TemplateParams; void setTemplateParameters(TemplateParameterList *TParams) { - if (auto *const CTDI = - TemplateParams.dyn_cast()) { - CTDI->setTemplateParameters(TParams); - } else { - TemplateParams = TParams; - } - } - - void setAssociatedConstraints(Expr *AC) { - assert(isCanonicalDecl() && - "Attaching associated constraints to non-canonical Decl"); - TemplateParams.get() - ->setAssociatedConstraints(AC); + TemplateParams = TParams; } public: @@ -889,17 +832,10 @@ virtual CommonBase *newCommon(ASTContext &C) const = 0; // Construct a template decl with name, parameters, and templated element. - RedeclarableTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, - ASTContext &C, DeclContext *DC, SourceLocation L, - DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl) - : TemplateDecl(CTDI, DK, DC, L, Name, Params, Decl), redeclarable_base(C) - {} - RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : RedeclarableTemplateDecl(nullptr, DK, C, DC, L, Name, Params, Decl) {} + : TemplateDecl(DK, DC, L, Name, Params, Decl), redeclarable_base(C) {} public: friend class ASTDeclReader; @@ -2026,6 +1962,20 @@ return TemplateParams; } + /// \brief All associated constraints of this partial specialization, + /// including the requires clause and any constraints derived from + /// constrained-parameters. + /// + /// The constraints in the resulting list are to be treated as if in a + /// conjunction ("and"). + void getAssociatedConstraints(llvm::SmallVectorImpl &AC) const { + TemplateParams->getAssociatedConstraints(AC); + } + + bool hasAssociatedConstraints() const { + return TemplateParams->hasAssociatedConstraints(); + } + /// Get the template arguments as written. const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { return ArgsAsWritten; @@ -2145,16 +2095,10 @@ llvm::FoldingSetVector & getPartialSpecializations(); - ClassTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, ASTContext &C, - DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : RedeclarableTemplateDecl(CTDI, ClassTemplate, C, DC, L, Name, Params, - Decl) {} - ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : ClassTemplateDecl(nullptr, C, DC, L, Name, Params, Decl) {} + : RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {} CommonBase *newCommon(ASTContext &C) const override; @@ -2180,14 +2124,12 @@ return getTemplatedDecl()->isThisDeclarationADefinition(); } - // FIXME: remove default argument for AssociatedConstraints - /// Create a class template node. + /// \brief Create a class template node. static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl, - Expr *AssociatedConstraints = nullptr); + NamedDecl *Decl); /// Create an empty class template node. static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2866,7 +2808,21 @@ return ArgsAsWritten; } - /// Retrieve the member variable template partial specialization from + /// \brief All associated constraints of this partial specialization, + /// including the requires clause and any constraints derived from + /// constrained-parameters. + /// + /// The constraints in the resulting list are to be treated as if in a + /// conjunction ("and"). + void getAssociatedConstraints(llvm::SmallVectorImpl &AC) const { + TemplateParams->getAssociatedConstraints(AC); + } + + bool hasAssociatedConstraints() const { + return TemplateParams->hasAssociatedConstraints(); + } + + /// \brief Retrieve the member variable template partial specialization from /// which this particular variable template partial specialization was /// instantiated. /// @@ -3095,11 +3051,9 @@ protected: Expr *ConstraintExpr; - ConceptDecl(DeclContext *DC, - SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, - Expr *ConstraintExpr) - : TemplateDecl(nullptr, Concept, DC, L, Name, Params), + ConceptDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, Expr *ConstraintExpr) + : TemplateDecl(Concept, DC, L, Name, Params), ConstraintExpr(ConstraintExpr) {}; public: static ConceptDecl *Create(ASTContext &C, DeclContext *DC, diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1631,9 +1631,11 @@ bool RecursiveASTVisitor::TraverseTemplateParameterListHelper( TemplateParameterList *TPL) { if (TPL) { - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); + for (NamedDecl *D : *TPL) { + TRY_TO(TraverseDecl(D)); + } + if (Expr *RequiresClause = TPL->getRequiresClause()) { + TRY_TO(TraverseStmt(RequiresClause)); } } return true; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2489,8 +2489,8 @@ def err_non_bool_atomic_constraint : Error< "atomic constraint must be of type 'bool' (found %0)">; -def err_template_different_associated_constraints : Error< - "associated constraints differ in template redeclaration">; +def err_template_different_requires_clause : Error< + "requires clause differs in template redeclaration">; // C++11 char16_t/char32_t def warn_cxx98_compat_unicode_type : Warning< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5945,7 +5945,13 @@ Expr *ConstraintExpr, bool &IsSatisfied); - // ParseObjCStringLiteral - Parse Objective-C string literals. + /// Check that the associated constraints of a template declaration match the + /// associated constraints of an older declaration of which it is a + /// redeclaration + bool CheckRedeclarationConstraintMatch(TemplateParameterList *Old, + TemplateParameterList *New); + + // ParseObjCStringLiteral - Parse Objective-C string literals. ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, ArrayRef Strings); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -691,7 +691,7 @@ cast(*P))); } - assert(!TTP->getRequiresClause() && + assert(!TTP->getTemplateParameters()->getRequiresClause() && "Unexpected requires-clause on template template-parameter"); Expr *const CanonRequiresClause = nullptr; diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -70,6 +70,8 @@ } if (RequiresClause) { *getTrailingObjects() = RequiresClause; + if (RequiresClause->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; } } @@ -136,6 +138,18 @@ } } +void TemplateParameterList:: +getAssociatedConstraints(llvm::SmallVectorImpl &AC) const { + // TODO: Concepts: Collect immediately-introduced constraints. + if (HasRequiresClause) + AC.push_back(getRequiresClause()); +} + +bool TemplateParameterList::hasAssociatedConstraints() const { + // TODO: Concepts: Regard immediately-introduced constraints. + return HasRequiresClause; +} + namespace clang { void *allocateDefaultArgStorageChain(const ASTContext &C) { @@ -144,6 +158,28 @@ } // namespace clang +//===----------------------------------------------------------------------===// +// TemplateDecl Implementation +//===----------------------------------------------------------------------===// + +TemplateDecl::TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), TemplateParams(Params) {} + +void TemplateDecl::anchor() {} + +void TemplateDecl:: +getAssociatedConstraints(llvm::SmallVectorImpl &AC) const { + // TODO: Concepts: Append function trailing requires clause. + TemplateParams->getAssociatedConstraints(AC); +} + +bool TemplateDecl::hasAssociatedConstraints() const { + // TODO: Concepts: Regard function trailing requires clause. + return TemplateParams->hasAssociatedConstraints(); +} + //===----------------------------------------------------------------------===// // RedeclarableTemplateDecl Implementation //===----------------------------------------------------------------------===// @@ -344,19 +380,10 @@ SourceLocation L, DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl, - Expr *AssociatedConstraints) { + NamedDecl *Decl) { AdoptTemplateParameterList(Params, cast(Decl)); - if (!AssociatedConstraints) { - return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl); - } - - auto *const CTDI = new (C) ConstrainedTemplateDeclInfo; - auto *const New = - new (C, DC) ClassTemplateDecl(CTDI, C, DC, L, Name, Params, Decl); - New->setAssociatedConstraints(AssociatedConstraints); - return New; + return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl); } ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C, @@ -703,12 +730,6 @@ FD, Template, TSK, TemplateArgs, ArgsAsWritten, POI, MSInfo); } -//===----------------------------------------------------------------------===// -// TemplateDecl Implementation -//===----------------------------------------------------------------------===// - -void TemplateDecl::anchor() {} - //===----------------------------------------------------------------------===// // ClassTemplateSpecializationDecl Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -119,4 +119,4 @@ IsSatisfied = EvalResult.Val.getInt().getBoolValue(); return false; -} +} \ No newline at end of file diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -44,27 +44,7 @@ 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. /// @@ -1502,9 +1482,6 @@ } } - // 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 @@ -1516,30 +1493,6 @@ 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, @@ -1643,15 +1596,10 @@ 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); @@ -7230,6 +7178,9 @@ TemplateArgLoc); } + // TODO: Concepts: Match immediately-introduced-constraint for type + // constraints + return true; } @@ -7255,6 +7206,15 @@ << 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. /// @@ -7344,6 +7304,27 @@ 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; } @@ -8053,10 +8034,9 @@ 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/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3443,14 +3443,21 @@ 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; } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9270,9 +9270,11 @@ while (NumParams--) Params.push_back(ReadDeclAs(F, Record, Idx)); - // TODO: Concepts + bool HasRequiresClause = Record[Idx++]; + Expr *RequiresClause = HasRequiresClause ? ReadExpr(F) : nullptr; + TemplateParameterList *TemplateParams = TemplateParameterList::Create( - getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, nullptr); + getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause); return TemplateParams; } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2087,7 +2087,6 @@ DeclID PatternID = ReadDeclID(); auto *TemplatedDecl = cast_or_null(Reader.GetDecl(PatternID)); TemplateParameterList *TemplateParams = Record.readTemplateParameterList(); - // FIXME handle associated constraints D->init(TemplatedDecl, TemplateParams); return PatternID; @@ -2253,7 +2252,8 @@ ClassTemplatePartialSpecializationDecl *D) { RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D); - D->TemplateParams = Record.readTemplateParameterList(); + TemplateParameterList *Params = Record.readTemplateParameterList(); + D->TemplateParams = Params; D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); // These are read/set from/to the first declaration. @@ -2355,7 +2355,8 @@ VarTemplatePartialSpecializationDecl *D) { RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D); - D->TemplateParams = Record.readTemplateParameterList(); + TemplateParameterList *Params = Record.readTemplateParameterList(); + D->TemplateParams = Params; D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); // These are read/set from/to the first declaration. @@ -2371,6 +2372,7 @@ D->setDeclaredWithTypename(Record.readInt()); + // TODO: Concepts: Immediately introduced constraint if (Record.readInt()) D->setDefaultArgument(GetTypeSourceInfo()); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -6022,10 +6022,16 @@ AddSourceLocation(TemplateParams->getTemplateLoc()); AddSourceLocation(TemplateParams->getLAngleLoc()); AddSourceLocation(TemplateParams->getRAngleLoc()); - // TODO: Concepts + Record->push_back(TemplateParams->size()); for (const auto &P : *TemplateParams) AddDeclRef(P); + if (const Expr *RequiresClause = TemplateParams->getRequiresClause()) { + Record->push_back(true); + AddStmt(const_cast(RequiresClause)); + } else { + Record->push_back(false); + } } /// Emit a template argument list. diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1601,7 +1601,7 @@ VisitTypeDecl(D); Record.push_back(D->wasDeclaredWithTypename()); - + // TODO: Concepts - constrained parameters. bool OwnsDefaultArg = D->hasDefaultArgument() && !D->defaultArgumentWasInherited(); Record.push_back(OwnsDefaultArg); @@ -1631,6 +1631,7 @@ 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() && @@ -1660,6 +1661,7 @@ 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/test/CXX/concepts-ts/temp/concept/p4.cpp b/clang/test/CXX/concepts-ts/temp/concept/p4.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CXX/concepts-ts/temp/concept/p4.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -verify %s + +template requires true +concept C = true; // expected-error{{concept cannot have associated constraints}} + +// TODO: Add test for other kinds of associated constraints once we have them. diff --git a/clang/test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp b/clang/test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp --- a/clang/test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp +++ b/clang/test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s +// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s namespace nodiag { @@ -13,15 +13,15 @@ template requires true // expected-note{{previous template declaration is here}} struct A; -template struct A; // expected-error{{associated constraints differ in template redeclaration}} +template struct A; // expected-error{{requires clause differs in template redeclaration}} template struct B; // expected-note{{previous template declaration is here}} -template requires true // expected-error{{associated constraints differ in template redeclaration}} +template requires true // expected-error{{requires clause differs in template redeclaration}} struct B; template requires true // expected-note{{previous template declaration is here}} struct C; -template requires !0 // expected-error{{associated constraints differ in template redeclaration}} +template requires !0 // expected-error{{requires clause differs in template redeclaration}} struct C; } // end namespace diag @@ -33,7 +33,7 @@ struct A; }; -template requires someFunc(T()) +template requires someFunc(U()) struct AA::A { }; struct AAF { @@ -47,18 +47,26 @@ template struct TA { - template