aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-05-15 14:06:48 -0400
committerJason Merrill <jason@redhat.com>2020-05-15 14:06:57 -0400
commitcda6396a1b6e6bba2a3b0847931567c3458f2184 (patch)
tree0886bfbae0e65f66cf1fa84dae41a69a1e0a11d1 /gcc
parent4c1a5d8b71e29b71e0bc1004480c12c5fc427cb7 (diff)
downloadgcc-cda6396a1b6e6bba2a3b0847931567c3458f2184.zip
gcc-cda6396a1b6e6bba2a3b0847931567c3458f2184.tar.gz
gcc-cda6396a1b6e6bba2a3b0847931567c3458f2184.tar.bz2
PR c++/93286 - ICE with __is_constructible and variadic template.
My GCC 10 patch for 93286 fixed the missing piece in tsubst's handling of lists vs. that in tsubst_copy_and_build, but it would be better to share the code between them. gcc/cp/ChangeLog 2020-05-15 Jason Merrill <jason@redhat.com> PR c++/93286 - ICE with __is_constructible and variadic template. * pt.c (tsubst_tree_list): New. (tsubst, tsubst_copy_and_build): Use it. * decl2.c (is_late_template_attribute): Handle error_mark_node args.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl2.c3
-rw-r--r--gcc/cp/pt.c272
4 files changed, 101 insertions, 183 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 37705f9..732be07 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2020-05-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/93286 - ICE with __is_constructible and variadic template.
+ * pt.c (tsubst_tree_list): New.
+ (tsubst, tsubst_copy_and_build): Use it.
+ * decl2.c (is_late_template_attribute): Handle error_mark_node args.
+
2020-05-15 Nathan Sidwell <nathan@acm.org>
* pt.c (template_args_equal): Fix thinkos in previous 'cleanup'.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 827b03d..3f7ded4 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6953,7 +6953,7 @@ extern tree tsubst_default_argument (tree, int, tree, tree,
tsubst_flags_t);
extern tree tsubst (tree, tree, tsubst_flags_t, tree);
extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t,
- tree, bool, bool);
+ tree, bool = false, bool = false);
extern tree tsubst_expr (tree, tree, tsubst_flags_t,
tree, bool);
extern tree tsubst_pack_expansion (tree, tree, tsubst_flags_t, tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 4767d53..449c86c 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1173,6 +1173,9 @@ is_late_template_attribute (tree attr, tree decl)
&& is_attribute_p ("omp declare simd", name))
return true;
+ if (args == error_mark_node)
+ return false;
+
/* An attribute pack is clearly dependent. */
if (args && PACK_EXPANSION_P (args))
return true;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bfeeebc..cad5b21 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15044,6 +15044,94 @@ tsubst_exception_specification (tree fntype,
return new_specs;
}
+/* Substitute through a TREE_LIST of types or expressions, handling pack
+ expansions. */
+
+tree
+tsubst_tree_list (tree t, tree args, tsubst_flags_t complain, tree in_decl)
+{
+ if (t == void_list_node)
+ return t;
+
+ tree purpose = TREE_PURPOSE (t);
+ tree purposevec = NULL_TREE;
+ if (!purpose)
+ ;
+ else if (PACK_EXPANSION_P (purpose))
+ {
+ purpose = tsubst_pack_expansion (purpose, args, complain, in_decl);
+ if (TREE_CODE (purpose) == TREE_VEC)
+ purposevec = purpose;
+ }
+ else if (TYPE_P (purpose))
+ purpose = tsubst (purpose, args, complain, in_decl);
+ else
+ purpose = tsubst_copy_and_build (purpose, args, complain, in_decl);
+ if (purpose == error_mark_node || purposevec == error_mark_node)
+ return error_mark_node;
+
+ tree value = TREE_VALUE (t);
+ tree valuevec = NULL_TREE;
+ if (!value)
+ ;
+ else if (PACK_EXPANSION_P (value))
+ {
+ value = tsubst_pack_expansion (value, args, complain, in_decl);
+ if (TREE_CODE (value) == TREE_VEC)
+ valuevec = value;
+ }
+ else if (TYPE_P (value))
+ value = tsubst (value, args, complain, in_decl);
+ else
+ value = tsubst_copy_and_build (value, args, complain, in_decl);
+ if (value == error_mark_node || valuevec == error_mark_node)
+ return error_mark_node;
+
+ tree chain = TREE_CHAIN (t);
+ if (!chain)
+ ;
+ else if (TREE_CODE (chain) == TREE_LIST)
+ chain = tsubst_tree_list (chain, args, complain, in_decl);
+ else if (TYPE_P (chain))
+ chain = tsubst (chain, args, complain, in_decl);
+ else
+ chain = tsubst_copy_and_build (chain, args, complain, in_decl);
+ if (chain == error_mark_node)
+ return error_mark_node;
+
+ if (purpose == TREE_PURPOSE (t)
+ && value == TREE_VALUE (t)
+ && chain == TREE_CHAIN (t))
+ return t;
+
+ int len;
+ /* Determine the number of arguments. */
+ if (purposevec)
+ {
+ len = TREE_VEC_LENGTH (purposevec);
+ gcc_assert (!valuevec || len == TREE_VEC_LENGTH (valuevec));
+ }
+ else if (valuevec)
+ len = TREE_VEC_LENGTH (valuevec);
+ else
+ len = 1;
+
+ for (int i = len; i-- > 0; )
+ {
+ if (purposevec)
+ purpose = TREE_VEC_ELT (purposevec, i);
+ if (valuevec)
+ value = TREE_VEC_ELT (valuevec, i);
+
+ if (value && TYPE_P (value))
+ chain = hash_tree_cons (purpose, value, chain);
+ else
+ chain = tree_cons (purpose, value, chain);
+ }
+
+ return chain;
+}
+
/* Take the tree structure T and replace template parameters used
therein with the argument vector ARGS. IN_DECL is an associated
decl for diagnostics. If an error occurs, returns ERROR_MARK_NODE.
@@ -15463,104 +15551,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
case TREE_LIST:
- {
- tree purpose, value, chain;
-
- if (t == void_list_node)
- return t;
-
- if ((TREE_PURPOSE (t) && PACK_EXPANSION_P (TREE_PURPOSE (t)))
- || (TREE_VALUE (t) && PACK_EXPANSION_P (TREE_VALUE (t))))
- {
- /* We have pack expansions, so expand those and
- create a new list out of it. */
-
- /* Expand the argument expressions. */
- tree purposevec = NULL_TREE;
- if (TREE_PURPOSE (t))
- purposevec = tsubst_pack_expansion (TREE_PURPOSE (t), args,
- complain, in_decl);
- if (purposevec == error_mark_node)
- return error_mark_node;
-
- tree valuevec = NULL_TREE;
- if (TREE_VALUE (t))
- valuevec = tsubst_pack_expansion (TREE_VALUE (t), args,
- complain, in_decl);
- if (valuevec == error_mark_node)
- return error_mark_node;
-
- /* Build the rest of the list. */
- tree chain = TREE_CHAIN (t);
- if (chain && chain != void_type_node)
- chain = tsubst (chain, args, complain, in_decl);
- if (chain == error_mark_node)
- return error_mark_node;
-
- /* Determine the number of arguments. */
- int len = -1;
- if (purposevec && TREE_CODE (purposevec) == TREE_VEC)
- {
- len = TREE_VEC_LENGTH (purposevec);
- gcc_assert (!valuevec || len == TREE_VEC_LENGTH (valuevec));
- }
- else if (TREE_CODE (valuevec) == TREE_VEC)
- len = TREE_VEC_LENGTH (valuevec);
- else
- {
- /* Since we only performed a partial substitution into
- the argument pack, we only RETURN (a single list
- node. */
- if (purposevec == TREE_PURPOSE (t)
- && valuevec == TREE_VALUE (t)
- && chain == TREE_CHAIN (t))
- return t;
-
- return tree_cons (purposevec, valuevec, chain);
- }
-
- /* Convert the argument vectors into a TREE_LIST. */
- for (int i = len; i-- > 0; )
- {
- purpose = (purposevec ? TREE_VEC_ELT (purposevec, i)
- : NULL_TREE);
- value = (valuevec ? TREE_VEC_ELT (valuevec, i)
- : NULL_TREE);
-
- /* Build the list (backwards). */
- chain = hash_tree_cons (purpose, value, chain);
- }
-
- return chain;
- }
-
- purpose = TREE_PURPOSE (t);
- if (purpose)
- {
- purpose = tsubst (purpose, args, complain, in_decl);
- if (purpose == error_mark_node)
- return error_mark_node;
- }
- value = TREE_VALUE (t);
- if (value)
- {
- value = tsubst (value, args, complain, in_decl);
- if (value == error_mark_node)
- return error_mark_node;
- }
- chain = TREE_CHAIN (t);
- if (chain && chain != void_type_node)
- {
- chain = tsubst (chain, args, complain, in_decl);
- if (chain == error_mark_node)
- return error_mark_node;
- }
- if (purpose == TREE_PURPOSE (t)
- && value == TREE_VALUE (t)
- && chain == TREE_CHAIN (t))
- return t;
- return hash_tree_cons (purpose, value, chain);
- }
+ return tsubst_tree_list (t, args, complain, in_decl);
case TREE_BINFO:
/* We should never be tsubsting a binfo. */
@@ -20078,90 +20069,7 @@ tsubst_copy_and_build (tree t,
}
case TREE_LIST:
- {
- tree purpose, value, chain;
-
- if (t == void_list_node)
- RETURN (t);
-
- if ((TREE_PURPOSE (t) && PACK_EXPANSION_P (TREE_PURPOSE (t)))
- || (TREE_VALUE (t) && PACK_EXPANSION_P (TREE_VALUE (t))))
- {
- /* We have pack expansions, so expand those and
- create a new list out of it. */
- tree purposevec = NULL_TREE;
- tree valuevec = NULL_TREE;
- tree chain;
- int i, len = -1;
-
- /* Expand the argument expressions. */
- if (TREE_PURPOSE (t))
- purposevec = tsubst_pack_expansion (TREE_PURPOSE (t), args,
- complain, in_decl);
- if (TREE_VALUE (t))
- valuevec = tsubst_pack_expansion (TREE_VALUE (t), args,
- complain, in_decl);
-
- /* Build the rest of the list. */
- chain = TREE_CHAIN (t);
- if (chain && chain != void_type_node)
- chain = RECUR (chain);
-
- /* Determine the number of arguments. */
- if (purposevec && TREE_CODE (purposevec) == TREE_VEC)
- {
- len = TREE_VEC_LENGTH (purposevec);
- gcc_assert (!valuevec || len == TREE_VEC_LENGTH (valuevec));
- }
- else if (TREE_CODE (valuevec) == TREE_VEC)
- len = TREE_VEC_LENGTH (valuevec);
- else
- {
- /* Since we only performed a partial substitution into
- the argument pack, we only RETURN (a single list
- node. */
- if (purposevec == TREE_PURPOSE (t)
- && valuevec == TREE_VALUE (t)
- && chain == TREE_CHAIN (t))
- RETURN (t);
-
- RETURN (tree_cons (purposevec, valuevec, chain));
- }
-
- /* Convert the argument vectors into a TREE_LIST */
- i = len;
- while (i > 0)
- {
- /* Grab the Ith values. */
- i--;
- purpose = purposevec ? TREE_VEC_ELT (purposevec, i)
- : NULL_TREE;
- value
- = valuevec ? convert_from_reference (TREE_VEC_ELT (valuevec, i))
- : NULL_TREE;
-
- /* Build the list (backwards). */
- chain = tree_cons (purpose, value, chain);
- }
-
- RETURN (chain);
- }
-
- purpose = TREE_PURPOSE (t);
- if (purpose)
- purpose = RECUR (purpose);
- value = TREE_VALUE (t);
- if (value)
- value = RECUR (value);
- chain = TREE_CHAIN (t);
- if (chain && chain != void_type_node)
- chain = RECUR (chain);
- if (purpose == TREE_PURPOSE (t)
- && value == TREE_VALUE (t)
- && chain == TREE_CHAIN (t))
- RETURN (t);
- RETURN (tree_cons (purpose, value, chain));
- }
+ RETURN (tsubst_tree_list (t, args, complain, in_decl));
case COMPONENT_REF:
{