[clang] [clang-tools-extra] [Clang] Add builtins that deduplicate and sort types (PR #106730)

Ilya Biryukov via cfe-commits cfe-commits at lists.llvm.org
Wed May 14 08:11:56 PDT 2025


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


More information about the cfe-commits mailing list