Message ID | 010201921005af84-94b13c14-e527-438d-bcd9-437f012338aa-000000@eu-west-1.amazonses.com |
---|---|
State | New |
Headers | show |
Series | c++: Don't ICE due to artificial constructor parameters [PR116722] | expand |
On 9/20/24 5:21 PM, Simon Martin wrote: > The following code triggers an ICE > > === cut here === > class base {}; > class derived : virtual public base { > public: > template<typename Arg> constexpr derived(Arg) {} > }; > int main() { > derived obj(1.); > } > === cut here === > > The problem is that cxx_bind_parameters_in_call ends up attempting to > convert a REAL_CST (the first non artificial parameter) to INTEGER_TYPE > (the type of the __in_chrg parameter), which ICEs. > > This patch teaches cxx_bind_parameters_in_call to handle the __in_chrg > and __vtt_parm parameters that {con,de}structors might have. > > Note that in the test case, the constructor is not constexpr-suitable, > however it's OK since it's a template according to my read of paragraph > (3) of [dcl.constexpr]. Agreed. It looks like your patch doesn't correct the mismatching of arguments to parameters that you describe, but at least for now it should be enough to set *non_constant_p and return if we see a VTT or in-charge parameter. > Successfully tested on x86_64-pc-linux-gnu. > > PR c++/116722 > > gcc/cp/ChangeLog: > > * constexpr.cc (cxx_bind_parameters_in_call): Leave artificial > constructor parameters as is. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp0x/constexpr-ctor22.C: New test. > > --- > gcc/cp/constexpr.cc | 10 +++++++++- > gcc/testsuite/g++.dg/cpp0x/constexpr-ctor22.C | 15 +++++++++++++++ > 2 files changed, 24 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-ctor22.C > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc > index f6fd059be46..815f93b1d47 100644 > --- a/gcc/cp/constexpr.cc > +++ b/gcc/cp/constexpr.cc > @@ -1871,13 +1871,21 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, > x = get_nth_callarg (t, i); > /* For member function, the first argument is a pointer to the implied > object. For a constructor, it might still be a dummy object, in > - which case we get the real argument from ctx. */ > + which case we get the real argument from ctx. */ > if (i == 0 && DECL_CONSTRUCTOR_P (fun) > && is_dummy_object (x)) > { > x = ctx->object; > x = build_address (x); > } > + /* Leave the __in_chrg and __vtt_parm parameters of *structors of classes > + with virtual bases as is. */ > + if ((i == 1 && DECL_HAS_IN_CHARGE_PARM_P (fun)) > + || (i == 2 && DECL_HAS_VTT_PARM_P (fun))) > + { > + TREE_VEC_ELT (binds, i) = arg; > + continue; > + } > if (TREE_ADDRESSABLE (type)) > { > /* Undo convert_for_arg_passing work here. */ > diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor22.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor22.C > new file mode 100644 > index 00000000000..279f6ec4454 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor22.C > @@ -0,0 +1,15 @@ > +// PR c++/116722 > +// We're now accepting this in spite of the virtual base class. This is OK > +// according to [dcl.constexpr] 3: "Except for instantiated constexpr functions > +// non-templated constexpr functions shall be constexpr-suitable". > +// { dg-do compile { target c++11 } } > + > +class base {}; > +class derived : virtual public base { > +public: > + template<typename Arg> > + constexpr derived(Arg) {} > +}; > +int main() { > + derived obj(1.); > +}
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index f6fd059be46..815f93b1d47 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -1871,13 +1871,21 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, x = get_nth_callarg (t, i); /* For member function, the first argument is a pointer to the implied object. For a constructor, it might still be a dummy object, in - which case we get the real argument from ctx. */ + which case we get the real argument from ctx. */ if (i == 0 && DECL_CONSTRUCTOR_P (fun) && is_dummy_object (x)) { x = ctx->object; x = build_address (x); } + /* Leave the __in_chrg and __vtt_parm parameters of *structors of classes + with virtual bases as is. */ + if ((i == 1 && DECL_HAS_IN_CHARGE_PARM_P (fun)) + || (i == 2 && DECL_HAS_VTT_PARM_P (fun))) + { + TREE_VEC_ELT (binds, i) = arg; + continue; + } if (TREE_ADDRESSABLE (type)) { /* Undo convert_for_arg_passing work here. */ diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor22.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor22.C new file mode 100644 index 00000000000..279f6ec4454 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor22.C @@ -0,0 +1,15 @@ +// PR c++/116722 +// We're now accepting this in spite of the virtual base class. This is OK +// according to [dcl.constexpr] 3: "Except for instantiated constexpr functions +// non-templated constexpr functions shall be constexpr-suitable". +// { dg-do compile { target c++11 } } + +class base {}; +class derived : virtual public base { +public: + template<typename Arg> + constexpr derived(Arg) {} +}; +int main() { + derived obj(1.); +}