summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-01-13 17:38:19 -0500
committerJason Merrill <jason@redhat.com>2020-01-13 20:30:18 -0500
commit8ca4435f431f9b8049ebf102b5659f2d3e7be198 (patch)
tree577caca36cad64bb399b2dd2efec17d348921b36
parentf1ba88b1b20cb579b3b7ce6ce65470205742be7e (diff)
downloadgcc-8ca4435f431f9b8049ebf102b5659f2d3e7be198.tar.gz
PR c++/92582 - ICE with member template as requirement.
Here, we weren't recognizing that the template parameter of A is used by the reference to d in the requires-clause of f. Fixed by passing down the active template parameters in the context of normalization, and adding to the mapping any such parameters shared by a member template used in the constraint-expression. * pt.c (struct find_template_parameter_info): Add ctx_parms. (any_template_parm_r): Handle TEMPLATE_DECL. (find_template_parameters): Take parms instead of their depth. * constraint.cc (build_parameter_mapping): Pass them.
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/constraint.cc9
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/pt.c39
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl3.C12
5 files changed, 57 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 146c28087fb..59646c70fa4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2020-01-13 Jason Merrill <jason@redhat.com>
+ PR c++/92582 - ICE with member template as requirement.
+ * pt.c (struct find_template_parameter_info): Add ctx_parms.
+ (any_template_parm_r): Handle TEMPLATE_DECL.
+ (find_template_parameters): Take parms instead of their depth.
+ * constraint.cc (build_parameter_mapping): Pass them.
+
PR c++/33799 - destroy return value if local cleanup throws.
* cp-tree.h (current_retval_sentinel): New macro.
* decl.c (start_preparsed_function): Set up cleanup for retval.
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 11f58075701..128ab8ae0b2 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -559,12 +559,11 @@ map_arguments (tree parms, tree args)
static tree
build_parameter_mapping (tree expr, tree args, tree decl)
{
- int depth = 0;
+ tree ctx_parms = NULL_TREE;
if (decl)
{
gcc_assert (TREE_CODE (decl) == TEMPLATE_DECL);
- tree parms = DECL_TEMPLATE_PARMS (decl);
- depth = TREE_INT_CST_LOW (TREE_PURPOSE (parms));
+ ctx_parms = DECL_TEMPLATE_PARMS (decl);
}
else if (current_template_parms)
{
@@ -572,10 +571,10 @@ build_parameter_mapping (tree expr, tree args, tree decl)
point of declaration of concepts is currently set after the
initializer, the template parameter lists are not available
when normalizing concept definitions, hence the case above. */
- depth = TMPL_PARMS_DEPTH (current_template_parms);
+ ctx_parms = current_template_parms;
}
- tree parms = find_template_parameters (expr, depth);
+ tree parms = find_template_parameters (expr, ctx_parms);
tree map = map_arguments (parms, args);
return map;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c0f780df685..01fcf663a29 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7865,7 +7865,7 @@ extern bool constraints_satisfied_p (tree, tree);
extern void clear_satisfaction_cache ();
extern bool* lookup_subsumption_result (tree, tree);
extern bool save_subsumption_result (tree, tree, bool);
-extern tree find_template_parameters (tree, int);
+extern tree find_template_parameters (tree, tree);
extern bool equivalent_constraints (tree, tree);
extern bool equivalently_constrained (tree, tree);
extern bool subsumes_constraints (tree, tree);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 29c3aecd831..fa82ecad233 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10364,12 +10364,14 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
struct find_template_parameter_info
{
- explicit find_template_parameter_info (int d)
- : max_depth (d)
+ explicit find_template_parameter_info (tree ctx_parms)
+ : ctx_parms (ctx_parms),
+ max_depth (TMPL_PARMS_DEPTH (ctx_parms))
{}
hash_set<tree> visited;
hash_set<tree> parms;
+ tree ctx_parms;
int max_depth;
};
@@ -10459,6 +10461,29 @@ any_template_parm_r (tree t, void *data)
WALK_SUBTREE (TREE_TYPE (t));
break;
+ case TEMPLATE_DECL:
+ {
+ /* If T is a member template that shares template parameters with
+ ctx_parms, we need to mark all those parameters for mapping. */
+ tree dparms = DECL_TEMPLATE_PARMS (t);
+ tree cparms = ftpi->ctx_parms;
+ while (TMPL_PARMS_DEPTH (dparms) > ftpi->max_depth)
+ dparms = TREE_CHAIN (dparms);
+ while (dparms
+ && (TREE_TYPE (TREE_VALUE (dparms))
+ != TREE_TYPE (TREE_VALUE (cparms))))
+ dparms = TREE_CHAIN (dparms),
+ cparms = TREE_CHAIN (cparms);
+ if (dparms)
+ {
+ int ddepth = TMPL_PARMS_DEPTH (dparms);
+ tree dargs = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (t)));
+ for (int i = 0; i < ddepth; ++i)
+ WALK_SUBTREE (TMPL_ARGS_LEVEL (dargs, i+1));
+ }
+ }
+ break;
+
default:
break;
}
@@ -10467,12 +10492,16 @@ any_template_parm_r (tree t, void *data)
return 0;
}
-/* Returns a list of unique template parameters found within T. */
+/* Returns a list of unique template parameters found within T, where CTX_PARMS
+ are the template parameters in scope. */
tree
-find_template_parameters (tree t, int depth)
+find_template_parameters (tree t, tree ctx_parms)
{
- find_template_parameter_info ftpi (depth);
+ if (!ctx_parms)
+ return NULL_TREE;
+
+ find_template_parameter_info ftpi (ctx_parms);
for_each_template_parm (t, keep_template_parm, &ftpi, &ftpi.visited,
/*include_nondeduced*/true, any_template_parm_r);
tree list = NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl3.C
new file mode 100644
index 00000000000..353937b060c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl3.C
@@ -0,0 +1,12 @@
+// PR c++/92582
+// { dg-do compile { target concepts } }
+
+template <class a, class> concept b = true;
+template <typename> struct A {
+ template <typename c> static constexpr bool d = b<c, int>;
+ template <typename c> static void f(c) requires d<c>;
+};
+int main()
+{
+ A<void>::f(0);
+}