diff options
author | Marek Polacek <polacek@redhat.com> | 2021-11-06 18:10:39 -0400 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2021-12-02 08:21:24 -0500 |
commit | 9af081003f9c19f33457e0ed1aa14a764f462c3c (patch) | |
tree | fea325d5c8cb9d4322953256459aeadc8a5a7b8b | |
parent | cde87638bf5cf6aafffb590986b6a890da0ba06c (diff) | |
download | gcc-9af081003f9c19f33457e0ed1aa14a764f462c3c.zip gcc-9af081003f9c19f33457e0ed1aa14a764f462c3c.tar.gz gcc-9af081003f9c19f33457e0ed1aa14a764f462c3c.tar.bz2 |
c++: Fix bogus error with __integer_pack [PR94490]
Here we issue a bogus:
error: '(0 ? fake_tuple_size_v<int> : fake_tuple_size_v<int>)' is not a constant expression
because cxx_constant_value in expand_integer_pack gets
*(0 ? VIEW_CONVERT_EXPR<const int>(fake_tuple_size_v) : VIEW_CONVERT_EXPR<const int>(fake_tuple_size_v))
which is a REFERENCE_REF_P and we evaluate its operand to 3, so we end
up with *3 and that fails. Sounds like we need to get rid of the
REFERENCE_REF_P then. That is what tsubst_copy_and_build/INDIRECT_REF
will do:
if (REFERENCE_REF_P (t))
{
/* A type conversion to reference type will be enclosed in
such an indirect ref, but the substitution of the cast
will have also added such an indirect ref. */
r = convert_from_reference (r);
}
so I think it's reasonable to call instantiate_non_dependent_expr_sfinae.
PR c++/94490
gcc/cp/ChangeLog:
* pt.c (expand_integer_pack): Call
instantiate_non_dependent_expr_sfinae.
gcc/testsuite/ChangeLog:
* g++.dg/ext/integer-pack5.C: New test.
-rw-r--r-- | gcc/cp/pt.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/integer-pack5.C | 29 |
2 files changed, 30 insertions, 0 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f4b9d96..6b56095 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3792,6 +3792,7 @@ expand_integer_pack (tree call, tree args, tsubst_flags_t complain, } else { + hi = instantiate_non_dependent_expr_sfinae (hi, complain); hi = cxx_constant_value (hi); int len = valid_constant_size_p (hi) ? tree_to_shwi (hi) : -1; diff --git a/gcc/testsuite/g++.dg/ext/integer-pack5.C b/gcc/testsuite/g++.dg/ext/integer-pack5.C new file mode 100644 index 0000000..8493864 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/integer-pack5.C @@ -0,0 +1,29 @@ +// PR c++/94490 +// { dg-do compile { target c++14 } } + +template<class T> +constexpr int fake_tuple_size_v = 3; +template<int...> struct intseq {}; + +// So that it compiles with clang++. +#if __has_builtin(__make_integer_seq) +using size_t = decltype(sizeof(1)); +template<typename, size_t... _Indices> +using _IdxTuple = intseq<_Indices...>; + +template<int N> using genseq = __make_integer_seq<_IdxTuple, size_t, N>; +#else +template<int N> using genseq = intseq<__integer_pack(N)...>; +#endif + +template<int A, class S = genseq<0 ? A : A>> +struct arith_result +{ }; + +template<typename T> +auto Mul(const T&) +{ + return [](auto) { return arith_result<fake_tuple_size_v<T>> { }; }(0); +} + +auto x = Mul(0); |