PR c++/102933
gcc/cp/ChangeLog:
* parser.c (cp_parser_template_id): Call check_auto_in_tmpl_args
only for the concepts TS not also for standard concepts.
(cp_parser_simple_type_specifier): Adjust diagnostic for using
auto in parameter declaration.
* pt.c (tsubst_qualified_id): Call check_auto_in_tmpl_args only
for the concepts TS not also for standard concepts.
(extract_autos_r): Ignore CTAD placeholders.
(extract_autos): Use range-based for.
(do_auto_deduction): Use extract_autos only for the concepts TS
and not also for standard concepts.
(type_uses_auto): Likewise with for_each_template_parm.
(check_auto_in_tmpl_args): Assert that this function is used only
for the concepts tS. Simplify.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/nontype-class50.C: New test.
* g++.dg/cpp2a/nontype-class50a.C: New test.
---
gcc/cp/parser.c | 4 ++--
gcc/cp/pt.c | 24 +++++++++----------
gcc/testsuite/g++.dg/cpp2a/nontype-class50.C | 13 ++++++++++
gcc/testsuite/g++.dg/cpp2a/nontype-class50a.C | 5 ++++
4 files changed, 32 insertions(+), 14 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class50.C
create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class50a.C
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 49d951cfb19..5052f534d40 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -18168,7 +18168,7 @@ cp_parser_template_id (cp_parser *parser,
types. We reject them in functions, but if what we have is an
identifier, even with none_type we can't conclude it's NOT a
type, we have to wait for template substitution. */
- if (flag_concepts && check_auto_in_tmpl_args (templ, arguments))
+ if (flag_concepts_ts && check_auto_in_tmpl_args (templ, arguments))
template_id = error_mark_node;
/* Build a representation of the specialization. */
else if (identifier_p (templ))
@@ -19505,7 +19505,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
else if (!flag_concepts)
pedwarn (token->location, 0,
"use of %<auto%> in parameter declaration "
- "only available with %<-fconcepts-ts%>");
+ "only available with %<-std=c++20%> or %<-fconcepts%>");
}
else
type = make_auto ();
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 287cf4ce9d0..3321601e6ff 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16456,7 +16456,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
we want to catch is when we couldn't tell then, and can now,
namely when templ prior to substitution was an
identifier. */
- if (flag_concepts && check_auto_in_tmpl_args (expr, template_args))
+ if (flag_concepts_ts && check_auto_in_tmpl_args (expr, template_args))
return error_mark_node;
if (variable_template_p (expr))
@@ -28560,7 +28560,7 @@ static int
extract_autos_r (tree t, void *data)
{
hash_table<auto_hash> &hash = *(hash_table<auto_hash>*)data;
- if (is_auto (t))
+ if (is_auto (t) && !template_placeholder_p (t))
{
/* All the autos were built with index 0; fix that up now. */
tree *p = hash.find_slot (t, INSERT);
@@ -28594,10 +28594,8 @@ extract_autos (tree type)
for_each_template_parm (type, extract_autos_r, &hash, &visited, true);
tree tree_vec = make_tree_vec (hash.elements());
- for (hash_table<auto_hash>::iterator iter = hash.begin();
- iter != hash.end(); ++iter)
+ for (tree elt : hash)
{
- tree elt = *iter;
unsigned i = TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (elt));
TREE_VEC_ELT (tree_vec, i)
= build_tree_list (NULL_TREE, TYPE_NAME (elt));
@@ -29837,7 +29835,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
tree parms = build_tree_list (NULL_TREE, type);
tree tparms;
- if (flag_concepts)
+ if (flag_concepts_ts)
tparms = extract_autos (type);
else
{
@@ -30025,7 +30023,7 @@ type_uses_auto (tree type)
{
if (type == NULL_TREE)
return NULL_TREE;
- else if (flag_concepts)
+ else if (flag_concepts_ts)
{
/* The Concepts TS allows multiple autos in one type-specifier; just
return the first one we find, do_auto_deduction will collect all of
@@ -30048,6 +30046,9 @@ type_uses_auto (tree type)
bool
check_auto_in_tmpl_args (tree tmpl, tree args)
{
+ /* Only the concepts TS allows 'auto' as a type-id. */
+ gcc_assert (flag_concepts_ts);
+
/* If there were previous errors, nevermind. */
if (!args || TREE_CODE (args) != TREE_VEC)
return false;
@@ -30057,11 +30058,10 @@ check_auto_in_tmpl_args (tree tmpl, tree args)
We'll only be able to tell during template substitution, so we
expect to be called again then. If concepts are enabled and we
know we have a type, we're ok. */
- if (flag_concepts
- && (identifier_p (tmpl)
- || (DECL_P (tmpl)
- && (DECL_TYPE_TEMPLATE_P (tmpl)
- || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))))
+ if (identifier_p (tmpl)
+ || (DECL_P (tmpl)
+ && (DECL_TYPE_TEMPLATE_P (tmpl)
+ || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))))
return false;
/* Quickly search for any occurrences of auto; usually there won't
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class50.C
b/gcc/testsuite/g++.dg/cpp2a/nontype-class50.C
new file mode 100644
index 00000000000..1c2786a59e7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class50.C
@@ -0,0 +1,13 @@
+// PR c++/102933
+// { dg-do compile { target c++20 } }
+
+template<class T> struct X { T t; };
+
+template<X> void f();
+
+template<class T>
+void g() {
+ f<X{T{0}}>();
+}
+
+template void g<int>();
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class50a.C
b/gcc/testsuite/g++.dg/cpp2a/nontype-class50a.C
new file mode 100644
index 00000000000..eb8a6ad9375
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class50a.C
@@ -0,0 +1,5 @@
+// PR c++/102933
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fconcepts-ts" }
+
+#include "nontype-class50.C"