hubert.reinterpretcast updated this revision to Diff 54455. hubert.reinterpretcast added a comment.
Store the RequiresClause expression into the created storage; add accessor; add unnecessary parens to silence warning http://reviews.llvm.org/D19322 Files: include/clang/AST/DeclTemplate.h lib/AST/DeclTemplate.cpp lib/Sema/SemaTemplateDeduction.cpp
Index: lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- lib/Sema/SemaTemplateDeduction.cpp +++ lib/Sema/SemaTemplateDeduction.cpp @@ -4034,8 +4034,8 @@ nullptr, false, false); QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0); NamedDecl *TemplParamPtr = TemplParam; - FixedSizeTemplateParameterListStorage<1> TemplateParamsSt( - Loc, Loc, TemplParamPtr, Loc); + FixedSizeTemplateParameterListStorage<1, false> TemplateParamsSt( + Loc, Loc, TemplParamPtr, Loc, nullptr); QualType FuncParam = SubstituteAutoTransform(*this, TemplArg).Apply(Type); assert(!FuncParam.isNull() && Index: lib/AST/DeclTemplate.cpp =================================================================== --- lib/AST/DeclTemplate.cpp +++ lib/AST/DeclTemplate.cpp @@ -31,9 +31,11 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef<NamedDecl *> Params, - SourceLocation RAngleLoc) + SourceLocation RAngleLoc, + Expr *RequiresClause) : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc), - NumParams(Params.size()), ContainsUnexpandedParameterPack(false) { + NumParams(Params.size()), ContainsUnexpandedParameterPack(false), + HasRequiresClause(static_cast<bool>(RequiresClause)) { assert(this->NumParams == NumParams && "Too many template parameters"); for (unsigned Idx = 0; Idx < NumParams; ++Idx) { NamedDecl *P = Params[Idx]; @@ -52,15 +54,21 @@ // template parameter list does too. } } + if (RequiresClause) { + *getTrailingObjects<Expr *>() = RequiresClause; + } } -TemplateParameterList *TemplateParameterList::Create( - const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc) { - void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *>(Params.size()), +TemplateParameterList * +TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ArrayRef<NamedDecl *> Params, + SourceLocation RAngleLoc, Expr *RequiresClause) { + void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *, Expr *>( + Params.size(), RequiresClause ? 1u : 0u), llvm::alignOf<TemplateParameterList>()); return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params, - RAngleLoc); + RAngleLoc, RequiresClause); } unsigned TemplateParameterList::getMinRequiredArguments() const { Index: include/clang/AST/DeclTemplate.h =================================================================== --- include/clang/AST/DeclTemplate.h +++ include/clang/AST/DeclTemplate.h @@ -46,7 +46,8 @@ /// \brief Stores a list of template parameters for a TemplateDecl and its /// derived classes. class TemplateParameterList final - : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *> { + : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *, + Expr *> { /// The location of the 'template' keyword. SourceLocation TemplateLoc; @@ -56,26 +57,36 @@ /// The number of template parameters in this template /// parameter list. - unsigned NumParams : 31; + unsigned NumParams : 30; /// Whether this template parameter list contains an unexpanded parameter /// pack. unsigned ContainsUnexpandedParameterPack : 1; + /// Whether this template parameter list has an associated requires-clause + unsigned HasRequiresClause : 1; + protected: size_t numTrailingObjects(OverloadToken<NamedDecl *>) const { return NumParams; } + size_t numTrailingObjects(OverloadToken<Expr *>) const { + return HasRequiresClause; + } + TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, - ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc); + ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc, + Expr *RequiresClause); public: + // FIXME: remove default argument for RequiresClause static TemplateParameterList *Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef<NamedDecl *> Params, - SourceLocation RAngleLoc); + SourceLocation RAngleLoc, + Expr *RequiresClause = nullptr); /// \brief Iterates through the template parameters in this list. typedef NamedDecl** iterator; @@ -127,6 +138,11 @@ return ContainsUnexpandedParameterPack; } + /// \brief The constraint-expression of the associated requires-clause. + const Expr *getRequiresClause() const { + return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr; + } + SourceLocation getTemplateLoc() const { return TemplateLoc; } SourceLocation getLAngleLoc() const { return LAngleLoc; } SourceLocation getRAngleLoc() const { return RAngleLoc; } @@ -136,34 +152,50 @@ } friend TrailingObjects; - template <size_t N> friend class FixedSizeTemplateParameterListStorage; + + template <size_t N, bool HasRequiresClause> + friend class FixedSizeTemplateParameterListStorage; }; -/// \brief Stores a list of template parameters for a TemplateDecl and its -/// derived classes. Suitable for creating on the stack. -template <size_t N> class FixedSizeTemplateParameterListStorage { +/// \brief Stores a list of template parameters and the associated +/// requires-clause (if any) for a TemplateDecl and its derived classes. +/// Suitable for creating on the stack. +template <size_t N, bool HasRequiresClause> +class FixedSizeTemplateParameterListStorage { // This is kinda ugly: TemplateParameterList usually gets allocated // in a block of memory with NamedDecls appended to it. Here, to get - // it stack allocated, we include the params as a separate - // variable. After allocation, the TemplateParameterList object - // treats them as part of itself. + // it stack allocated, we include the constraint-expression from the + // requires-clause and the params as separate variables. + // After allocation, the TemplateParameterList object treats them as + // part of itself. + // TODO: RequiresClause does not always need to be allocated TemplateParameterList List; NamedDecl *Params[N]; + Expr *RequiresClause; public: FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef<NamedDecl *> Params, - SourceLocation RAngleLoc) - : List(TemplateLoc, LAngleLoc, Params, RAngleLoc) { + SourceLocation RAngleLoc, + Expr *RequiresClause) + : List(TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause) { + + assert(N == Params.size()); + assert(HasRequiresClause == static_cast<bool>(RequiresClause)); + // Because we're doing an evil layout hack above, have some // asserts, just to double-check everything is laid out like // expected. - assert(sizeof(*this) == - TemplateParameterList::totalSizeToAlloc<NamedDecl *>(N) && - "Object layout not as expected"); + assert((sizeof(*this) == + TemplateParameterList::totalSizeToAlloc<NamedDecl *, Expr *>( + N, 1) && + "Object layout not as expected")); assert(this->Params == List.getTrailingObjects<NamedDecl *>() && "Object layout not as expected"); + assert(!HasRequiresClause || + &this->RequiresClause == List.getTrailingObjects<Expr *>() && + "Object layout not as expected"); } TemplateParameterList *get() { return &List; } };
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits