aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2021-11-06 18:10:39 -0400
committerMarek Polacek <polacek@redhat.com>2021-12-02 08:21:24 -0500
commit9af081003f9c19f33457e0ed1aa14a764f462c3c (patch)
treefea325d5c8cb9d4322953256459aeadc8a5a7b8b
parentcde87638bf5cf6aafffb590986b6a890da0ba06c (diff)
downloadgcc-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.c1
-rw-r--r--gcc/testsuite/g++.dg/ext/integer-pack5.C29
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);