diff options
-rw-r--r-- | gcc/cp/pt.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/nontype-class40.C | 79 |
2 files changed, 86 insertions, 5 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e991a32..2d3ab92 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8266,7 +8266,7 @@ convert_template_argument (tree parm, /* 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. */ @@ -29013,6 +29013,12 @@ do_class_deduction (tree ptype, tree tmpl, tree init, 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)) @@ -29029,10 +29035,6 @@ do_class_deduction (tree ptype, tree tmpl, tree init, "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; diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class40.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class40.C new file mode 100644 index 0000000..d193544 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class40.C @@ -0,0 +1,79 @@ +// 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>{}; +} |