On 2/8/21 2:03 PM, Patrick Palka wrote:
The subsequent patches revealed some latent type canonicalization
issues during normalization and satisfaction:
1. In tsubst_parameter_mapping, we're canonicalizing the arguments of a
TYPE_ARGUMENT_PACK only if 'arg' wasn't a TYPE_ARGUMENT_PACK to begin
with.
2. We currently set DECL_CONTEXT and CONSTRAINT_VAR_P on each of the
parameters introduced in a requires-expression _after_ we're done
processing the requirements. But meanwhile we may have already
computed the canonical form of a type that depends on one of these
PARM_DECLs, which depends on the result of cp_tree_equal, which
depends on CONSTRAINT_VAR_P and DECL_CONTEXT. So we must set these
fields earlier, before processing the requirements.
3. In do_auto_deduction, we use the result of finish_decltype_type later
as a template argument, so we should canonicalize the result too.
(While we're here, we should pass 'complain' to finish_decltype_type,
which fixes the testcase auto1.C below.)
gcc/cp/ChangeLog:
* constraint.cc (tsubst_parameter_mapping): Canonicalize the
arguments of a TYPE_ARGUMENT_PACK even if we've started with a
TYPE_ARGUMENT_PACK.
(finish_requires_expr): Don't set DECL_CONTEXT and
CONSTRAINT_VAR_P on each of the introduced parameters here.
* parser.c (cp_parser_requirement_parameter_list): Instead set
these fields earlier, here.
gcc/testsuite/ChangeLog:
* g++.dg/cpp1z/auto1.C: New test.
---
gcc/cp/constraint.cc | 25 ++++++++-----------------
gcc/cp/parser.c | 12 ++++++++++++
gcc/cp/pt.c | 8 ++++++--
gcc/testsuite/g++.dg/cpp1z/auto1.C | 13 +++++++++++++
4 files changed, 39 insertions(+), 19 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp1z/auto1.C
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 3e599fe8c47..39c97986082 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2319,15 +2319,15 @@ tsubst_parameter_mapping (tree map, tree args,
subst_info info)
new_arg = tsubst_template_arg (arg, args, complain, in_decl);
if (TYPE_P (new_arg))
new_arg = canonicalize_type_argument (new_arg, complain);
- if (TREE_CODE (new_arg) == TYPE_ARGUMENT_PACK)
+ }
+ if (TREE_CODE (new_arg) == TYPE_ARGUMENT_PACK)
+ {
+ tree pack_args = ARGUMENT_PACK_ARGS (new_arg);
+ for (int i = 0; i < TREE_VEC_LENGTH (pack_args); i++)
{
- tree pack_args = ARGUMENT_PACK_ARGS (new_arg);
- for (int i = 0; i < TREE_VEC_LENGTH (pack_args); i++)
- {
- tree& pack_arg = TREE_VEC_ELT (pack_args, i);
- if (TYPE_P (pack_arg))
- pack_arg = canonicalize_type_argument (pack_arg, complain);
- }
+ tree& pack_arg = TREE_VEC_ELT (pack_args, i);
+ if (TYPE_P (pack_arg))
+ pack_arg = canonicalize_type_argument (pack_arg, complain);
}
}
if (new_arg == error_mark_node)
@@ -3253,15 +3253,6 @@ evaluate_concept_check (tree check, tsubst_flags_t
complain)
tree
finish_requires_expr (location_t loc, tree parms, tree reqs)
{
- /* Modify the declared parameters by removing their context
- so they don't refer to the enclosing scope and explicitly
- indicating that they are constraint variables. */
- for (tree parm = parms; parm; parm = DECL_CHAIN (parm))
- {
- DECL_CONTEXT (parm) = NULL_TREE;
- CONSTRAINT_VAR_P (parm) = true;
- }
-
/* Build the node. */
tree r = build_min (REQUIRES_EXPR, boolean_type_node, parms, reqs,
NULL_TREE);
TREE_SIDE_EFFECTS (r) = false;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 5da8670f0e2..fef10b9661d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -28779,6 +28779,18 @@ cp_parser_requirement_parameter_list (cp_parser
*parser)
if (!parens.require_close (parser))
return error_mark_node;
+ /* Modify the declared parameters by removing their context
+ so they don't refer to the enclosing scope and explicitly
+ indicating that they are constraint variables. */
+ for (tree parm = parms; parm; parm = TREE_CHAIN (parm))
+ {
+ if (parm == void_list_node || parm == explicit_void_list_node)
+ break;
+ tree decl = TREE_VALUE (parm);
+ DECL_CONTEXT (decl) = NULL_TREE;
+ CONSTRAINT_VAR_P (decl) = true;
+ }
+
return parms;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3605b67e424..bceb942e79a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -29478,9 +29478,13 @@ do_auto_deduction (tree type, tree init, tree
auto_node,
|| ((TREE_CODE (init) == COMPONENT_REF
|| TREE_CODE (init) == SCOPE_REF)
&& !REF_PARENTHESIZED_P (init)));
+ tree deduced = finish_decltype_type (init, id, complain);
+ deduced = canonicalize_type_argument (deduced, complain);
+ if (deduced == error_mark_node)
+ return error_mark_node;
targs = make_tree_vec (1);
- TREE_VEC_ELT (targs, 0)
- = finish_decltype_type (init, id, tf_warning_or_error);
+ TREE_VEC_ELT (targs, 0) = deduced;
+ /* FIXME: These errors ought to be diagnosed at parse time. */
Perhaps in grokdeclarator.
The patch is OK.
if (type != auto_node)
{
if (complain & tf_error)
diff --git a/gcc/testsuite/g++.dg/cpp1z/auto1.C
b/gcc/testsuite/g++.dg/cpp1z/auto1.C
new file mode 100644
index 00000000000..5cc762a386e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/auto1.C
@@ -0,0 +1,13 @@
+// Verify that deduction failure of the decltype(auto) template parameter is
+// a SFINAE error.
+// { dg-do compile { target c++17 } }
+
+template <class> void f();
+template <class> void f(int);
+
+template <class T = int, decltype(auto) = &f<T>> void g();
+template <class = int> void g();
+
+int main() {
+ g();
+}