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


Reply via email to