On 12/1/21 12:22, Marek Polacek wrote:
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.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11?
OK.
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.
---
gcc/cp/pt.c | 1 +
gcc/testsuite/g++.dg/ext/integer-pack5.C | 29 ++++++++++++++++++++++++
2 files changed, 30 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/ext/integer-pack5.C
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f4b9d9673fb..6b560952639 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 00000000000..84938649d31
--- /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);
base-commit: 54ebec35abec09a24b47b997172622ca0d8e2318