[clang] [clang-tools-extra] [Clang] Add __type_list_dedup builtin to deduplicate types in template arguments (PR #106730)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 4 06:19:18 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tools-extra
@llvm/pr-subscribers-clangd
Author: Ilya Biryukov (ilya-biryukov)
<details>
<summary>Changes</summary>
This allows to deduplicate the type lists efficiently in C++. It is possible to achieve the same effect via template metaprogramming, but performance of the resulting code is much lower than in the compiler.
We have observed that this code is quite common in our internal codebase and this builtin allows to have significant savings (up to 25% of compile time on targets that already take 3 minutes to compile). The same builtin is also used widely enough in the codebase that we expect a savings from a long tail of uses, too, although it is hard to put an estimate on this number in advance.
The implementation aims to be as simple as possible and relies on the exsisting machinery for builtin templates.
---
Patch is 20.75 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/106730.diff
16 Files Affected:
- (modified) clang-tools-extra/clangd/unittests/FindTargetTests.cpp (+6)
- (modified) clang/include/clang/AST/ASTContext.h (+11)
- (modified) clang/include/clang/AST/DeclID.h (+3)
- (modified) clang/include/clang/Basic/Builtins.h (+4-1)
- (modified) clang/lib/AST/ASTContext.cpp (+7)
- (modified) clang/lib/AST/ASTImporter.cpp (+3)
- (modified) clang/lib/AST/DeclTemplate.cpp (+31)
- (modified) clang/lib/Lex/PPMacroExpansion.cpp (+1)
- (modified) clang/lib/Sema/SemaLookup.cpp (+6-1)
- (modified) clang/lib/Sema/SemaTemplate.cpp (+33-2)
- (modified) clang/lib/Serialization/ASTReader.cpp (+6)
- (modified) clang/lib/Serialization/ASTWriter.cpp (+2)
- (modified) clang/test/Import/builtin-template/Inputs/S.cpp (+7)
- (modified) clang/test/Import/builtin-template/test.cpp (+9-1)
- (added) clang/test/PCH/type_list_dedup.cpp (+20)
- (added) clang/test/SemaTemplate/temp-param-list-dedup.cpp (+57)
``````````diff
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 3220a5a6a98250..d9f788cbf2a8a2 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -731,6 +731,12 @@ TEST_F(TargetDeclTest, BuiltinTemplates) {
using type_pack_element = [[__type_pack_element]]<N, Pack...>;
)cpp";
EXPECT_DECLS("TemplateSpecializationTypeLoc", );
+
+ Code = R"cpp(
+ template <template <class...> Templ, class... Types>
+ using type_list_dedup = [[__type_list_dedup]]<Templ, Types...>;
+ )cpp";
+ EXPECT_DECLS("TemplateSpecializationTypeLoc", );
}
TEST_F(TargetDeclTest, MemberOfTemplate) {
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 89bb5768dbd40d..1960ec1e99f652 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -401,6 +401,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// The identifier '__type_pack_element'.
mutable IdentifierInfo *TypePackElementName = nullptr;
+ /// The identifier '__type_list_dedup'.
+ mutable IdentifierInfo *TypeListDedupName = nullptr;
+
QualType ObjCConstantStringType;
mutable RecordDecl *CFConstantStringTagDecl = nullptr;
mutable TypedefDecl *CFConstantStringTypeDecl = nullptr;
@@ -608,6 +611,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable ExternCContextDecl *ExternCContext = nullptr;
mutable BuiltinTemplateDecl *MakeIntegerSeqDecl = nullptr;
mutable BuiltinTemplateDecl *TypePackElementDecl = nullptr;
+ mutable BuiltinTemplateDecl *TypeListDedupDecl = nullptr;
/// The associated SourceManager object.
SourceManager &SourceMgr;
@@ -1115,6 +1119,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
ExternCContextDecl *getExternCContextDecl() const;
BuiltinTemplateDecl *getMakeIntegerSeqDecl() const;
BuiltinTemplateDecl *getTypePackElementDecl() const;
+ BuiltinTemplateDecl *getTypeListDedupDecl() const;
// Builtin Types.
CanQualType VoidTy;
@@ -2006,6 +2011,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
return TypePackElementName;
}
+ IdentifierInfo *getTypeListDedupName() const {
+ if (!TypeListDedupName)
+ TypeListDedupName = &Idents.get("__type_list_dedup");
+ return TypeListDedupName;
+ }
+
/// Retrieve the Objective-C "instancetype" type, if already known;
/// otherwise, returns a NULL type;
QualType getObjCInstanceType() {
diff --git a/clang/include/clang/AST/DeclID.h b/clang/include/clang/AST/DeclID.h
index 81454a247229f5..41cecf1b8a9ebf 100644
--- a/clang/include/clang/AST/DeclID.h
+++ b/clang/include/clang/AST/DeclID.h
@@ -83,6 +83,9 @@ enum PredefinedDeclIDs {
/// The internal '__type_pack_element' template.
PREDEF_DECL_TYPE_PACK_ELEMENT_ID,
+ /// The internal '__type_list_dedup' template.
+ PREDEF_DECL_TYPE_LIST_DEDUP_ID,
+
/// The number of declaration IDs that are predefined.
NUM_PREDEF_DECL_IDS
};
diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h
index e85ec5b2dca14e..018996c0da527e 100644
--- a/clang/include/clang/Basic/Builtins.h
+++ b/clang/include/clang/Basic/Builtins.h
@@ -309,7 +309,10 @@ enum BuiltinTemplateKind : int {
BTK__make_integer_seq,
/// This names the __type_pack_element BuiltinTemplateDecl.
- BTK__type_pack_element
+ BTK__type_pack_element,
+
+ /// This names the __type_list_dedup BuiltinTemplateDecl.
+ BTK__type_list_dedup,
};
} // end namespace clang
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index c61234aa4d1af1..aaea59eb9962c4 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1170,6 +1170,13 @@ ASTContext::getTypePackElementDecl() const {
return TypePackElementDecl;
}
+BuiltinTemplateDecl *ASTContext::getTypeListDedupDecl() const {
+ if (!TypeListDedupDecl)
+ TypeListDedupDecl =
+ buildBuiltinTemplateDecl(BTK__type_list_dedup, getTypeListDedupName());
+ return TypeListDedupDecl;
+}
+
RecordDecl *ASTContext::buildImplicitRecord(StringRef Name,
RecordDecl::TagKind TK) const {
SourceLocation Loc;
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index fa850409ba1210..7d97558ff0a87a 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -5476,6 +5476,9 @@ ExpectedDecl ASTNodeImporter::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
case BuiltinTemplateKind::BTK__type_pack_element:
ToD = Importer.getToContext().getTypePackElementDecl();
break;
+ case BuiltinTemplateKind::BTK__type_list_dedup:
+ ToD = Importer.getToContext().getTypeListDedupDecl();
+ break;
}
assert(ToD && "BuiltinTemplateDecl of unsupported kind!");
Importer.MapImported(D, ToD);
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 976b3a3e1ecedb..727f9a0751cf82 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -1608,6 +1608,35 @@ createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) {
nullptr);
}
+static TemplateParameterList *
+createTypeListDedupParameterList(const ASTContext &C, DeclContext *DC) {
+ // template <typename ...> typename Templ
+ auto *InnerTs = TemplateTypeParmDecl::Create(
+ C, DC, SourceLocation(), SourceLocation(), /*Depth=*/1, /*Position=*/0,
+ /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true,
+ /*HasTypeConstraint=*/false);
+ InnerTs->setImplicit(true);
+ auto *TemplateParamList = TemplateParameterList::Create(
+ C, SourceLocation(), SourceLocation(), {InnerTs}, SourceLocation(),
+ /*RequiresClause=*/nullptr);
+ auto *Template = TemplateTemplateParmDecl::Create(
+ C, DC, SourceLocation(), /*Depth=*/0,
+ /*Position=*/0, /*ParameterPack=*/false, /*Id=*/nullptr,
+ /*Typename=*/true, TemplateParamList);
+ Template->setImplicit(true);
+
+ // typename ...Ts
+ auto *Ts = TemplateTypeParmDecl::Create(
+ C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
+ /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true,
+ /*HasTypeConstraint=*/false);
+ Ts->setImplicit(true);
+ return TemplateParameterList::Create(
+ C, SourceLocation(), SourceLocation(),
+ llvm::ArrayRef<NamedDecl *>({Template, Ts}), SourceLocation(),
+ /*RequiresClause=*/nullptr);
+}
+
static TemplateParameterList *createBuiltinTemplateParameterList(
const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) {
switch (BTK) {
@@ -1615,6 +1644,8 @@ static TemplateParameterList *createBuiltinTemplateParameterList(
return createMakeIntegerSeqParameterList(C, DC);
case BTK__type_pack_element:
return createTypePackElementParameterList(C, DC);
+ case BTK__type_list_dedup:
+ return createTypeListDedupParameterList(C, DC);
}
llvm_unreachable("unhandled BuiltinTemplateKind!");
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index 1d671ab72b0c03..f2d091ab29082e 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1836,6 +1836,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
// Report builtin templates as being builtins.
.Case("__make_integer_seq", getLangOpts().CPlusPlus)
.Case("__type_pack_element", getLangOpts().CPlusPlus)
+ .Case("__type_list_dedup", getLangOpts().CPlusPlus)
// Likewise for some builtin preprocessor macros.
// FIXME: This is inconsistent; we usually suggest detecting
// builtin macros via #ifdef. Don't add more cases here.
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 7a6a64529f52ec..cf75caca67088b 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -928,10 +928,15 @@ bool Sema::LookupBuiltin(LookupResult &R) {
if (II == getASTContext().getMakeIntegerSeqName()) {
R.addDecl(getASTContext().getMakeIntegerSeqDecl());
return true;
- } else if (II == getASTContext().getTypePackElementName()) {
+ }
+ if (II == getASTContext().getTypePackElementName()) {
R.addDecl(getASTContext().getTypePackElementDecl());
return true;
}
+ if (II == getASTContext().getTypeListDedupName()) {
+ R.addDecl(getASTContext().getTypeListDedupDecl());
+ return true;
+ }
}
// Check if this is an OpenCL Builtin, and if so, insert its overloads.
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index bf6b53700d90eb..cace516263a78d 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -17,7 +17,9 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
+#include "clang/AST/TypeOrdering.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticSema.h"
@@ -38,9 +40,11 @@
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
#include <iterator>
#include <optional>
@@ -3132,12 +3136,12 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
TemplateLoc, SyntheticTemplateArgs);
}
- case BTK__type_pack_element:
+ case BTK__type_pack_element: {
// Specializations of
// __type_pack_element<Index, T_1, ..., T_N>
// are treated like T_Index.
assert(Converted.size() == 2 &&
- "__type_pack_element should be given an index and a parameter pack");
+ "__type_pack_element should be given an index and a parameter pack");
TemplateArgument IndexArg = Converted[0], Ts = Converted[1];
if (IndexArg.isDependent() || Ts.isDependent())
@@ -3158,6 +3162,33 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
int64_t N = Index.getExtValue();
return Ts.getPackAsArray()[N].getAsType();
}
+ case BTK__type_list_dedup: {
+ assert(Converted.size() == 2 &&
+ "__type_list_dedup should be given a template and a parameter pack");
+ TemplateArgument Template = Converted[0];
+ TemplateArgument Ts = Converted[1];
+ if (Template.isDependent() || Ts.isDependent())
+ return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD),
+ Converted);
+
+ assert(Template.getKind() == clang::TemplateArgument::Template);
+ assert(Ts.getKind() == clang::TemplateArgument::Pack);
+ TemplateArgumentListInfo SyntheticTemplateArgs;
+ llvm::DenseSet<QualType> Seen;
+ // Synthesize a new template argument list, removing duplicates.
+ for (auto T : Ts.getPackAsArray()) {
+ assert(T.getKind() == clang::TemplateArgument::Type);
+ if (!Seen.insert(T.getAsType().getCanonicalType()).second)
+ continue;
+ SyntheticTemplateArgs.addArgument(TemplateArgumentLoc(
+ TemplateArgument(T), SemaRef.Context.getTrivialTypeSourceInfo(
+ T.getAsType(),
+ /*FIXME: add location*/ SourceLocation())));
+ }
+ return SemaRef.CheckTemplateIdType(Template.getAsTemplate(), TemplateLoc,
+ SyntheticTemplateArgs);
+ }
+ }
llvm_unreachable("unexpected BuiltinTemplateDecl!");
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index e5a1e20a265616..78cb449d60c474 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -23,6 +23,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclGroup.h"
+#include "clang/AST/DeclID.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
@@ -7897,6 +7898,11 @@ Decl *ASTReader::getPredefinedDecl(PredefinedDeclIDs ID) {
return Context.TypePackElementDecl;
NewLoaded = Context.getTypePackElementDecl();
break;
+ case PREDEF_DECL_TYPE_LIST_DEDUP_ID:
+ if (Context.TypeListDedupDecl)
+ return Context.TypeListDedupDecl;
+ NewLoaded = Context.getTypeListDedupDecl();
+ break;
case NUM_PREDEF_DECL_IDS:
llvm_unreachable("Invalid decl ID");
break;
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index c6289493fce1de..9a1c67e33894bd 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -22,6 +22,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclID.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
@@ -5051,6 +5052,7 @@ void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {
PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID);
RegisterPredefDecl(Context.TypePackElementDecl,
PREDEF_DECL_TYPE_PACK_ELEMENT_ID);
+ RegisterPredefDecl(Context.TypeListDedupDecl, PREDEF_DECL_TYPE_LIST_DEDUP_ID);
const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
diff --git a/clang/test/Import/builtin-template/Inputs/S.cpp b/clang/test/Import/builtin-template/Inputs/S.cpp
index d5c9a9ae0309d3..6cde0732d3719f 100644
--- a/clang/test/Import/builtin-template/Inputs/S.cpp
+++ b/clang/test/Import/builtin-template/Inputs/S.cpp
@@ -14,3 +14,10 @@ using TypePackElement = __type_pack_element<i, T...>;
template <int i>
struct X;
+
+
+template <template <class...> class Templ, class...Types>
+using TypeListDedup = __type_list_dedup<Templ, Types...>;
+
+template <class ...Ts>
+struct TypeList {};
diff --git a/clang/test/Import/builtin-template/test.cpp b/clang/test/Import/builtin-template/test.cpp
index 590efad0c71dca..ca67457d73f2b6 100644
--- a/clang/test/Import/builtin-template/test.cpp
+++ b/clang/test/Import/builtin-template/test.cpp
@@ -1,9 +1,11 @@
// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s -Xcc -DSEQ | FileCheck --check-prefix=CHECK-SEQ %s
// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s -Xcc -DPACK | FileCheck --check-prefix=CHECK-PACK %s
-// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s -Xcc -DPACK -Xcc -DSEQ | FileCheck --check-prefixes=CHECK-SEQ,CHECK-PACK %s
+// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s -Xcc -DDEDUP | FileCheck --check-prefix=CHECK-DEDUP %s
+// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s -Xcc -DPACK -Xcc -DSEQ -Xcc -DDEDUP | FileCheck --check-prefixes=CHECK-SEQ,CHECK-PACK,CHECK-DEDUP %s
// CHECK-SEQ: BuiltinTemplateDecl {{.+}} <<invalid sloc>> <invalid sloc> implicit __make_integer_seq{{$}}
// CHECK-PACK: BuiltinTemplateDecl {{.+}} <<invalid sloc>> <invalid sloc> implicit __type_pack_element{{$}}
+// CHECK-DEDUP: BuiltinTemplateDecl {{.+}} <<invalid sloc>> <invalid sloc> implicit __type_list_dedup{{$}}
void expr() {
#ifdef SEQ
@@ -20,4 +22,10 @@ void expr() {
static_assert(__is_same(TypePackElement<0, X<0>, X<1>>, X<0>), "");
static_assert(__is_same(TypePackElement<1, X<0>, X<1>>, X<1>), "");
#endif
+
+#ifdef DEDUP
+ static_assert(__is_same(TypeListDedup<TypeList>, TypeList<>), "");
+ static_assert(__is_same(TypeListDedup<TypeList, int, double, int>, TypeList<int, double>), "");
+ static_assert(__is_same(TypeListDedup<TypeList, X<0>, X<1>, X<1>, X<2>, X<0>>, TypeList<X<0>, X<1>, X<2>>), "");
+#endif
}
diff --git a/clang/test/PCH/type_list_dedup.cpp b/clang/test/PCH/type_list_dedup.cpp
new file mode 100644
index 00000000000000..a84dc340160edf
--- /dev/null
+++ b/clang/test/PCH/type_list_dedup.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++14 -x c++-header %s -emit-pch -o %t.pch
+// RUN: %clang_cc1 -std=c++14 -x c++ /dev/null -include-pch %t.pch
+
+// RUN: %clang_cc1 -std=c++14 -x c++-header %s -emit-pch -fpch-instantiate-templates -o %t.pch
+// RUN: %clang_cc1 -std=c++14 -x c++ /dev/null -include-pch %t.pch
+
+template <template <class...> class Templ, class...Types>
+using TypeListDedup = __type_list_dedup<Templ, Types...>;
+
+template <class ...Ts>
+struct TypeList {};
+
+template <int i>
+struct X {};
+
+void fn1() {
+ TypeList<int, double> l1 = TypeListDedup<TypeList, int, double, int>{};
+ TypeList<> l2 = TypeListDedup<TypeList>{};
+ TypeList<X<0>, X<1>> x1 = TypeListDedup<TypeList, X<0>, X<1>, X<0>, X<1>>{};
+}
diff --git a/clang/test/SemaTemplate/temp-param-list-dedup.cpp b/clang/test/SemaTemplate/temp-param-list-dedup.cpp
new file mode 100644
index 00000000000000..7a9f6c79419445
--- /dev/null
+++ b/clang/test/SemaTemplate/temp-param-list-dedup.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 %s -verify
+
+template <typename...> struct TypeList;
+
+static_assert(__is_same(
+ __type_list_dedup<TypeList, int, int*, int, double, float>,
+ TypeList<int, int*, double, float>));
+
+template <template<typename ...> typename Templ, typename ...Types>
+struct Dependent {
+ using empty_list = __type_list_dedup<Templ>;
+ using same = __type_list_dedup<Templ, Types...>;
+ using twice = __type_list_dedup<Templ, Types..., Types...>;
+ using dep_only_types = __type_list_dedup<TypeList, Types...>;
+ using dep_only_template = __type_list_dedup<Templ, int, double, int>;
+};
+
+static_assert(__is_same(Dependent<TypeList>::empty_list, TypeList<>));
+static_assert(__is_same(Dependent<TypeList>::same, TypeList<>));
+static_assert(__is_same(Dependent<TypeList>::twice, TypeList<>));
+static_assert(__is_same(Dependent<TypeList>::dep_only_types, TypeList<>));
+static_assert(__is_same(Dependent<TypeList>::dep_only_template, TypeList<int, double>));
+
+static_assert(__is_same(Dependent<TypeList, int*, double*, int*>::empty_list, TypeList<>));
+static_assert(__is_same(Dependent<TypeList, int*, double*, int*>::same, TypeList<int*, double*>));
+static_assert(__is_same(Dependent<TypeList, int*, double*, int*>::twice, TypeList<int*, double*>));
+static_assert(__is_same(Dependent<TypeList, int*, double*, int*>::dep_only_types, TypeList<int*, double*>));
+static_assert(__is_same(Dependent<TypeList, int*, double*, int*>::dep_only_template, TypeList<int, double>));
+
+
+template <class ...T>
+using Twice = TypeList<T..., T...>;
+
+static_assert(__is_same(__type_list_dedup<Twice, int, double, int>, TypeList<int, double, int, double>));
+
+
+template <int...> struct IntList;
+// Wrong kinds of template arguments.
+__type_list_dedup<IntList>* wrong_template; // expected-error {{template template argument has different template parameters than its corresponding template template parameter}}
+ // expected-note at -3 {{template parameter has a different kind in template argument}}
+__type_list_dedup<TypeList, 1, 2, 3>* wrong_template_args; // expected-error {{template argument for template type parameter must be a type}}
+ // expected-note@* {{previous template template parameter is here}}
+ // expected-note@* {{template parameter from hidden source}}
+__type_list_dedup<> not_enough_args; // expected-error {{too few template arguments for template '__type_list_dedup'}}
+ // expected-note@* {{template declaration from hidden source}}
+__type_list_dedup missing_template_args; // expected-error {{use of template '__type_list_dedup' requires template arguments}}
+ // expected-note@* {{template declaration from hidden source}}
+
+// Direct recursive use will fail because the signature of template parameters does not match.
+// The intention for this test is to anticipate a failure mode where compiler may start running the deduplication recursively, going int...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/106730
More information about the cfe-commits
mailing list