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? 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 -- 2.33.1