]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Fix bogus error with __integer_pack [PR94490]
authorMarek Polacek <polacek@redhat.com>
Sat, 6 Nov 2021 22:10:39 +0000 (18:10 -0400)
committerMarek Polacek <polacek@redhat.com>
Thu, 2 Dec 2021 13:21:24 +0000 (08:21 -0500)
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.

gcc/cp/pt.c
gcc/testsuite/g++.dg/ext/integer-pack5.C [new file with mode: 0644]

index f4b9d9673fbedceba7be02af09784bd6906b376b..6b560952639f5a2defcec64bc808dac756dabd62 100644 (file)
@@ -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 (file)
index 0000000..8493864
--- /dev/null
@@ -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);