/* When determining whether an argument pack expansion is a template,
look at the pattern. */
- if (TREE_CODE (arg) == TYPE_PACK_EXPANSION)
+ if (PACK_EXPANSION_P (arg))
arg = PACK_EXPANSION_PATTERN (arg);
/* Deal with an injected-class-name used as a template template arg. */
if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
return ptype;
+ /* Initializing one placeholder from another. */
+ if (init && TREE_CODE (init) == TEMPLATE_PARM_INDEX
+ && is_auto (TREE_TYPE (init))
+ && CLASS_PLACEHOLDER_TEMPLATE (TREE_TYPE (init)) == tmpl)
+ return cp_build_qualified_type (TREE_TYPE (init), cp_type_quals (ptype));
+
/* Look through alias templates that just rename another template. */
tmpl = get_underlying_template (tmpl);
if (!ctad_template_p (tmpl))
"with %<-std=c++20%> or %<-std=gnu++20%>");
}
- if (init && TREE_TYPE (init) == ptype)
- /* Using the template parm as its own argument. */
- return ptype;
-
tree type = TREE_TYPE (tmpl);
bool try_list_ctor = false;
--- /dev/null
+// PR c++/93083
+// { dg-do compile { target c++20 } }
+
+template<unsigned N>
+struct FixedString
+{
+ char buf[N + 1]{};
+ constexpr FixedString(char const* s) {
+ for (unsigned i = 0; i != N; ++i) buf[i] = s[i];
+ }
+
+ auto operator<=>(const FixedString&) const = default;
+ constexpr operator char const*() const { return buf; }
+ constexpr static unsigned size() noexcept { return N; }
+};
+
+template<unsigned N> FixedString(char const (&)[N]) -> FixedString<N - 1>;
+
+template <FixedString... names>
+struct name_list
+{
+ template <FixedString name>
+ using add_name = name_list<
+ names...,
+ FixedString<name.size()>{ name }
+ >;
+};
+
+
+int main()
+{
+ using names =
+ name_list<>
+ ::add_name<"Zaphod Beeblebrox">;
+
+}
+
+// ----------------
+
+template <int N> struct literal {
+ constexpr literal(const char (&input)[N]) noexcept { }
+ constexpr literal(const literal &) noexcept { }
+};
+
+template <literal Name, int id> struct field { };
+
+template <literal Name> struct field<Name, 1u> { };
+
+// ----------------
+
+template <int N>
+struct use_as_nttp {};
+
+template <use_as_nttp Value>
+struct has_nttp {};
+
+template <use_as_nttp Value>
+using has_nttp_2 = has_nttp<Value>;
+
+// ----------------
+
+using size_t = decltype(sizeof(0));
+
+template <size_t N>
+struct string_literal
+{
+ constexpr string_literal(const char*) {}
+ string_literal(string_literal const&) = default;
+};
+template <size_t N>
+string_literal(const char (&)[N]) -> string_literal<N - 1>;
+
+template <string_literal Str>
+struct type_string { };
+
+template <string_literal Str>
+void foo() {
+ type_string<Str>{};
+}