summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuanqi Xu <yedeng.yd@linux.alibaba.com>2024-04-07 13:58:37 +0800
committerChuanqi Xu <yedeng.yd@linux.alibaba.com>2024-04-25 17:33:32 +0800
commitd7a72730a00a35e86bebe48cff22f5eb5dceef71 (patch)
tree903112e583cb0ea2092e2c5f0078be56d53b7320
parentf4edc5b1cde1735d1c9c9f6c43ef4f50066965b0 (diff)
-rw-r--r--clang/lib/AST/ODRHash.cpp10
-rw-r--r--clang/test/Modules/recursive-instantiations.cppm40
2 files changed, 40 insertions, 10 deletions
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index 3488a20b23c0..fac06721b52c 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -809,16 +809,6 @@ void ODRHash::AddDecl(const Decl *D) {
AddDeclarationName(ND->getDeclName());
- const auto *Specialization =
- dyn_cast<ClassTemplateSpecializationDecl>(D);
- AddBoolean(Specialization);
- if (Specialization) {
- const TemplateArgumentList &List = Specialization->getTemplateArgs();
- ID.AddInteger(List.size());
- for (const TemplateArgument &TA : List.asArray())
- AddTemplateArgument(TA);
- }
-
// If this was a specialization we should take into account its template
// arguments. This helps to reduce collisions coming when visiting template
// specialization types (eg. when processing type template arguments).
diff --git a/clang/test/Modules/recursive-instantiations.cppm b/clang/test/Modules/recursive-instantiations.cppm
new file mode 100644
index 000000000000..d5854b0e647e
--- /dev/null
+++ b/clang/test/Modules/recursive-instantiations.cppm
@@ -0,0 +1,40 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/type_traits.cppm -emit-module-interface -o %t/type_traits.pcm
+// RUN: %clang_cc1 -std=c++20 %t/test.cpp -fprebuilt-module-path=%t -verify
+
+//--- type_traits.cppm
+export module type_traits;
+
+export template <typename T>
+constexpr bool is_pod_v = __is_pod(T);
+
+//--- test.cpp
+// expected-no-diagnostics
+import type_traits;
+// Base is either void or wrapper<T>.
+template <class Base> struct wrapper : Base {};
+template <> struct wrapper<void> {};
+
+// wrap<0>::type<T> is wrapper<T>, wrap<1>::type<T> is wrapper<wrapper<T>>,
+// and so on.
+template <int N>
+struct wrap {
+ template <class Base>
+ using type = wrapper<typename wrap<N-1>::template type<Base>>;
+};
+
+template <>
+struct wrap<0> {
+ template <class Base>
+ using type = wrapper<Base>;
+};
+
+inline constexpr int kMaxRank = 40;
+template <int N, class Base = void>
+using rank = typename wrap<N>::template type<Base>;
+using rank_selector_t = rank<kMaxRank>;
+
+static_assert(is_pod_v<rank_selector_t>, "Must be POD");