aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/pt.c12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class40.C79
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>{};
+}