C++ PATCH to fix an ICE on invalid with OVERLOADs (PR c++/84854)

Jason Merrill jason@redhat.com
Thu Mar 15 14:07:00 GMT 2018


On Thu, Mar 15, 2018 at 7:49 AM, Marek Polacek <polacek@redhat.com> wrote:
> On Wed, Mar 14, 2018 at 02:06:36PM -0400, Jason Merrill wrote:
>> On Wed, Mar 14, 2018 at 11:59 AM, Marek Polacek <polacek@redhat.com> wrote:
>> > cxx_constant_value doesn't understand template codes, and neither it
>> > understands OVERLOADs, so if we pass an OVERLOAD to it, we crash.  Here
>> > instantiate_non_dependent_expr got an OVERLOAD, but since it calls
>> > is_nondependent_constant_expression which checks type_unknown_p, it left the
>> > expression as it was.  We can't use is_nondependent_constant_expression in
>> > finish_if_stmt_cond because i_n_c_e checks is_constant_expression and that is
>> > not suitable here; we'd miss diagnostics.  So I did the following; I think we
>> > should reject the testcase with an error.
>> >
>> > Bootstrapped/regtested on x86_64-linux, ok for trunk?
>> >
>> > 2018-03-14  Marek Polacek  <polacek@redhat.com>
>> >
>> >         PR c++/84854
>> >         * semantics.c (finish_if_stmt_cond): Give error if the condition
>> >         is an overloaded function with no contextual type information.
>> >
>> >         * g++.dg/cpp1z/constexpr-if15.C: New test.
>> >
>> > diff --git gcc/cp/semantics.c gcc/cp/semantics.c
>> > index fdf37bea770..a056e9445e9 100644
>> > --- gcc/cp/semantics.c
>> > +++ gcc/cp/semantics.c
>> > @@ -735,8 +735,16 @@ finish_if_stmt_cond (tree cond, tree if_stmt)
>> >        && require_constant_expression (cond)
>> >        && !value_dependent_expression_p (cond))
>> >      {
>> > -      cond = instantiate_non_dependent_expr (cond);
>> > -      cond = cxx_constant_value (cond, NULL_TREE);
>> > +      if (type_unknown_p (cond))
>> > +       {
>> > +         cxx_incomplete_type_error (cond, TREE_TYPE (cond));
>> > +         cond = error_mark_node;
>>
>> I think I'd prefer to skip this block when type_unknown_p, and leave
>> error handling up to the code shared with regular if.
>
> Like this?

Yes, thanks.

> It was my first version, but I thought we wanted the error;

Getting an error is an improvement, but it should apply to
non-constexpr if as well, so checking in maybe_convert_cond would be
better.  Actually, if we deal with unknown type there, we shouldn't
need this patch at all.

...except I also notice that since maybe_convert_cond doesn't do any
conversion in a template, we're trying to extract the constant value
without first converting to bool, which breaks this testcase:

struct A
{
  constexpr operator bool () { return true; }
  int i;
};

A a;

template <class T> void f()
{
  constexpr bool b = a;  // works
  if constexpr (a) { }   // breaks
}

int main()
{
  f<int>();
}

A simple fix would be to replace your type_unknown_p check here with a
comparison to boolean_type_node, so we wait until instantiation time
to require a constant value.

Better would be to actually do the conversion.  Perhaps this could
share code (for converting and getting a constant value) with
finish_static_assert.

Jason



More information about the Gcc-patches mailing list