================
@@ -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

Reply via email to