On Tue, Sep 12, 2023 at 01:34:43PM -0400, Marek Polacek via Gcc-patches wrote: > On Tue, Sep 12, 2023 at 01:27:44PM -0400, Jason Merrill via Gcc-patches wrote: > > Tested x86_64-pc-linux-gnu, applying to trunk. > > > > -- 8< -- > > > > The argument might not already be an integer. > > > > PR c++/111357 > > > > gcc/cp/ChangeLog: > > > > * pt.cc (expand_integer_pack): Convert argument to int. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/ext/integer-pack7.C: New test. > > --- > > gcc/cp/pt.cc | 2 ++ > > gcc/testsuite/g++.dg/ext/integer-pack7.C | 38 ++++++++++++++++++++++++ > > 2 files changed, 40 insertions(+) > > create mode 100644 gcc/testsuite/g++.dg/ext/integer-pack7.C > > > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > > index 838179d5fe3..b583c11eb99 100644 > > --- a/gcc/cp/pt.cc > > +++ b/gcc/cp/pt.cc > > @@ -3793,6 +3793,8 @@ expand_integer_pack (tree call, tree args, > > tsubst_flags_t complain, > > } > > else > > { > > + hi = perform_implicit_conversion_flags (integer_type_node, hi, > > complain, > > + LOOKUP_IMPLICIT); > > FWIW, we have perform_implicit_conversion for this.
Is it correct to convert exactly to integer_type_node though? Consider #include <utility> using std::integer_sequence; using std::make_integer_sequence; template<long... V> void g(integer_sequence<long,V...>) {} template<typename ...T> struct c1 { static constexpr int value = 1; constexpr operator int() { return value; } constexpr operator long() { return value + 1; } }; template<typename T> struct R { using S = make_integer_sequence<long,c1<T>{}>; R() noexcept(noexcept(g(S()))) {} }; int main() { R<int>(); } Shouldn't that invoke c1<T>{}.operator long() rather than operator int()? I thought the conversion was supposed to be done a few lines earlier, instead of doing CALL_EXPR_ARG (call, 0) = hi; do CALL_EXPR_ARG (call, 0) = perform_implicit_conversion_flags (TREE_TYPE (ohi), hi, complain, LOOKUP_IMPLICIT); or tsubst that TREE_TYPE (ohi) as well? I.e. convert to type of the template parameter. Jakub