Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -287,12 +287,16 @@ TemplateTemplateParmDecl *getParam() const { return Parm; } - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Parm); } + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) { + Profile(ID, C, Parm); + } static void Profile(llvm::FoldingSetNodeID &ID, + const ASTContext &C, TemplateTemplateParmDecl *Parm); }; - mutable llvm::FoldingSet + mutable llvm::ContextualFoldingSet CanonTemplateTemplateParms; TemplateTemplateParmDecl * Index: include/clang/AST/ASTNodeTraverser.h =================================================================== --- include/clang/AST/ASTNodeTraverser.h +++ include/clang/AST/ASTNodeTraverser.h @@ -490,6 +490,8 @@ } void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { + if (const Expr *CE = D->getConstraintExpression()) + Visit(CE); if (D->hasDefaultArgument()) Visit(D->getDefaultArgument(), SourceRange(), D->getDefaultArgStorage().getInheritedFrom(), @@ -497,6 +499,8 @@ } void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { + if (const Expr *CE = D->getConstraintExpression()) + Visit(CE); if (D->hasDefaultArgument()) Visit(D->getDefaultArgument(), SourceRange(), D->getDefaultArgStorage().getInheritedFrom(), @@ -505,6 +509,8 @@ void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) { dumpTemplateParameters(D->getTemplateParameters()); + if (const Expr *CE = D->getConstraintExpression()) + Visit(CE); if (D->hasDefaultArgument()) dumpTemplateArgumentLoc( D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(), Index: include/clang/AST/DeclTemplate.h =================================================================== --- include/clang/AST/DeclTemplate.h +++ include/clang/AST/DeclTemplate.h @@ -81,20 +81,24 @@ /// pack. unsigned ContainsUnexpandedParameterPack : 1; - /// Whether this template parameter list has an associated requires-clause + /// Whether this template parameter list has a requires clause. unsigned HasRequiresClause : 1; + /// Whether any of the template parameters has constrained-parameter + /// constraint-expression. + unsigned HasConstrainedParameters : 1; + protected: - TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, - ArrayRef Params, SourceLocation RAngleLoc, - Expr *RequiresClause); + TemplateParameterList(const ASTContext& C, SourceLocation TemplateLoc, + SourceLocation LAngleLoc, ArrayRef Params, + SourceLocation RAngleLoc, Expr *RequiresClause); size_t numTrailingObjects(OverloadToken) const { return NumParams; } size_t numTrailingObjects(OverloadToken) const { - return HasRequiresClause; + return HasRequiresClause ? 1 : 0; } public: @@ -158,14 +162,22 @@ return ContainsUnexpandedParameterPack; } + /// Determine whether this template parameter list contains a parameter pack. + bool hasParameterPack() const { + for (const NamedDecl *P : asArray()) + if (P->isParameterPack()) + return true; + return false; + } + /// The constraint-expression of the associated requires-clause. Expr *getRequiresClause() { - return HasRequiresClause ? *getTrailingObjects() : nullptr; + return HasRequiresClause ? getTrailingObjects()[0] : nullptr; } /// The constraint-expression of the associated requires-clause. const Expr *getRequiresClause() const { - return HasRequiresClause ? *getTrailingObjects() : nullptr; + return HasRequiresClause ? getTrailingObjects()[0] : nullptr; } /// \brief All associated constraints derived from this template parameter @@ -203,15 +215,16 @@ >::type storage; public: - FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc, + FixedSizeTemplateParameterListStorage(const ASTContext &C, + SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef Params, SourceLocation RAngleLoc, Expr *RequiresClause) : FixedSizeStorageOwner( (assert(N == Params.size()), - assert(HasRequiresClause == static_cast(RequiresClause)), - new (static_cast(&storage)) TemplateParameterList( + assert(HasRequiresClause == (RequiresClause != nullptr)), + new (static_cast(&storage)) TemplateParameterList(C, TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause))) {} }; @@ -1106,6 +1119,10 @@ DefaultArgStorage; DefArgStorage DefaultArgument; + /// \brief The constraint expression introduced by this declaration (by means + /// of a 'constrained-parameter'. + Expr *ConstraintExpression = nullptr; + TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, SourceLocation IdLoc, IdentifierInfo *Id, bool Typename) @@ -1182,6 +1199,30 @@ /// Returns whether this is a parameter pack. bool isParameterPack() const; + /// \brief Returns the constraint expression associated with this template + /// parameter (if any). + Expr *getConstraintExpression() const { + return ConstraintExpression; + } + + /// \brief Sets the constraint expression associated with this template + /// parameter (if any). + void setConstraintExpression(Expr *E) { + ConstraintExpression = E; + } + + /// \brief Get the associated-constraints of this template parameter. + /// Currently, this will either be a vector of size 1 containing the + /// constrained-parameter constraint or an empty vector. + /// + /// Use this instead of getConstraintExpression for concepts APIs that + /// accept an ArrayRef of constraint expressions. + llvm::SmallVector getAssociatedConstraints() const { + if (ConstraintExpression) + return{ConstraintExpression}; + return{}; + } + SourceRange getSourceRange() const override LLVM_READONLY; // Implement isa/cast/dyncast/etc. @@ -1221,6 +1262,10 @@ /// The number of types in an expanded parameter pack. unsigned NumExpandedTypes = 0; + /// \brief The constraint expression introduced by this declaration (by means + /// of a 'constrained-parameter'. + Expr *ConstraintExpression = nullptr; + size_t numTrailingObjects( OverloadToken>) const { return NumExpandedTypes; @@ -1367,6 +1412,30 @@ return TypesAndInfos[I].second; } + /// \brief Returns the constraint expression associated with this template + /// parameter (if any). + Expr *getConstraintExpression() const { + return ConstraintExpression; + } + + /// \brief Sets the constraint expression associated with this template + /// parameter (if any). + void setConstraintExpression(Expr *E) { + ConstraintExpression = E; + } + + /// \brief Get the associated-constraints of this template parameter. + /// Currently, this will either be a vector of size 1 containing the + /// constrained-parameter constraint or an empty vector. + /// + /// Use this instead of getConstraintExpression for concepts APIs that + /// accept an ArrayRef of constraint expressions. + llvm::SmallVector getAssociatedConstraints() const { + if (ConstraintExpression) + return{ConstraintExpression}; + return{}; + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == NonTypeTemplateParm; } @@ -1400,6 +1469,10 @@ /// The number of parameters in an expanded parameter pack. unsigned NumExpandedParams = 0; + /// \brief The constraint expression introduced by this declaration (by means + /// of a 'constrained-parameter'. + Expr *ConstraintExpression = nullptr; + TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, bool ParameterPack, IdentifierInfo *Id, TemplateParameterList *Params) @@ -1527,6 +1600,30 @@ /// Removes the default argument of this template parameter. void removeDefaultArgument() { DefaultArgument.clear(); } + /// \brief Returns the constraint expression associated with this template + /// parameter (if any). + Expr *getConstraintExpression() const { + return ConstraintExpression; + } + + /// \brief Sets the constraint expression associated with this template + /// parameter (if any). + void setConstraintExpression(Expr *E) { + ConstraintExpression = E; + } + + /// \brief Get the associated-constraints of this template parameter. + /// Currently, this will either be a vector of size 1 containing the + /// constrained-parameter constraint or an empty vector. + /// + /// Use this instead of getConstraintExpression for concepts APIs that + /// accept an ArrayRef of constraint expressions. + llvm::SmallVector getAssociatedConstraints() const { + if (ConstraintExpression) + return{ConstraintExpression}; + return{}; + } + SourceRange getSourceRange() const override LLVM_READONLY { SourceLocation End = getLocation(); if (hasDefaultArgument() && !defaultArgumentWasInherited()) Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -1759,9 +1759,10 @@ // D is the "T" in something like // template