================ @@ -6484,6 +6499,57 @@ class SubstTemplateTypeParmType final } }; +/// Represents the result of substituting a set of types as a template argument +/// that needs to be expanded later. +/// +/// These types are always dependent and produced depending on the situations: +/// - SubstTemplateTypeParmPack represents a pack expansion that had to be +/// delayed, +/// - TODO: represents a pack expansion represented by a builtin. +class SubstPackType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + + /// A pointer to the set of template arguments that this + /// parameter pack is instantiated with. + const TemplateArgument *Arguments; + +protected: + SubstPackType(TypeClass Derived, QualType Canon, + const TemplateArgument &ArgPack); + +public: + unsigned getNumArgs() const { return SubstPackTypeBits.NumArgs; } + + TemplateArgument getArgumentPack() const; + + void Profile(llvm::FoldingSetNodeID &ID); + static void Profile(llvm::FoldingSetNodeID &ID, + const TemplateArgument &ArgPack); + + static bool classof(const Type *T) { + return T->getTypeClass() == SubstTemplateTypeParmPack || + T->getTypeClass() == SubstBuiltinTemplatePack; + } +}; + +/// Represents the result of substituting a builtin template as a pack. +class SubstBuiltinTemplatePackType : public SubstPackType { + friend class ASTContext; + + SubstBuiltinTemplatePackType(QualType Canon, const TemplateArgument &ArgPack); ---------------- ilya-biryukov wrote:
`SubstTemplateTypeParmPackType` needs a (variadic) template parameter and we don't have one. We could go in the direction of making the template parameter in `SubstTemplateTypeParmPackType` optional (e.g. it's just null), but I believe it's a bad idea because that would require a lot of care to all places where `SubstTemplateTypeParmPackType` is used to make sure they handle the cases with nulls properly and having some static typing here should make these problems avoidable by design. Another alternative that I imagine is to remove `SubstTemplateTypeParmPackType`, have only `SubstPackType` as a concrete type for both cases (builtin packs and variadic template parameters) and have different sugar on top: - for cases of delayed pack expansion (i.e. `SubstTemplateTypeParmPackType` now) we could use `SubstTemplateTypeParmType` that matches the sugar we want here precisely ("this delayed pack is coming from substitution of this template parameter") - for cases with builtins producing packs, we add `TemplateSpecializationType` on top like we do today. I did not pursue this only because there was a curious use of `SubstTemplateTypeParmPackType` in template deduction that I didn't want to dig into to keep myself focused on the task at hand. It feels like a good alternative, actually, but I would really want to pursue it separately to avoid changing behavior where we do not actually have these new builtins with this change. https://github.com/llvm/llvm-project/pull/106730 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits