diff options
author | Nathan Sidwell <nathan@acm.org> | 2020-02-27 10:50:36 -0800 |
---|---|---|
committer | Nathan Sidwell <nathan@acm.org> | 2020-02-27 10:50:36 -0800 |
commit | 9d2d283367a407c1ba9ecdb8590f9295828e25f8 (patch) | |
tree | 670766297b077469d190cbf4fad93b2c4191d4c2 | |
parent | ba49e9eb18730cc71e5ffc302092f87ef6821f24 (diff) | |
download | gcc-9d2d283367a407c1ba9ecdb8590f9295828e25f8.zip gcc-9d2d283367a407c1ba9ecdb8590f9295828e25f8.tar.gz gcc-9d2d283367a407c1ba9ecdb8590f9295828e25f8.tar.bz2 |
Compare ARGUMENT_PACKS [pr93933]
This implements Jason's suggested approach: 'I'd think that the bug is
that we're treating them as types in the first place; they aren't
types, so they shouldn't reach comptypes. I'd lean toward adding an
assert to that effect and fixing the caller to use
e.g. template_args_equal.'
PR c++/93933
* pt.c (template_args_equal): Pass ARGUMENT_PACKS through to
cp_tree_equal.
* tree.c (cp_tree_equal): Compare ARGUMENT_PACKS here,
* typeck.c (comptypes): Assert we don't get any argument packs.
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/pt.c | 21 | ||||
-rw-r--r-- | gcc/cp/tree.c | 17 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/concepts/pr93933.C | 31 |
5 files changed, 59 insertions, 20 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5e9eeec..22fe803 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2020-02-27 Nathan Sidwell <nathan@acm.org> + PR c++/93933 + * pt.c (template_args_equal): Pass ARGUMENT_PACKS through to + cp_tree_equal. + * tree.c (cp_tree_equal): Compare ARGUMENT_PACKS here, + * typeck.c (comptypes): Assert we don't get any argument packs. + * class.c (adjust_clone_args): Correct arg-checking assert. * typeck.c (comptypes): Assert not nulls. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6c9abb8..622c70b 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8999,25 +8999,8 @@ template_args_equal (tree ot, tree nt, bool partial_order /* = false */) PACK_EXPANSION_PATTERN (nt)) && template_args_equal (PACK_EXPANSION_EXTRA_ARGS (ot), PACK_EXPANSION_EXTRA_ARGS (nt))); - else if (ARGUMENT_PACK_P (ot)) - { - int i, len; - tree opack, npack; - - if (!ARGUMENT_PACK_P (nt)) - return 0; - - opack = ARGUMENT_PACK_ARGS (ot); - npack = ARGUMENT_PACK_ARGS (nt); - len = TREE_VEC_LENGTH (opack); - if (TREE_VEC_LENGTH (npack) != len) - return 0; - for (i = 0; i < len; ++i) - if (!template_args_equal (TREE_VEC_ELT (opack, i), - TREE_VEC_ELT (npack, i))) - return 0; - return 1; - } + else if (ARGUMENT_PACK_P (ot) || ARGUMENT_PACK_P (nt)) + return cp_tree_equal (ot, nt); else if (ot && TREE_CODE (ot) == ARGUMENT_PACK_SELECT) gcc_unreachable (); else if (TYPE_P (nt)) diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 72b3a72..3fc6287 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -3857,12 +3857,27 @@ cp_tree_equal (tree t1, tree t2) DEFERRED_NOEXCEPT_PATTERN (t2)) && comp_template_args (DEFERRED_NOEXCEPT_ARGS (t1), DEFERRED_NOEXCEPT_ARGS (t2))); - break; case LAMBDA_EXPR: /* Two lambda-expressions are never considered equivalent. */ return false; + case TYPE_ARGUMENT_PACK: + case NONTYPE_ARGUMENT_PACK: + { + tree p1 = ARGUMENT_PACK_ARGS (t1); + tree p2 = ARGUMENT_PACK_ARGS (t2); + int len = TREE_VEC_LENGTH (p1); + if (TREE_VEC_LENGTH (p2) != len) + return false; + + for (int ix = 0; ix != len; ix++) + if (!template_args_equal (TREE_VEC_ELT (p1, ix), + TREE_VEC_ELT (p2, ix))) + return false; + return true; + } + default: break; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 42d0b47..2a3243f 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1485,6 +1485,10 @@ comptypes (tree t1, tree t2, int strict) { gcc_checking_assert (t1 && t2); + /* TYPE_ARGUMENT_PACKS are not really types. */ + gcc_checking_assert (TREE_CODE (t1) != TYPE_ARGUMENT_PACK + && TREE_CODE (t2) != TYPE_ARGUMENT_PACK); + if (strict == COMPARE_STRICT && comparing_specializations && (t1 != TYPE_CANONICAL (t1) || t2 != TYPE_CANONICAL (t2))) /* If comparing_specializations, treat dependent aliases as distinct. */ diff --git a/gcc/testsuite/g++.dg/concepts/pr93933.C b/gcc/testsuite/g++.dg/concepts/pr93933.C new file mode 100644 index 0000000..b4f2c36 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/pr93933.C @@ -0,0 +1,31 @@ +// { dg-do compile { target c++17 } } +// { dg-options "-fconcepts" } + +// distilled from <concepts>, via header units + +template<typename _ArgTypes> +struct is_invocable; + +template<typename... _Args> +concept invocable = is_invocable<_Args...>::value; + +template<typename _Is> +requires invocable<_Is> +class BUG; + +template<typename _Is> +requires invocable<_Is> +class BUG {}; // { dg-bogus "different constraints" } + +template<int> struct is_invocable_NT; + +template<int... Ints> +concept invocable_NT = is_invocable_NT<Ints...>::value; + +template<int _Is> +requires invocable_NT<_Is> +class BUG_NT; + +template<int _Is> +requires invocable_NT<_Is> +class BUG_NT {}; |