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.
This commit is contained in:
parent
df933e307b
commit
a95753214b
2 changed files with 86 additions and 5 deletions
12
gcc/cp/pt.c
12
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;
|
||||
|
|
79
gcc/testsuite/g++.dg/cpp2a/nontype-class40.C
Normal file
79
gcc/testsuite/g++.dg/cpp2a/nontype-class40.C
Normal file
|
@ -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>{};
|
||||
}
|
Loading…
Add table
Reference in a new issue