diff options
author | Jason Merrill <jason@redhat.com> | 2020-11-25 17:05:24 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-12-04 17:47:05 -0500 |
commit | a95753214b55d21e5b44eeb098cccf88d44c94dd (patch) | |
tree | baf54176edc281d78bf9eb314bb06b74aa59a089 | |
parent | df933e307b1950ce12472660dcac1765b8eb431d (diff) | |
download | gcc-a95753214b55d21e5b44eeb098cccf88d44c94dd.zip gcc-a95753214b55d21e5b44eeb098cccf88d44c94dd.tar.gz gcc-a95753214b55d21e5b44eeb098cccf88d44c94dd.tar.bz2 |
c++: Fix deduction from auto template parameter [PR93083]
The check in do_class_deduction to handle passing one class placeholder
template parm as an argument for itself needed to be extended to also handle
equivalent parms from other templates.
gcc/cp/ChangeLog:
PR c++/93083
* pt.c (convert_template_argument): Handle equivalent placeholders.
(do_class_deduction): Look through EXPR_PACK_EXPANSION, too.
gcc/testsuite/ChangeLog:
PR c++/93083
* g++.dg/cpp2a/nontype-class40.C: New test.
-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>{}; +} |